FlawOpen

flawopen.com/SQL-инъекция в Rust/sqlx

Предотвращает ли проверка sqlx при компиляции SQL-инъекции?

Справочная страница
Краткий ответ

query! при компиляции сверяет литеральный запрос со схемой реальной базы данных; это не делает задним числом безопасным динамически собранный запрос. Передавайте значения отдельно через связанные параметры.

НЕБЕЗОПАСНО — вставить ввод в SQL
let user_id: String = read_user_input();
let q = format!(
  "SELECT id FROM users WHERE id = '{}'",
  user_id
);
// Representative only: data and SQL syntax are mixed.
// Never pass user-influenced SQL as AssertSqlSafe.
БЕЗОПАСНО — связать значение через query!
let user_id: &str = read_user_input();
// PostgreSQL; query! checks the configured schema.
sqlx::query!(
  "SELECT id FROM users WHERE id = $1",
  user_id
).fetch_one(&pool).await?

Что именно проверяется при компиляции

Макрос SQLx 0.9 query! требует строковый литерал и во время сборки проверяет синтаксис, типы параметров и результатов по настроенной схеме базы данных; настройте DATABASE_URL или используйте сохранённые в репозитории офлайн-метаданные. Этот пример относится к PostgreSQL: здесь используется маркер $1. SQLx рекомендует $1 для PostgreSQL и SQLite; MySQL и MariaDB используют позиционные маркеры ?. Функция времени выполнения query() может связывать значения через .bind(), если структура SQL фиксирована или контролируется приложением. В SQLx 0.9 динамическую строку нужно передавать через AssertSqlSafe; этот тип лишь утверждает, что запрос безопасен, но не очищает строку. Не используйте его, чтобы пометить безопасной строку с интерполированными недоверенными значениями.

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

rg -n 'format!\s*\(|sqlx::query(_as)?\s*\(' --glob '*.rs'

Часто задаваемые вопросы

Нужно ли всегда использовать макрос query! вместо query()?

Используйте query!, если требования к литеральному запросу и схеме при сборке подходят проекту: макрос добавляет проверку SQL и типов при компиляции. Динамический query() тоже безопасен, если связывать каждое значение через .bind(). В любом случае не вставляйте недоверенные данные в синтаксис SQL.

Источники

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