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

Апрель 21, 2014

Django 1.5.6 исправляет несколько ошибок в 1.5.5, включая три проблемы безопасности.

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

Работа с URL в Django основана на сопоставлении шаблонов regex (представляющих URL) с вызываемыми представлениями, а собственная обработка Django заключается в сопоставлении запрашиваемого URL с этими шаблонами для определения подходящего представления для вызова.

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

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

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

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

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

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

Django включает в себя как систему caching framework, так и систему для preventing cross-site request forgery (CSRF) attacks. Система CSRF-защиты основана на случайном nonce, отправляемом клиенту в cookie, который должен быть отправлен клиентом при последующих запросах, а в формах - на скрытом значении, которое должно быть отправлено обратно вместе с формой.

Фреймворк кэширования включает опцию кэширования ответов анонимных (т.е. неаутентифицированных) клиентов.

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

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

  1. Если входящий запрос не передал никаких файлов cookie, и
  2. Если ответ действительно отправил один или несколько файлов cookie, и
  3. Если в ответе установлен заголовок Vary: Cookie, то ответ не будет кэшироваться.

Типизация в MySQL

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

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

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

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

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

Исправления

  • Исправлено ModelBackend, повышающее UnboundLocalError, если get_user_model() вызывало ошибку (#21439).

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

Вернуться на верх