Примечания к выпуску 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-адреса. Если у такого модуля есть побочные эффекты во время импорта, эти побочные эффекты возникнут.
Таким образом, злоумышленник может вызвать неожиданное выполнение кода при следующих условиях:
Присутствует одно или несколько представлений, которые создают URL-адрес на основе пользовательского ввода (обычно это параметр «следующий» в строке запроса, указывающий, куда перенаправить после успешного завершения действия).
Злоумышленнику известно, что на пути импорта Python на сервере существуют один или несколько модулей, которые выполняют выполнение кода с побочными эффектами при импорте.
Чтобы исправить это, reverse() теперь будет принимать и импортировать только пунктирные пути на основе модулей, содержащих представление, перечисленных в Конфигурации шаблона URL-адреса проекта, чтобы гарантировать, что только те модули, которые разработчик намеревался импортировать таким образом, могут или будут импортированы.
Кэширование анонимных страниц может раскрыть токен CSRF¶
Django включает в себя как инфраструктуру кэширования, так и систему предотвращения атак с подделкой межсайтовых запросов (CSRF). Система CSRF-защиты основана на случайном одноразовом номере, отправляемом клиенту в файле cookie, который должен отправляться клиентом при будущих запросах, а в формах — скрытом значении, которое должно быть отправлено обратно вместе с формой.
Платформа кэширования включает возможность кэширования ответов анонимным (т. е. не прошедшим проверку подлинности) клиентам.
Когда первый анонимный запрос к данной странице исходит от клиента, у которого нет файла cookie CSRF, структура кэширования также будет кэшировать файл cookie CSRF и передавать тот же одноразовый номер другим анонимным клиентам, у которых нет файла cookie CSRF. Это может позволить злоумышленнику получить действительное значение файла cookie CSRF и выполнить атаки, обходящие проверку файла cookie.
Чтобы исправить это, платформа кэширования больше не будет кэшировать такие ответы. Эвристика для этого будет:
Если входящий запрос не отправил файлы cookie и
Если ответ действительно отправил один или несколько файлов cookie, и
Если в ответе установлен заголовок «Vary: Cookie», то ответ не будет кэшироваться.
Приведение типов MySQL¶
Известно, что база данных MySQL выполняет «приведение типов» для определенных запросов; например, при запросе к таблице, содержащей строковые значения, но с использованием запроса, фильтрующего на основе целочисленного значения, MySQL сначала автоматически преобразует строки к целым числам и возвращает результат на основе этого.
Если запрос выполняется без предварительного преобразования значений в соответствующий тип, это может привести к неожиданным результатам, подобным тому, что произошло бы, если бы был изменен сам запрос.
Классы полей модели Django знают свои собственные типы, и большинство таких классов перед выполнением запроса выполняют явное преобразование аргументов запроса в правильный тип уровня базы данных. Однако три класса полей модели неправильно преобразовали свои аргументы:
IPAddressField
Эти три поля были обновлены для преобразования их аргументов в правильные типы перед выполнением запроса.
Кроме того, разработчики полей настраиваемых моделей теперь предупреждаются в документации о том, что их классы настраиваемых полей будут выполнять соответствующие преобразования типов, а пользователям методов запроса 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).