Почему использование прямых SQL-запросов (mysql_query) в коде без очистки входных данных ведет к SQL-инъекциям?
SQL-инъекция — одна из наиболее распространённых и опасных уязвимостей веб-приложений. Она возникает тогда, когда пользовательские данные напрямую подставляются в SQL-запрос без какой-либо проверки или экранирования.
**Как это работает на практике**
Представьте типичный код на PHP с использованием устаревшей функции mysql_query:
php
$username = $_GET[‘username’];
$query = «SELECT * FROM users WHERE username = ‘$username'»;
$result = mysql_query($query);
Если пользователь введёт в поле имени строку вида `’ OR ‘1’=’1`, итоговый запрос примет вид:
sql
SELECT * FROM users WHERE username = » OR ‘1’=’1′
Условие `’1’=’1’` всегда истинно, поэтому запрос вернёт все записи из таблицы пользователей. Злоумышленник получает доступ к данным, которые ему не предназначены.
**Почему mysql_query особенно уязвима**
Функция `mysql_query` (и весь модуль `mysql_*` в PHP) была признана устаревшей ещё в PHP 5.5 и полностью удалена в PHP 7. Она не поддерживает подготовленные выражения (prepared statements), которые являются основным механизмом защиты от SQL-инъекций. Разработчик вынужден вручную экранировать данные, что легко забыть или сделать неправильно.
**Что может сделать злоумышленник через SQL-инъекцию**
— Получить доступ к конфиденциальным данным: паролям, email-адресам, платёжным данным.
— Изменить или удалить данные в базе.
— Обойти аутентификацию и войти под любым пользователем, включая администратора.
— В некоторых конфигурациях — выполнить команды на уровне операционной системы через функции вроде `LOAD_FILE` или `INTO OUTFILE`.
— Провести атаку на другие системы, используя сервер БД как плацдарм.
**Как правильно защититься**
1. **Использовать подготовленные выражения (PDO или MySQLi):** Данные и SQL-код передаются раздельно, поэтому СУБД не может интерпретировать пользовательский ввод как часть запроса.
php
$stmt = $pdo->prepare(«SELECT * FROM users WHERE username = ?»);
$stmt->execute([$username]);
2. **Валидировать входные данные:** Проверять тип, длину и формат данных до их использования.
3. **Использовать ORM:** Фреймворки вроде Eloquent или Doctrine автоматически экранируют запросы.
4. **Принцип минимальных привилегий:** Пользователь базы данных должен иметь только те права, которые необходимы для работы приложения.
5. **Не отображать SQL-ошибки пользователю:** Это лишает злоумышленника ценной информации о структуре базы.
**Вывод**
Прямая подстановка пользовательских данных в SQL-запрос — это архитектурная ошибка, а не просто небрежность. Современные инструменты (PDO, MySQLi с prepared statements) полностью решают эту проблему, и их использование является обязательным стандартом разработки безопасных приложений.
