
Глубокое погружение в критическую SQL-инъекцию в Python-ORM Ormar — воспроизведение, исправление и тесты
Глубокий анализ критической (CVSS 9.8) уязвимости SQL-инъекции в Python async ORM, включая воспроизведение, анализ и исправление.
Ormar — это популярный асинхронный мини-ORM для Python, часто используемый вместе с FastAPI и Starlette. Версии 0.9.9–0.22.0 содержат уязвимость SQL-инъекции в агрегатных методах min() и max().
Корневая причина — ошибка «частичной реализации»: в то время как sum() и avg() проверяют, что параметр столбца ссылается на реальное числовое поле, min() и max() полностью пропускают эту проверку и передают пользовательский ввод напрямую в sqlalchemy.text() — необработанный SQL-приёмник.
Атакующий может внедрить подзапрос в качестве параметра «столбца»:
# Ожидаемое использование
await Item.objects.max("price") # → SELECT max(price) FROM items
# Вектор атаки
await Item.objects.max("(SELECT password FROM users LIMIT 1)")
# → SELECT max((SELECT password FROM users LIMIT 1)) FROM items
# Возвращает пароль администратора!
| Атрибут | Значение |
|---|---|
| ID CVE | CVE-2026-26198 |
| Оценка CVSS | 9.8 (критическая) |
| CWE | CWE-89: SQL-инъекция |
| Затронуто | ormar 0.9.9 – 0.22.0 |
| Исправлено в | ormar 0.23.0 |
| Опубликовано | 24 февраля 2026 г. |
| Нужна аутентификация? | Нет — без аутентификации |
├── README.md ← Вы здесь
├── vulnerable_app.py ← Минимальное FastAPI-приложение с уязвимым паттерном
├── exploit_demo.py ← Безопасный PoC, демонстрирующий инъекцию в действии
├── patched_app.py ← Исправленная версия с валидацией ввода
├── test_vulnerability.py ← Тесты, доказывающие наличие уязвимости и работоспособность исправления
├── requirements.txt
└── analysis/
└── root_cause.md ← Подробный анализ ошибки на уровне кода
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
# Запуск тестов (внешняя БД не требуется — используется SQLite)
python -m pytest test_vulnerability.py -v
# Запуск интерактивной демонстрации эксплойта
python exploit_demo.py
Исправление проверяет, что параметр столбца соответствует реальному полю модели, прежде чем он попадёт в sqlalchemy.text(). Это реализовано через подход с белым списком: разрешены только имена столбцов, существующие в определениях полей модели.
Реализацию см. в patched_app.py, полный разбор — в analysis/root_cause.md.
sum()/avg() были проверены, а min()/max() — нет, создал ложное чувство безопасности.MIT