Найдите слепую SQL-инъекцию через text() в SQLAlchemy
Этот код SQLAlchemy строит запрос, подставляя пользовательское table_name в сырой фрагмент text(). Найдите инъекцию и объясните, почему она «слепая».
Ограничения:
table_nameприходит из пользовательского ввода- запрос не возвращает строк пользователю (fire-and-forget)
db.execute(
text(f"select create_new_table('{table_name}', 'ts', if_not_exists => true)")
)
Определите причину.
SQL-инъекция — text() выполняет склеенную f-строку как есть, не параметризуя её, поэтому table_name внедряет произвольный SQL. Слепая: ответа с данными нет, выполнение подтверждают лишь по времени. Фикс: связанные параметры и белый список.
- ✗Думать, что
text()параметризует подставленную f-строку - ✗Считать слепую инъекцию невозможной без видимого вывода
- ✗Принимать инъекцию за состояние гонки или раскрытие информации
- →Как атакующий извлекает данные через слепую инъекцию по времени побитово?
- →Почему связанные параметры устраняют инъекцию, а чёрный список — нет?
Уязвимость
text() в SQLAlchemy выполняет переданную строку как есть — он НЕ параметризует f-строку:
text(f"select create_new_table('{table_name}', 'ts', if_not_exists => true)")
table_name склеивается в SQL → инъекция. Вывода нет → слепая (blind).
Как обнаружить. Раз ответ не содержит данных, отличить уязвимый эндпоинт от безопасного можно только по побочному каналу — прежде всего по времени ответа: если строка, закрывающая литерал и добавляющая задержку в СУБД, увеличивает время ответа, значит ввод попадает в SQL-парсер. На практике это ловится не ручным подбором, а статическим анализом (bandit/CodeQL правило «raw SQL из f-строки») и логированием текста запроса — уязвимость видна в коде до эксплуатации.
Исправление
Никогда не подставляйте ввод в text(); используйте связанные параметры и проверяйте идентификатор по белому списку:
ALLOWED = {"events", "logs"}
if table_name not in ALLOWED:
abort(400)
db.execute(text("select create_new_table(:t, 'ts', if_not_exists => true)"), {"t": table_name})
✅ Связанные параметры экранируют данные; белый список ограничивает имена таблиц.