Что такое SQL-инъекция и как от неё защититься

«Что такое SQL-инъекция и как от неё защититься» — вопрос из категории Безопасность, который задают на 23% собеседований Python Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

SQL-инъекция (SQL Injection) — это тип атаки на веб-приложения, при которой злоумышленник внедряет произвольный SQL-код в запросы к базе данных. Это становится возможным, когда приложение напрямую вставляет пользовательский ввод в SQL-запрос без должной обработки.

Успешная атака может привести к утечке, изменению или удалению данных, а в некоторых случаях — к полному захвату контроля над сервером.

Пример уязвимости (Python):

Предположим, есть код для поиска пользователя по имени. Ввод от пользователя напрямую конкатенируется со строкой запроса.

# НЕБЕЗОПАСНЫЙ КОД!
user_input = "' OR '1'='1' -- " # Ввод злоумышленника

query = f"SELECT * FROM users WHERE name = '{user_input}';"
# cursor.execute(query)

Итоговый SQL-запрос будет выглядеть так:

SELECT * FROM users WHERE name = '' OR '1'='1' -- ';

Условие OR '1'='1' всегда истинно, поэтому запрос вернет всех пользователей из таблицы. -- комментирует оставшуюся часть запроса.

Как защититься?

Основной принцип защиты — разделение кода и данных. Данные, полученные от пользователя, никогда не должны интерпретироваться как часть исполняемого SQL-кода.

  1. Использование параметризованных запросов (Prepared Statements) Это самый надежный метод. Драйвер базы данных сам безопасно подставляет значения в запрос, экранируя все спецсимволы.

    # БЕЗОПАСНЫЙ КОД
    user_input = "' OR '1'='1' -- "
    
    # Знак '?' — это плейсхолдер для данных
    query = "SELECT * FROM users WHERE name = ?;"
    cursor.execute(query, (user_input,))
  2. Использование ORM (Object-Relational Mapping) Библиотеки вроде SQLAlchemy (Python), Hibernate (Java) или Eloquent (PHP) по умолчанию используют параметризованные запросы, что значительно снижает риск инъекций.

  3. Принцип наименьших привилегий Пользователь базы данных, от имени которого приложение выполняет запросы, должен иметь только необходимые ему права. Например, ему не нужен доступ на удаление таблиц (DROP TABLE).