← Назад к вопросам

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

3.0 Senior🔥 201 комментариев
#PHP Core

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI7 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Что такое SQL-инъекция

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

Как работает атака

Представьте простой PHP-код для авторизации:

$username = $_POST['username'];
$password = $_POST['password'];
$sql = "SELECT * FROM users WHERE username = '$username' AND password = '$password'";
$result = mysqli_query($conn, $sql);

Если злоумышленник введёт в поле username значение admin' --, SQL-запрос примет вид:

SELECT * FROM users WHERE username = 'admin' --' AND password = '...'

Символ -- означает комментарий в SQL, поэтому условие с паролем игнорируется, и атакующий может получить доступ от имени администратора без знания пароля.

Более опасные варианты инъекций позволяют извлекать, изменять или удалять данные, а в некоторых случаях — выполнять произвольные команды на сервере БД.

Методы защиты от SQL-инъекций

1. Использование подготовленных выражений (Prepared Statements)

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

Пример с PDO:

$stmt = $pdo->prepare("SELECT * FROM users WHERE username = :username AND password = :password");
$stmt->execute([
    'username' => $_POST['username'],
    'password' => $_POST['password']
]);
$user = $stmt->fetch();

Пример с MySQLi:

$stmt = $conn->prepare("SELECT * FROM users WHERE username = ? AND password = ?");
$stmt->bind_param("ss", $_POST['username'], $_POST['password']);
$stmt->execute();
$result = $stmt->get_result();

2. Экранирование специальных символов

Если по какой-то причине подготовленные выражения недоступны, необходимо экранировать пользовательский ввод с помощью функций, специфичных для СУБД:

// Для MySQLi
$username = mysqli_real_escape_string($conn, $_POST['username']);
$password = mysqli_real_escape_string($conn, $_POST['password']);
$sql = "SELECT * FROM users WHERE username = '$username' AND password = '$password'";

Важно: этот метод менее надёжен, чем подготовленные выражения, и требует корректной установки кодировки соединения.

3. Валидация и фильтрация входных данных

  • Валидация типа данных: для числовых параметров используйте приведение типов или filter_var().
$user_id = (int)$_GET['id']; // Приведение к integer
$email = filter_var($_POST['email'], FILTER_VALIDATE_EMAIL); // Валидация email
  • Белые списки (whitelisting): разрешайте только ожидаемые значения, особенно для полей с ограниченным набором вариантов.

4. Принцип наименьших привилегий

Настройте права доступа учётной записи БД, от имени которой работает приложение:

  • Запретите операции DROP, ALTER, CREATE в производственной среде.
  • Ограничьте доступ к таблицам только необходимыми операциями (SELECT, INSERT, UPDATE).
  • Используйте отдельные учётные записи для разных частей приложения.

5. Хранимые процедуры

Использование хранимых процедур может помочь, но только при корректной реализации — они тоже подвержены инъекциям, если динамически формируют SQL.

6. Регулярное обновление и сканирование

  • Обновляйте СУБД, фреймворки и библиотеки.
  • Используйте статические анализаторы кода и сканеры уязвимостей (например, SQLMap для тестирования).
  • Проводите код-ревью с акцентом на безопасность.

Дополнительные рекомендации

  • Не выводите детальные ошибки SQL в production-среде — они могут раскрыть структуру базы данных.
  • Используйте ORM (Doctrine, Eloquent), которые часто включают защиту от инъекций, но понимайте их ограничения.
  • Логируйте подозрительные запросы для последующего анализа.

SQL-инъекция остаётся критической уязвимостью, но её полностью можно предотвратить корректным использованием подготовленных выражений и соблюдением best practices в разработке. Защита должна быть многоуровневой — не полагайтесь на единственный метод, комбинируйте подходы для максимальной безопасности.