FlawOpen

flawopen.com/SQL-инъекция в Python/SQLAlchemy

Защищает ли SQLAlchemy text() от SQL-инъекций?

Справочное руководство
Краткий ответ

Связанный параметр похож на запечатанную карточку со значением в бланке запроса: SQLAlchemy передаёт SQL-инструкцию и словарь параметров нижележащему DBAPI, не включая значения в SQL-выражение, которое формирует ваш код. DBAPI-драйвер выполняет привязку с учётом конкретной базы, поэтому способ передачи может различаться. text() принимает текст SQL, но не очищает и не параметризует значения, уже вставленные в этот текст.

НЕБЕЗОПАСНО — интерполяция ввода в SQL
stmt = text(
  f"SELECT id FROM users WHERE id = {user_id}"
)
rows = conn.execute(stmt)
ЗАЩИЩЕНО — связывать значения и ограничивать SQL-структуру
stmt = text(
  "SELECT id FROM users WHERE id = :id"
)
rows = conn.execute(stmt, {"id": user_id})

# Bind values, not identifiers. Choose any
# selectable column from a fixed application map.
columns = {"name": users.c.name,
           "created": users.c.created_at}
column = columns.get(requested_sort, users.c.created_at)
stmt = select(users.c.id).order_by(column)
rows = conn.execute(stmt)

Что делает text() — и чего он не делает

text() создаёт текстовую SQL-конструкцию, но не очищает строку с уже интерполированным вводом. Объявляйте placeholders для значений в SQL и передавайте их отдельно в Connection.execute() или Session.execute(). Core API SQLAlchemy связывает литеральные значения Python в подходящих выражениях, но текстовые фрагменты остаются синтаксисом SQL. Параметры не заменяют имена таблиц и столбцов или направление сортировки. Сопоставляйте выбираемую пользователем структуру с фиксированными выражениями SQLAlchemy. Параметризация предотвращает SQL-инъекции, но не заменяет авторизацию и проверку бизнес-правил.

Как проверить кодовую базу

rg -n 'text\(|\.execute\(' --glob '*.py' .

Вопросы и ответы

Всегда ли конструкторы запросов Core и ORM в SQLAlchemy безопасны?

Они связывают значения Python в обычных выражениях, но безопасность зависит от способа построения запроса. Проверяйте текстовый SQL, литеральные SQL-конструкции и динамические идентификаторы. Ни один API не защитит SQL-строку после конкатенации ввода.

Источники

См. также SQL-инъекции (CWE-89): как они работают и как их предотвратить в любом языке — flawopen.com Предотвращает ли проверка sqlx при компиляции SQL-инъекции? Защищают ли хранимые процедуры от SQL-инъекций? Защищает ли TypeORM QueryBuilder от SQL-инъекций? Django ORM и SQL Injection: безопасные шаблоны SQL-инъекция в Doctrine ORM: безопасные запросы EF Core FromSqlRaw: безопасный SQL с параметрами