Ответ
Основной и самый надежный метод защиты — использование параметризованных запросов (prepared statements). Этот подход разделяет сам SQL-запрос (код) и данные, передаваемые пользователем, не позволяя данным интерпретироваться как исполняемый код.
Принцип работы
- Шаблон запроса: Сначала в базу данных отправляется шаблон SQL-запроса с плейсхолдерами (
?или%s) вместо пользовательских данных. - Передача данных: Отдельно от шаблона передаются данные для подстановки в плейсхолдеры. Драйвер базы данных безопасно вставляет их, экранируя все спецсимволы.
Пример на Python (DB-API)
import sqlite3
user_input = "' OR 1=1; --"
# ❌ НЕПРАВИЛЬНО (уязвимо):
# Строка просто конкатенируется, что позволяет выполнить инъекцию.
query_vulnerable = f"SELECT * FROM users WHERE login = '{user_input}'"
# ✅ ПРАВИЛЬНО (безопасно):
# Данные передаются вторым аргументом в виде кортежа.
query_safe = "SELECT * FROM users WHERE login = ?"
cursor.execute(query_safe, (user_input,))
Дополнительные уровни защиты:
- Использование ORM (Object-Relational Mapping), таких как SQLAlchemy или Django ORM. Они по умолчанию создают параметризованные запросы.
# SQLAlchemy автоматически создает безопасный запрос user = session.query(User).filter(User.login == user_input).first() - Валидация и санация ввода: Проверяйте, что вводимые данные соответствуют ожидаемому формату (например, число является числом).
- Минимальные привилегии для пользователя БД: Учетная запись, используемая приложением, должна иметь доступ только к необходимым ей таблицам и операциям.