• 3.1
  • 3.2
  • 6.1
  • Версия документации: 5.0

Примечания к выпуску Django 1.6.3

21 апреля 2014 г.

Django 1.6.3 исправляет несколько ошибок версии 1.6.2, включая три проблемы безопасности, и вносит одно обратно несовместимое изменение:

Неожиданное выполнение кода с использованием reverse()

Обработка URL-адресов в Django основана на сопоставлении шаблонов регулярных выражений (представляющих URL-адреса) с вызываемыми представлениями, а собственная обработка Django состоит из сопоставления запрошенного URL-адреса с этими шаблонами для определения подходящего представления для вызова.

Django также предоставляет удобную функцию reverse(), которая выполняет этот процесс в противоположном направлении. Функция reverse() принимает информацию о представлении и возвращает URL-адрес, который будет вызывать это представление. Разработчикам приложений рекомендуется использовать функцию reverse(), поскольку выходные данные функции reverse() всегда основаны на текущих шаблонах URL-адресов, а это означает, что разработчикам не нужно менять другой код при внесении изменений в URL-адреса.

Одна из сигнатур аргумента для reverse() — это передача пути Python, обозначенного точками, к желаемому представлению. В этой ситуации Django импортирует модуль, указанный этим пунктирным путем, как часть создания результирующего URL-адреса. Если у такого модуля есть побочные эффекты во время импорта, эти побочные эффекты возникнут.

Таким образом, злоумышленник может вызвать неожиданное выполнение кода при следующих условиях:

  1. Присутствует одно или несколько представлений, которые создают URL-адрес на основе пользовательского ввода (обычно это параметр «следующий» в строке запроса, указывающий, куда перенаправить после успешного завершения действия).

  2. Злоумышленнику известно, что на пути импорта Python на сервере существуют один или несколько модулей, которые выполняют выполнение кода с побочными эффектами при импорте.

Чтобы исправить это, reverse() теперь будет принимать и импортировать только пунктирные пути на основе модулей, содержащих представление, перечисленных в Конфигурации шаблона URL-адреса проекта, чтобы гарантировать, что только те модули, которые разработчик намеревался импортировать таким образом, могут или будут импортированы.

Кэширование анонимных страниц может раскрыть токен CSRF

Django включает в себя как инфраструктуру кэширования, так и систему предотвращения атак с подделкой межсайтовых запросов (CSRF). Система CSRF-защиты основана на случайном одноразовом номере, отправляемом клиенту в файле cookie, который должен отправляться клиентом при будущих запросах, а в формах — скрытом значении, которое должно быть отправлено обратно вместе с формой.

Платформа кэширования включает возможность кэширования ответов анонимным (т. е. не прошедшим проверку подлинности) клиентам.

Когда первый анонимный запрос к данной странице исходит от клиента, у которого нет файла cookie CSRF, структура кэширования также будет кэшировать файл cookie CSRF и передавать тот же одноразовый номер другим анонимным клиентам, у которых нет файла cookie CSRF. Это может позволить злоумышленнику получить действительное значение файла cookie CSRF и выполнить атаки, обходящие проверку файла cookie.

Чтобы исправить это, платформа кэширования больше не будет кэшировать такие ответы. Эвристика для этого будет:

  1. Если входящий запрос не отправил файлы cookie и

  2. Если ответ действительно отправил один или несколько файлов cookie, и

  3. Если в ответе установлен заголовок «Vary: Cookie», то ответ не будет кэшироваться.

Приведение типов MySQL

Известно, что база данных MySQL выполняет «приведение типов» для определенных запросов; например, при запросе к таблице, содержащей строковые значения, но с использованием запроса, фильтрующего на основе целочисленного значения, MySQL сначала автоматически преобразует строки к целым числам и возвращает результат на основе этого.

Если запрос выполняется без предварительного преобразования значений в соответствующий тип, это может привести к неожиданным результатам, подобным тому, что произошло бы, если бы был изменен сам запрос.

Классы полей модели Django знают свои собственные типы, и большинство таких классов перед выполнением запроса выполняют явное преобразование аргументов запроса в правильный тип уровня базы данных. Однако три класса полей модели неправильно преобразовали свои аргументы:

Эти три поля были обновлены для преобразования их аргументов в правильные типы перед выполнением запроса.

Кроме того, разработчики полей настраиваемых моделей теперь предупреждаются в документации о том, что их классы настраиваемых полей будут выполнять соответствующие преобразования типов, а пользователям методов запроса raw() и extra(), которые позволяют разработчику предоставлять необработанный SQL или фрагменты SQL, будет рекомендовано убедиться, что они выполняют соответствующие преобразования типов вручную. перед выполнением запросов.

select_for_update() требует транзакции

Исторически запросы, использующие select_for_update(), могли выполняться в режиме автоматической фиксации вне транзакции. До Django 1.6 режим автоматических транзакций Django позволял использовать его для блокировки записей до следующей операции записи. В Django 1.6 появилась автофиксация на уровне базы данных; с тех пор выполнение в таком контексте аннулирует эффект select_for_update(). Таким образом, теперь предполагается, что это ошибка и вызывает исключение.

Это изменение было сделано потому, что такие ошибки могут быть вызваны включением приложения, которое ожидает глобальных транзакций (например, ATOMIC_REQUESTS со значением True) или старым поведением автофиксации Django в проекте, который работает без них; кроме того, такие ошибки могут проявляться как ошибки, приводящие к повреждению данных.

Это изменение может привести к сбою теста, если вы используете select_for_update() в тестовом классе, который является подклассом TransactionTestCase, а не TestCase.

Остальные исправления и изменения

  • Содержимое, полученное из библиотеки GeoIP, теперь правильно декодируется из кодировки по умолчанию ISO-8859-1 (#21996).

  • Исправлена ​​``AttributeError`` при использовании bulk_create() с ForeignObject (#21566).

  • Исправлен сбой QuerySet, использующих F() + timedelta(), когда их запрос был скомпилирован повторно (#21643).

  • Предотвращена перезапись пользовательского атрибута класса widget подклассов IntegerField кодом в их методе __init__ (#22245).

  • Улучшена точность strip_tags() (но по-прежнему не может гарантировать HTML-безопасный результат, как указано в документации).

  • Исправлена ​​регрессия в SQL-компиляторе django.contrib.gis для неконкретных полей (#22250).

  • Исправлена ​​ошибка ModelAdmin.preserve_filters при запуске сайта с префиксом URL (#21795).

  • Исправлен сбой в утилите управления find_command, когда переменная среды PATH не была установлена ​​(#22256).

  • Исправлена ​​ошибка changepassword в Windows (#22364).

  • Устранены исключения взаимоблокировки теневого копирования в MySQL (#22291).

  • Исключения базы данных заключены в _set_autocommit (#22321).

  • Исправлена ​​атомарность при закрытии соединения с базой данных или при отключении сервера базы данных (#21239 и #21202)

  • Исправлена ​​регрессия в prefetch_related, из-за которой запрос связанных объектов включал ненужное соединение (#21760).

Кроме того, шестая версия Django, django.utils.six, была обновлена ​​до последней версии (1.6.1).

Back to Top