
Profundización en una inyección SQL crítica en el ORM Ormar de Python: reproducción, corrección y pruebas
Un análisis profundo de una vulnerabilidad crítica (CVSS 9.8) de inyección SQL en un ORM asíncrono de Python, con reproducción, análisis y corrección.
Ormar es un mini ORM asíncrono popular para Python, comúnmente utilizado con FastAPI y Starlette. Las versiones 0.9.9 hasta 0.22.0 contienen una vulnerabilidad de inyección SQL en los métodos agregados min() y max().
La causa raíz es un error de "implementación parcial": mientras que sum() y avg() validan que el parámetro de columna se refiera a un campo numérico real, min() y max() omiten esta verificación por completo y pasan la entrada del usuario directamente a sqlalchemy.text() — un sumidero SQL sin procesar.
Un atacante puede inyectar una subconsulta como parámetro de "columna":
# Uso esperado
await Item.objects.max("price") # → SELECT max(price) FROM items
# Payload de ataque
await Item.objects.max("(SELECT password FROM users LIMIT 1)")
# → SELECT max((SELECT password FROM users LIMIT 1)) FROM items
# ¡Devuelve la contraseña del administrador!
| Atributo | Valor |
|---|---|
| ID CVE | CVE-2026-26198 |
| Puntuación CVSS | 9.8 (Crítico) |
| CWE | CWE-89: Inyección SQL |
| Afectado | ormar 0.9.9 – 0.22.0 |
| Corregido en | ormar 0.23.0 |
| Publicado | 24 de febrero de 2026 |
| ¿Requiere autenticación? | Ninguna — sin autenticación |
├── README.md ← Estás aquí
├── vulnerable_app.py ← Aplicación FastAPI mínima con el patrón vulnerable
├── exploit_demo.py ← PoC seguro que muestra la inyección en acción
├── patched_app.py ← La versión corregida con validación de entrada
├── test_vulnerability.py ← Pruebas que demuestran que la vulnerabilidad existe y que la corrección funciona
├── requirements.txt
└── analysis/
└── root_cause.md ← Análisis detallado a nivel de código del error
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
# Ejecuta las pruebas (no se necesita base de datos externa — usa SQLite)
python -m pytest test_vulnerability.py -v
# Ejecuta la demostración interactiva del exploit
python exploit_demo.py
La corrección valida que el parámetro de columna coincida con un campo real del modelo antes de que llegue a sqlalchemy.text(). Esto se realiza mediante un enfoque de lista blanca: solo se permiten los nombres de columna que existen en las definiciones de campos del modelo.
Consulta patched_app.py para la implementación y analysis/root_cause.md para el desglose completo.
sum()/avg() estuvieran validadas pero min()/max() no, creó una falsa sensación de seguridad.MIT