
Analisi approfondita di una vulnerabilità critica di SQL injection nell'ORM Ormar di Python — riproduzione, correzione e test
Un'analisi approfondita di una vulnerabilità critica (CVSS 9.8) di SQL injection in un ORM asincrono Python, con riproduzione, analisi e correzione.
Ormar è un popolare mini-ORM asincrono per Python, comunemente usato con FastAPI e Starlette. Le versioni 0.9.9 fino alla 0.22.0 contengono una vulnerabilità di SQL injection nei metodi aggregati min() e max().
La causa principale è un bug di "implementazione parziale": mentre sum() e avg() verificano che il parametro della colonna si riferisca a un campo numerico effettivo, min() e max() saltano completamente questo controllo e passano l'input dell'utente direttamente a sqlalchemy.text() — un sink SQL grezzo.
Un attaccante può iniettare una subquery come parametro "colonna":
# Utilizzo previsto
await Item.objects.max("price") # → SELECT max(price) FROM items
# Payload di attacco
await Item.objects.max("(SELECT password FROM users LIMIT 1)")
# → SELECT max((SELECT password FROM users LIMIT 1)) FROM items
# Restituisce la password dell'amministratore!
| Attributo | Valore |
|---|---|
| ID CVE | CVE-2026-26198 |
| Punteggio CVSS | 9.8 (Critico) |
| CWE | CWE-89: SQL Injection |
| Versioni affette | ormar 0.9.9 – 0.22.0 |
| Corretto in | ormar 0.23.0 |
| Pubblicato | 24 febbraio 2026 |
| Autenticazione richiesta? | Nessuna — non autenticato |
├── README.md ← Sei qui
├── vulnerable_app.py ← App FastAPI minimale con il pattern vulnerabile
├── exploit_demo.py ← PoC sicuro che mostra l'iniezione in azione
├── patched_app.py ← La versione corretta con validazione dell'input
├── test_vulnerability.py ← Test che dimostrano che la vuln esiste e che la fix funziona
├── requirements.txt
└── analysis/
└── root_cause.md ← Analisi dettagliata a livello di codice del bug
git clone https://github.com/YOUR_USERNAME/CVE-2026-26198-analysis.git
cd CVE-2026-26198-analysis
python -m venv venv && source venv/bin/activate
pip install -r requirements.txt
# Esegui i test (nessun DB esterno necessario — usa SQLite)
python -m pytest test_vulnerability.py -v
# Esegui la demo interattiva dell'exploit
python exploit_demo.py
La correzione valida che il parametro della colonna corrisponda a un campo effettivo del modello prima che raggiunga sqlalchemy.text(). Questo viene fatto tramite un approccio a whitelist: sono consentiti solo i nomi di colonna che esistono nelle definizioni dei campi del modello.
Vedi patched_app.py per l'implementazione e analysis/root_cause.md per l'analisi completa.
sum()/avg() fossero validati ma min()/max() no ha creato un falso senso di sicurezza.MIT