Найдите уязвимость в PHP-фрагменте: $q = "SELECT * FROM users WHERE name = '".$_GET['name']."'"; — расскажите о рисках SQL-инъекции и дайте безопасные альтернативы
Уязвимость: в фрагменте строка запроса строится конкатенацией пользовательского ввода без фильтрации: $q = "SELECT * FROM users WHERE name = '".$_GET['name']."'"; Почему это плохо (SQL‑инъекция): - Злоумышленник может подставить payload, разрушающий синтаксис и добавляющий свои условия. Например, при значении параметра name = ` ' OR 1=1 -- ` итоговый запрос станет SELECT * FROM users WHERE name = '' OR 111=111 -- ' что вернёт все записи (авторизация/фильтрация обходятся). - Возможные риски: утечка всех данных таблицы/БД, обход аутентификации, изменение/удаление данных, выполнение произвольных запросов (вплоть до удалённого выполнения команд при наличии уязвимостей СУБД). - Дополнительные проблемы: логирование вредоносных запросов, поддержка дальнейших атак (privilege escalation, pivoting). Безопасные альтернативы (рекомендуется параметризованные запросы + валидация и права): 1) PDO (рекомендуемый способ) ``` $pdo = new PDO(...); $stmt = $pdo->prepare("SELECT * FROM users WHERE name = :name"); $stmt->execute(['name' => $_GET['name']]); $rows = $stmt->fetchAll(); ``` 2) mysqli с prepared statements ``` $mysqli = new mysqli(...); $stmt = $mysqli->prepare("SELECT * FROM users WHERE name = ?"); $stmt->bind_param("s", $_GET['name']); $stmt->execute(); $result = $stmt->get_result(); ``` 3) Если по каким‑то причинам параметризовать нельзя — экранируйте (как крайняя мера) ``` $name = $mysqli->real_escape_string($_GET['name']); $q = "SELECT * FROM users WHERE name = '$name'"; ``` Но real_escape_string ненадёжен при неправильной кодировке и уступает подготовленным выражениям. Дополнительные меры: - Входная валидация / allowlist (например, ограничить длину, разрешённые символы). - Минимизировать привилегии БД-пользователя (только доступ, необходимый для операции). - Логирование и мониторинг подозрительных запросов. - Использовать ORM/библиотеки, которые по умолчанию параметризуют запросы. Вывод: не конкатенируйте $_GET напрямую в SQL — используйте подготовленные выражения (PDO/mysqli) и валидацию входных данных.
$q = "SELECT * FROM users WHERE name = '".$_GET['name']."'";
Почему это плохо (SQL‑инъекция):
- Злоумышленник может подставить payload, разрушающий синтаксис и добавляющий свои условия. Например, при значении параметра name = ` ' OR 1=1 -- ` итоговый запрос станет
SELECT * FROM users WHERE name = '' OR 111=111 -- '
что вернёт все записи (авторизация/фильтрация обходятся).
- Возможные риски: утечка всех данных таблицы/БД, обход аутентификации, изменение/удаление данных, выполнение произвольных запросов (вплоть до удалённого выполнения команд при наличии уязвимостей СУБД).
- Дополнительные проблемы: логирование вредоносных запросов, поддержка дальнейших атак (privilege escalation, pivoting).
Безопасные альтернативы (рекомендуется параметризованные запросы + валидация и права):
1) PDO (рекомендуемый способ)
```
$pdo = new PDO(...);
$stmt = $pdo->prepare("SELECT * FROM users WHERE name = :name");
$stmt->execute(['name' => $_GET['name']]);
$rows = $stmt->fetchAll();
```
2) mysqli с prepared statements
```
$mysqli = new mysqli(...);
$stmt = $mysqli->prepare("SELECT * FROM users WHERE name = ?");
$stmt->bind_param("s", $_GET['name']);
$stmt->execute();
$result = $stmt->get_result();
```
3) Если по каким‑то причинам параметризовать нельзя — экранируйте (как крайняя мера)
```
$name = $mysqli->real_escape_string($_GET['name']);
$q = "SELECT * FROM users WHERE name = '$name'";
```
Но real_escape_string ненадёжен при неправильной кодировке и уступает подготовленным выражениям.
Дополнительные меры:
- Входная валидация / allowlist (например, ограничить длину, разрешённые символы).
- Минимизировать привилегии БД-пользователя (только доступ, необходимый для операции).
- Логирование и мониторинг подозрительных запросов.
- Использовать ORM/библиотеки, которые по умолчанию параметризуют запросы.
Вывод: не конкатенируйте $_GET напрямую в SQL — используйте подготовленные выражения (PDO/mysqli) и валидацию входных данных.