
Tiefer Einblick in eine kritische SQL-Injection in Pythons Ormar-ORM — Reproduktion, Fix und Tests
Ein tiefer Einblick in eine kritische (CVSS 9.8) SQL-Injection-Schwachstelle in einem Python-Async-ORM, mit Reproduktion, Analyse und Fix.
Ormar ist ein beliebtes Async-Mini-ORM für Python, das häufig mit FastAPI und Starlette verwendet wird. Die Versionen 0.9.9 bis 0.22.0 enthalten eine SQL-Injection-Schwachstelle in den Aggregatmethoden min() und max().
Die Ursache ist ein „partieller Implementierungs“-Bug: Während sum() und avg() validieren, dass der Spaltenparameter auf ein tatsächliches numerisches Feld verweist, überspringen min() und max() diese Prüfung vollständig und leiten Benutzereingaben direkt an sqlalchemy.text() weiter — eine Raw-SQL-Senke.
Ein Angreifer kann eine Unterabfrage als „Spalten“-Parameter injizieren:
# Erwartete Verwendung
await Item.objects.max("price") # → SELECT max(price) FROM items
# Angriffspayload
await Item.objects.max("(SELECT password FROM users LIMIT 1)")
# → SELECT max((SELECT password FROM users LIMIT 1)) FROM items
# Gibt das Admin-Passwort zurück!
| Attribut | Wert |
|---|---|
| CVE-ID | CVE-2026-26198 |
| CVSS-Score | 9.8 (Kritisch) |
| CWE | CWE-89: SQL-Injection |
| Betroffen | ormar 0.9.9 – 0.22.0 |
| Behoben in | ormar 0.23.0 |
| Veröffentlicht | 24. Februar 2026 |
| Authentifizierung nötig? | Keine — ohne Authentifizierung |
├── README.md ← Du bist hier
├── vulnerable_app.py ← Minimale FastAPI-App mit dem verwundbaren Muster
├── exploit_demo.py ← Sicheres PoC, das die Injection in Aktion zeigt
├── patched_app.py ← Die behobene Version mit Eingabevalidierung
├── test_vulnerability.py ← Tests, die die Schwachstelle und den Fix belegen
├── requirements.txt
└── analysis/
└── root_cause.md ← Detaillierte Code-Ebene-Analyse des Bugs
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
# Tests ausführen (keine externe DB nötig — verwendet SQLite)
python -m pytest test_vulnerability.py -v
# Interaktive Exploit-Demo ausführen
python exploit_demo.py
Der Fix validiert, dass der Spaltenparameter einem tatsächlichen Feld des Modells entspricht, bevor er sqlalchemy.text() erreicht. Dies geschieht über einen Whitelist-Ansatz: Nur Spaltennamen, die in den Felddefinitionen des Modells existieren, sind erlaubt.
Siehe patched_app.py für die Implementierung und analysis/root_cause.md für die vollständige Aufschlüsselung.
sum()/avg() validiert wurden, min()/max() jedoch nicht, erzeugte ein falsches Sicherheitsgefühl.MIT