Критические обновления безопасности Django: уязвимости SQL-инъекции и DoS требуют немедленного патча
Фонд Django (Django Software Foundation) выпустил внеочередные обновления безопасности, устраняющие две серьёзные уязвимости во всех поддерживаемых версиях популярного Python-фреймворка. Эти проблемы — от высокой до средней степени критичности — позволяют злоумышленникам выполнять SQL-инъекции в PostgreSQL или запускать атаки типа отказ в обслуживании (DoS), перегружая сервер и приводя к падению приложения.
Django лежит в основе миллионов сайтов по всему миру — от Instagram и Mozilla до The Washington Post и NASA. Масштаб распространения делает найденные баги особенно опасными для глобального сообщества разработчиков. Обновления уже доступны в версиях Django 5.2.9, 5.1.15 и 4.2.27. Для всех приложений на Django настоятельно рекомендуется срочно установить патчи.
Краткое резюме уязвимостей
Выявлены две разные проблемы в ядре Django, каждая из которых несёт свои риски для безопасности и отказоустойчивости приложений.
| CVE ID | Тип уязвимости | Критичность | CVSS | Затронутый компонент |
|---|---|---|---|---|
| CVE-2025-13372 | SQL-инъекция | HIGH | 8.1 | Класс FilteredRelation (PostgreSQL) |
| CVE-2025-64460 | Отказ в обслуживании (DoS) | MODERATE | 5.3 | XML-сериализатор (getInnerText) |
Затронутые версии Django
Уязвимости затрагивают сразу несколько веток Django, поэтому организациям нужно синхронно обновить все инсталляции.
| Ветка Django | Уязвимые версии | Исправленная версия | Статус поддержки |
|---|---|---|---|
| Django 5.2.x | 5.2.0 – 5.2.8 | 5.2.9 | Active Support |
| Django 5.1.x | 5.1.0 – 5.1.14 | 5.1.15 | Active Support |
| Django 4.2.x (LTS) | 4.2.0 – 4.2.26 | 4.2.27 | Long-Term Support |
| Django 6.0 (RC) | Release Candidate’ы | Потянуть последние коммиты | Pre-Release |
| Main branch | Development-сборки | Потянуть последние коммиты | Development |
CVE-2025-13372: SQL-инъекция через FilteredRelation (HIGH)
Технический обзор
Основная, наиболее критичная проблема релиза — SQL-инъекция в приложениях Django, использующих PostgreSQL. Уязвимость связана с тем, как класс FilteredRelation обрабатывает псевдонимы колонок при построении запросов.
SQL-инъекция стабильно входит в OWASP Top 10 и считается одним из самых опасных типов уязвимостей веб-приложений. В данном случае атакующий может выйти за рамки ожидаемой структуры SQL-запроса и внедрить произвольные SQL-команды, которые будут выполнены от имени приложения.
Уязвимый шаблон кода
Уязвимость проявляется при использовании распаковки словарей в методах QuerySet.annotate() или QuerySet.alias().
# Уязвимый шаблон — распаковка словаря
user_filters = {
'active_orders': FilteredRelation('orders', condition=Q(orders__status='active'))
}
queryset = User.objects.annotate(**user_filters)
# Уязвимый шаблон — динамическое создание alias’ов
dynamic_aliases = {
request.GET.get('filter_name'): FilteredRelation('related_model')
}
queryset = Model.objects.alias(**dynamic_aliases)
Сценарий атаки и эксплуатация
Атакующий формирует злоумышленное значение ключа словаря, в котором содержится SQL-payload.
При распаковке **kwargs этот ключ превращается в имя псевдонима колонки, а Django:
- не валидирует имя,
- не экранирует его как идентификатор,
- и даёт возможность внедрить фрагмент SQL.
| Фаза атаки | Действие злоумышленника | Результат |
|---|---|---|
| 1. Разведка | Находит Django-приложение на PostgreSQL с использованием FilteredRelation | Выбор цели |
| 2. Подготовка payload’а | Создаёт словарь с вредоносными ключами, содержащими SQL-инъекцию | Подготовка эксплуатации |
| 3. Инъекция | Передаёт полезную нагрузку через пользовательский ввод в annotate/alias | Внедрение SQL-кода |
| 4. Выполнение | База выполняет инъектированный SQL с правами приложения | Компрометация БД |
| 5. Экфильтрация данных | Выгружает, изменяет данные или повышает себе привилегии | Полный контроль над данными |
Возможные последствия SQL-инъекции
Успешная эксплуатация приводит к тяжёлым последствиям:
- Несанкционированный доступ к данным. Обход аутентификации и авторизации, чтение учётных данных, персональной информации, финансовых записей, внутренней бизнес-информации.
- Манипуляции данными. Изменение или удаление записей: аккаунты пользователей, история транзакций, логи аудита, критичные бизнес-данные.
- Обход аутентификации. Получение хэшей паролей или прямая подмена записей в таблицах аутентификации.
- Повышение привилегий. Перевод собственной учётной записи в роль администратора через модификацию записей в БД.
- Компрометация сервера БД. В PostgreSQL возможен запуск команд ОС через функции вроде
COPY TO PROGRAMили расширения. - Латеральное перемещение. Использование украденных учётных данных для перехода на другие системы и БД в инфраструктуре.
Оценка реального риска
| Фактор риска | Оценка | Обоснование |
|---|---|---|
| Эксплуатируемость | MEDIUM | Нужны определённые шаблоны кода и попадание пользовательского ввода в annotate/alias |
| Сложность атаки | MEDIUM | Требуются знания Django ORM и SQL PostgreSQL |
| Требуемые привилегии | LOW | Достаточно базового доступа к приложению или публичных форм |
| Взаимодействие с пользователем | NONE | Атака полностью автоматизируема |
| Scope | CHANGED | Влияние выходит за рамки приложения и затрагивает БД и инфраструктуру |
| Конфиденциальность | HIGH | Возможна полная выгрузка содержимого БД |
| Целостность | HIGH | Данные могут быть массово изменены или удалены |
| Доступность | HIGH | Базу можно сделать недоступной разрушительными операциями |
CVE-2025-64460: отказ в обслуживании через XML-сериализатор (MODERATE)
Технический обзор
Вторая уязвимость связана с функциональностью XML-сериализации Django, а именно с методом django.core.serializers.xml_serializer.getInnerText(). Это классический пример атаки на алгоритмическую сложность.
Специально сформированный XML заставляет приложение выполнять огромное количество операций, расходуя CPU и память до тех пор, пока сервер не начинает отказывать в обслуживании.
Разбор причины
getInnerText() собирает текст из XML-узлов через повторяющуюся конкатенацию строк.
В Python строки иммутабельны, и каждая операция a + b создаёт новый объект строки.
При глубокой вложенности и большом числе текстовых узлов это приводит к квадратичной сложности O(n²).
# Уязвимый (упрощённый) паттерн
def getInnerText(node):
text = ""
for child in node.childNodes:
if child.nodeType == Node.TEXT_NODE:
text = text + child.data # каждый раз создаётся новая строка
else:
text = text + getInnerText(child) # рекурсивная конкатенация
return text
Механика атаки
Злоумышленник формирует XML со следующими характеристиками:
| Особенность XML-структуры | Эффект при обработке | Нагрузка на ресурсы |
|---|---|---|
| Глубокая вложенность | Увеличивает глубину рекурсии и число конкатенаций | CPU, стек вызовов |
| Много текстовых узлов | Каждая нода → новая операция сложения строк | Выделение памяти, CPU |
| Большие текстовые блоки | Каждая конкатенация копирует весь накопленный текст | Память, пропускная способность |
| Чередование элементов и текста | Максимизирует количество операций | CPU, создание временных объектов |
Последствия DoS-атаки
При обработке такого XML возникают:
- Загрузка CPU до 100% на длительное время — легитимные запросы простаивают.
- Исчерпание памяти из-за множества временных объектов строк.
- Захват пула потоков — воркеры висят на долгих запросах.
- Неработоспособность приложения — сервер перестаёт отвечать пользователям.
- Деградация сервиса — резкий рост времени ответа.
- Каскадные сбои — балансировщик выкидывает «больные» инстансы, перегружая оставшиеся.
Сложность атаки
| Характеристика атаки | Уровень | Описание |
|---|---|---|
| Навыки атакующего | LOW | Генерация «тяжёлого» XML не требует серьёзной экспертизы |
| Ресурсы злоумышленника | MINIMAL | Иногда достаточно одного запроса |
| Сложность обнаружения | MEDIUM | Выглядит как обычная обработка XML |
| Сложность устранения | LOW | Установка патча полностью решает проблему |
| Тяжесть последствий | MODERATE–HIGH | Возможен полный отказ сервиса при минимальных усилиях атакующего |
Какие приложения в зоне наибольшего риска
| Тип приложения | Риск CVE-2025-13372 | Риск CVE-2025-64460 | Приоритет |
|---|---|---|---|
| REST-API на PostgreSQL | HIGH | LOW | CRITICAL |
| Системы импорта/экспорта данных | MEDIUM | HIGH | CRITICAL |
| Публичные веб-приложения | HIGH | MEDIUM | HIGH |
| Админ-панели | MEDIUM | MEDIUM | HIGH |
| Интеграционные XML-endpoint’ы | LOW | HIGH | HIGH |
| CMS-системы | HIGH | MEDIUM | HIGH |
| E-commerce-платформы | HIGH | HIGH | CRITICAL |
| Внутренние тулзы (ограниченный доступ) | MEDIUM | LOW | MEDIUM |
Немедленные шаги по снижению рисков
Шаг 1. Определить затронутые приложения
Сначала нужно составить перечень всех Django-проектов и их версий.
# Проверка версии Django
python -m django --version
# Либо так
python manage.py --version
# Через Python
python -c "import django; print(django.get_version())"
| Шаг | Действие | Как проверить |
|---|---|---|
| 1 | Перечислить все Django-проекты в инфраструктуре | Документация деплоймента, конфиги серверов |
| 2 | Определить версию Django по каждому проекту | Запустить команды проверки на прод-серверах |
| 3 | Выяснить тип БД (особенно PostgreSQL) | Посмотреть DATABASES в settings.py |
| 4 | Найти использование XML-сериализации | Поиск по коду django.core.serializers.xml_serializer |
| 5 | Проверить паттерны FilteredRelation | Code review annotate/alias с распаковкой словарей |
| 6 | Расставить приоритеты по экспонированию | Публичные → внутренние → dev/test |
Шаг 2. Установить обновления безопасности
Обновляем все затронутые инсталляции:
# Обновление через pip
pip install --upgrade Django==5.2.9 # для ветки 5.2.x
pip install --upgrade Django==5.1.15 # для ветки 5.1.x
pip install --upgrade Django==4.2.27 # для LTS 4.2.x
# Проверка версии
python -m django --version
# Для тех, кто сидит на main/RC
cd /path/to/django
git pull origin main
| Этап обновления | Действия | Что проверить |
|---|---|---|
| Pre-update | Бэкапы, тесты на стейджинге, чтение release notes | Проверка бэкапов, результаты тестов |
| Исполнение | Обновить пакет Django, при необходимости зависимости, очистить кэш Python | Подтверждение версии, проверка зависимостей |
| Тестирование | Прогнать автотесты, ручные проверки, перф-тесты | Прохождение тестов, чек-лист функционала |
| Деплой | Выкатить на прод, перезапустить сервисы, очистить кэши | Успешный старт, health-check’и |
| Post-deploy | Мониторинг логов, метрик, скан на уязвимости | Анализ логов, дашборды, отчёт сканера |
Шаг 3. Code review и hardening
Патч закрывает уязвимость, но ревизия кода поможет снизить риски в будущем.
Для SQL-инъекции (CVE-2025-13372)
- Не использовать распаковку словарей с пользовательскими ключами.
Никогда не передавайте вannotate()/alias()**kwargs, где ключи формируются из входных данных. - Явно задавать имена алиасов.
Используйте фиксированный набор имён вместо произвольного input’а. - Валидировать любые входные данные.
Даже если они не попадают напрямую в SQL. - Полагаться на ORM-параметризацию.
Избегать строковой сборки SQL.
# БЕЗОПАСНО: Явные имена алиасов
if filter_type == 'active':
queryset = User.objects.annotate(
active_orders=FilteredRelation('orders', condition=Q(orders__status='active'))
)
elif filter_type == 'completed':
queryset = User.objects.annotate(
completed_orders=FilteredRelation('orders', condition=Q(orders__status='completed'))
)
# ОПАСНО: ключи словаря контролируются пользователем
user_input = {'field_name': FilteredRelation(...)}
queryset = Model.objects.annotate(**user_input) # уязвимый паттерн
Для DoS (CVE-2025-64460)
- Ограничить максимальный размер XML-ввода.
- Ограничить глубину вложенности и число элементов.
- Настроить тайм-ауты на обработку XML.
- Ввести rate limiting на endpoint’ы, принимающие XML.
- Где возможно — перейти на JSON-сериализацию.
Обнаружение и мониторинг
Что стоит мониторить, чтобы заметить попытки эксплуатации:
| Тип индикатора | Что смотреть | Как отслеживать |
|---|---|---|
| Попытки SQL-инъекций | Ошибки SQL в логах БД | Централизация логов, алерты в SIEM |
| Нетипичные запросы | Сложные, «странные» запросы к БД | Логирование запросов, поиск аномалий |
| Пики CPU | Длительная 100% нагрузка | Мониторинг систем, APM |
| Рост потребления памяти | Резкий рост RAM при обработке XML | Профилирование памяти, мониторинг ресурсов |
| Долгие запросы | Затяжная обработка XML-запросов | APM, метрики времени ответа |
| Аномальные XML-payload’ы | Очень большие или глубоко вложенные XML | Логирование входных данных, WAF-правила |
| Рост числа ошибок/тайм-аутов | 5xx, timeouts | Мониторинг error-rate, health-check’и |
Многоуровневая защита (Defense in Depth)
Помимо установки патчей, важно выстроить несколько уровней обороны:
| Уровень защиты | Реализация | Эффект |
|---|---|---|
| WAF | Правила против SQL-инъекций и XML-атак | Фильтрует атаки до приложения |
| Контроль доступа к БД | Минимально необходимые права, read-only где возможно | Снижает ущерб при успешной SQL-инъекции |
| Валидация ввода | Проверка данных на входе | Не даёт вредоносным данным дойти до ядра |
| Rate limiting | Лимиты по IP/пользователю | Снижает риск DoS и массовой эксплуатации |
| Мониторинг безопасности | SIEM, IDS/IPS, APM | Позволяет быстро реагировать на атаки |
| Мониторинг активности БД | Логи и алерты на необычные запросы | Помогает выявлять попытки SQL-инъекций |
| Лимиты ресурсов | Ограничения CPU/RAM на процессах | Не даёт одному запросу «съесть» все ресурсы |
| Регулярные аудиты | Code review, пен-тесты, сканирование | Раннее выявление уязвимостей |
Долгосрочные практики безопасности
1. Автоматизированное управление зависимостями
- Использовать Dependabot, Renovate и аналогичные инструменты.
- Включить оповещения о уязвимых пакетах.
- Ввести регулярный цикл обновлений с тестированием.
- Вести актуальный реестр всех Django-приложений и их версий.
2. Безопасная разработка
- Ввести и соблюдать стандарты безопасного кодирования.
- Обязательный security-фокусированный code review.
- Подключить SAST в CI/CD для раннего поиска проблем.
- Проводить DAST-сканирование стейджинга и продакшена.
- Регулярно обучать разработчиков вопросам ИБ.
3. Готовность к инцидентам
- Описать и утвердить план реагирования на инциденты.
- Проводить учения и tabletop-упражнения.
- Поддерживать актуальные контакты команды безопасности.
- Определить каналы и порядок коммуникации при инцидентах.
- Заранее продумать roll-back-процедуры.
Полезные ресурсы по безопасности Django
| Ресурс | Описание | Где найти |
|---|---|---|
| Django Security Announcements | Официальная рассылка по обновлениям безопасности | Подписка на djangoproject.com |
| Политика безопасности Django | Как сообщать об уязвимостях | docs.djangoproject.com/.../internals/security/ |
| Release Notes Django | Подробные изменения и фиксы | docs.djangoproject.com/en/stable/releases/ |
| OWASP: Django Security | Рекомендации по защите Django-приложений | owasp.org |
| База CVE | Официальный учёт уязвимостей | cve.mitre.org |
Заключение
Уязвимости CVE-2025-13372 и CVE-2025-64460 ещё раз показывают, насколько важно проактивно обслуживать безопасность Django-приложений. Команда безопасности Django оперативно выпустила патчи, но ответственность за их установку лежит на разработчиках и DevOps-командах.
- CVE-2025-13372 (SQL-инъекция) — критический риск для проектов на PostgreSQL, вплоть до полного захвата базы данных.
- CVE-2025-64460 (DoS) — уязвимость средней критичности, но способная вызвать серьёзный простой сервиса при минимальных усилиях атакующего.
С учётом широчайшего распространения Django, относительной простоты эксплуатации и тяжести последствий эти обновления нужно рассматривать как обновления высшего приоритета, а не «очередной плановый релиз».
Чек-лист действий
| Приоритет | Действие | Статус |
|---|---|---|
| IMMEDIATE | Провести инвентаризацию всех Django-приложений и их версий | ☐ |
| IMMEDIATE | Обновить все инсталляции Django до исправленных версий | ☐ |
| IMMEDIATE | Протестировать обновления на стейджинге | ☐ |
| HIGH | Выкатить обновления на продакшен | ☐ |
| HIGH | Провести code review на предмет уязвимых паттернов (dict-expand, XML) | ☐ |
| HIGH | Настроить мониторинг попыток эксплуатации | ☐ |
| MEDIUM | Добавить правила WAF против SQL-инъекций и XML-атак | ☐ |
| MEDIUM | Усилить валидацию входных данных | ☐ |
| MEDIUM | Ввести rate limiting для XML-endpoint’ов | ☐ |
| ONGOING | Подписаться на security-рассылку Django | ☐ |
| ONGOING | Настроить автоматическое обновление зависимостей | ☐ |
Нужна помощь с защитой ваших Django-приложений?
SecurityLab.Pro предлагает комплексные услуги по безопасности веб-приложений:
- Аудит безопасности: полный обзор кода и анализ уязвимостей Django-проектов
- Пентесты: моделирование реальных атак до того, как это сделают злоумышленники
- Управление патчами: сопровождение обновлений и закрытие критичных дыр
- 24/7-мониторинг: круглосуточное наблюдение и реагирование на угрозы
- Incident Response: помощь при уже произошедших инцидентах и ликвидация последствий
- Security-консалтинг: выстраивание процессов и архитектуры безопасной разработки
