Москва: проверенные б/у ноутбуки с гарантией и проверкой перед оплатой
+7 906 722-94-45

Главная → Статьи → SQL injection: предотвращение инъекций

SQL injection: как предотвращать SQL-инъекции в приложениях

SQL-инъекции: типы атак, предотвращение через параметризованные запросы, ORM, валидацию ввода и практические паттерны защиты баз данных.

Прямой ответ

SQL injection — атака через внедрение SQL-кода в запросы приложения (injection — «SQL-инъекция» — injection — incident — «внедрение SQL» — injection), зачем предотвращать: защита от несанкционированного доступа (injection — «доступ к данным» — injection — incident — «кража данных» — injection — postgres — «защита» — injection); типы SQL-инъекций (injection — «типы атак» — injection): (1) Классическая (In-band) (injection — «результат виден сразу» — injection — incident — «результат в ответе» — injection — postgres — UNION SELECT (injection — «UNION» — injection — «данные в ответе» — injection); (2) Слепая (Blind) (injection — «результат не виден» — injection — incident — «результат не виден» — injection — postgres — логические условия (injection — AND 1=1 (injection — «логические» — injection — «данные через логику» — injection); (3) Вне полосы (Out-of-band) (injection — «данные через другой канал» — injection — incident — «данные через DNS/HTTP» — injection — postgres — LOAD_FILE (injection — «файлы» — injection — «данные через файлы» — injection); методы предотвращения (injection — «как предотвратить» — injection): (1) Параметризованные запросы (injection — «параметры вместо конкатенации» — injection — incident — «параметры» — injection — postgres — PREPARE (injection — PREPARE stmt AS SELECT * FROM users WHERE id = $1 (injection — «параметры» — injection — postgres — «безопасно» — injection); (2) ORM (injection — «ORM вместо SQL» — injection — incident — «ORM» — injection — postgres — SQLAlchemy/Django ORM (injection — «ORM» — injection — postgres — «безопасно» — injection); (3) Валидация ввода (injection — «проверка ввода» — injection — incident — «валидация» — injection — postgres — проверка типов (injection — «проверка типов» — injection — postgres — «валидация» — injection); (4) Экранирование (injection — «экранирование спецсимволов» — injection — incident — «экранирование» — injection — postgres — quote_literal (injection — «экранирование» — injection — postgres — «безопасно» — injection); когда предотвращать (injection): всегда (injection — «постоянно» — injection — incident — «24/7» — injection — postgres), все запросы (injection — «все запросы» — injection — incident — «все» — injection — postgres), пользовательский ввод (injection — «ввод пользователя» — injection — incident — «ввод» — injection — postgres); антипаттерны: конкатенация строк (injection — "SELECT * FROM users WHERE id = " + user_id (injection — incident — «конкатенация» — injection — postgres — «уязвимо» — injection), игнорирование валидации (injection — «без валидации» — injection — incident — «без проверки» — injection — postgres — «валидация обязательна» — injection).

Практика: предотвращение SQL-инъекций

Параметризованные запросы (injection — Python (injection — cursor.execute("SELECT * FROM users WHERE id = %s", (user_id,)) (injection — «параметры» — injection — postgres — «безопасно» — injection — Python); ORM (injection — SQLAlchemy (injection — session.query(User).filter(User.id == user_id).first() (injection — «ORM» — injection — postgres — «безопасно» — injection — SQLAlchemy); Валидация (injection — Python (injection — if not user_id.isdigit(): raise ValueError("Invalid user_id") (injection — «валидация» — injection — postgres — «проверка» — injection — Python); Экранирование (injection — PostgreSQL (injection — SELECT quote_literal(user_input) (injection — «экранирование» — injection — postgres — «безопасно» — injection — postgres); PREPARE (injection — PostgreSQL (injection — PREPARE stmt AS SELECT * FROM users WHERE id = $1; EXECUTE stmt(123); (injection — «подготовленные запросы» — injection — postgres — «безопасно» — injection — postgres).

Практический сценарий: защита приложения от SQL-инъекций

Контекст: веб-приложение (postgres — пользовательский ввод (incident — injection), боль: уязвимость (injection — «конкатенация строк» — injection — incident — «SQL-инъекция» — injection — postgres); решение — предотвращение SQL-инъекций: (1) параметризованные запросы (injection — cursor.execute("SELECT * FROM users WHERE id = %s", (user_id,)) (injection — postgres — «параметры» — injection — Python); (2) валидация (injection — if not user_id.isdigit(): raise ValueError("Invalid user_id") (injection — postgres — «валидация» — injection — Python); (3) ORM (injection — session.query(User).filter(User.id == user_id).first() (injection — postgres — «ORM» — injection — SQLAlchemy); (4) тестирование (injection — тесты на инъекции (injection — «тесты» — injection — postgres — «тестирование» — injection — incident); (5) аудит (injection — код-ревью (injection — «ревью» — injection — postgres — «аудит» — injection — incident); результат: SQL-инъекции предотвращены (injection — «параметризованные запросы» — injection — incident — «уязвимость устранена» — injection — postgres — «данные защищены» — injection); вывод: предотвращение SQL-инъекций решили задачу (защита от атак — injection — ADR — «конкатенация строк» — антипаттерн — postgres — параметризованные запросы обязательны — injection — техдолг).

FAQ

Что такое SQL injection и какие типы атак существуют? SQL injection (injection — атака через внедрение SQL (injection — «SQL-инъекция» — injection — incident — «внедрение SQL» — injection — postgres); типы (injection): In-band (injection — «результат виден» — injection — incident — «результат в ответе» — injection — postgres — UNION SELECT (injection — «UNION» — injection), Blind (injection — «результат не виден» — injection — incident — «результат не виден» — injection — postgres — AND 1=1 (injection — «логические» — injection), Out-of-band (injection — «данные через другой канал» — injection — incident — «данные через DNS» — injection — postgres — LOAD_FILE (injection — «файлы» — injection); «конкатенация строк» — антипаттерн (уязвимость — postgres — параметризованные запросы обязательны — injection — ADR — техдолг).

Какие методы предотвращения SQL-инъекций существуют? Методы (injection — предотвращение (injection — «как предотвратить» — injection — incident — «предотвращение» — injection — postgres): Параметризованные запросы (injection — «параметры» — injection — incident — «параметры» — injection — postgres — cursor.execute("SELECT * FROM users WHERE id = %s", (user_id,)) (injection — «безопасно» — injection), ORM (injection — «ORM» — injection — incident — «ORM» — injection — postgres — session.query(User).filter(User.id == user_id).first() (injection — «безопасно» — injection), Валидация (injection — «проверка ввода» — injection — incident — «валидация» — injection — postgres — if not user_id.isdigit(): raise ValueError (injection — «валидация» — injection), Экранирование (injection — «экранирование» — injection — incident — «экранирование» — injection — postgres — quote_literal (injection — «безопасно» — injection); «игнорировать методы» — антипаттерн (уязвимость — postgres — все методы важны — injection — ADR — техдолг).

Как использовать параметризованные запросы и почему они безопасны? Параметризованные запросы (injection — параметры (injection — «параметры вместо конкатенации» — injection — incident — «параметры» — injection — postgres); как: Python (injection — cursor.execute("SELECT * FROM users WHERE id = %s", (user_id,)) (injection — postgres — «параметры» — injection — Python), PostgreSQL (injection — PREPARE stmt AS SELECT * FROM users WHERE id = $1; EXECUTE stmt(123); (injection — postgres — «параметры» — injection — postgres); почему безопасны: параметры не интерпретируются как SQL (injection — «параметры — данные» — injection — incident — «не SQL» — injection — postgres — «безопасно» — injection); «конкатенация строк» — антипаттерн (уязвимость — postgres — параметризованные запросы обязательны — injection — ADR — техдолг).

Как тестировать приложение на SQL-инъекции и что делать при обнаружении уязвимости? Тестирование (injection — тесты (injection — «тесты на инъекции» — injection — incident — «тестирование» — injection — postgres); как: автоматические сканеры (injection — sqlmap (injection — «сканер» — injection — postgres — «автоматически» — injection — incident), ручное тестирование (injection — «вручную» — injection — incident — «вручную» — injection — postgres — «тестирование» — injection), код-ревью (injection — «ревью кода» — injection — incident — «ревью» — injection — postgres — «аудит» — injection); при обнаружении: исправить (injection — «параметризованные запросы» — injection — incident — «исправить» — injection — postgres — «немедленно» — injection), тестировать (injection — «тесты» — injection — incident — «тестировать» — injection — postgres — «тесты» — injection); «не тестировать» — антипаттерн (уязвимости не найдены — postgres — тестировать обязательно — injection — ADR — техдолг).

Источники: OWASP (SQL Injection), PostgreSQL docs (prepare), Python sqlite3 docs — ссылки в шапке.