Чем опасно - В текущем коде строка SQL собирается конкатенацией с прямым использованием пользовательского ввода: \(q = "SELECT * FROM users WHERE name='".$_GET['name']."'";\) Это позволяет атакующему подставить в параметр произвольный SQL-код (SQL‑инъекция). Последствия: обход аутентификации, утечка/изменение/удаление данных, получение привилегий, выполнение вредоносных команд через БД. Простой пример атаки - Если запрос в URL: `?name=admin' OR '1'='1` Получается SQL: `SELECT * FROM users WHERE name='admin' OR '1'='1'` — вернёт все строки (аутентификация может быть обойдена). - Или `name=a'; DROP TABLE users; -- ` — если разрешены мультизапросы, это может удалить таблицу. Как правильно исправить (рекомендация) 1) Использовать подготовленные выражения (prepared statements) с параметрами — это надёжно и просто. Пример на PDO: ``` $pdo = new PDO($dsn, $user, $pass, [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]); $pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); $stmt = $pdo->prepare("SELECT * FROM users WHERE name = :name"); $stmt->execute(['name' => $_GET['name']]); $user = $stmt->fetch(PDO::FETCH_ASSOC); ``` Пример на mysqli: ``` $stmt = $mysqli->prepare("SELECT * FROM users WHERE name = ?"); $stmt->bind_param('s', $_GET['name']); $stmt->execute(); $result = $stmt->get_result(); $user = $result->fetch_assoc(); ``` 2) Дополнительные меры (всегда в комбинации): - Валидация/вочлистинг входных данных (если имя — только буквы, применить регулярное ограничение). - Использовать минимально необходимые привилегии для учётной записи БД (не root). - Не возвращать `SELECT *`, перечислять только нужные поля. - Логирование подозрительных запросов и ограничение количества результатов. - На выводе в HTML — экранировать данные (prevent XSS), но это не заменяет параметризацию для SQL. 3) Что не стоит полагаться как основное: - Ручное экранирование (`mysqli_real_escape_string`) — работает, но менее надёжно и легко ошибочно применяется; предпочтительны подготовленные выражения. Кратко: не конкатенируйте пользовательский ввод в SQL — используйте параметризованные запросы (prepared statements), валидацию и принцип наименьших привилегий.
- В текущем коде строка SQL собирается конкатенацией с прямым использованием пользовательского ввода:
\(q = "SELECT * FROM users WHERE name='".$_GET['name']."'";\)
Это позволяет атакующему подставить в параметр произвольный SQL-код (SQL‑инъекция). Последствия: обход аутентификации, утечка/изменение/удаление данных, получение привилегий, выполнение вредоносных команд через БД.
Простой пример атаки
- Если запрос в URL: `?name=admin' OR '1'='1`
Получается SQL: `SELECT * FROM users WHERE name='admin' OR '1'='1'` — вернёт все строки (аутентификация может быть обойдена).
- Или `name=a'; DROP TABLE users; -- ` — если разрешены мультизапросы, это может удалить таблицу.
Как правильно исправить (рекомендация)
1) Использовать подготовленные выражения (prepared statements) с параметрами — это надёжно и просто.
Пример на PDO:
```
$pdo = new PDO($dsn, $user, $pass, [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$stmt = $pdo->prepare("SELECT * FROM users WHERE name = :name");
$stmt->execute(['name' => $_GET['name']]);
$user = $stmt->fetch(PDO::FETCH_ASSOC);
```
Пример на mysqli:
```
$stmt = $mysqli->prepare("SELECT * FROM users WHERE name = ?");
$stmt->bind_param('s', $_GET['name']);
$stmt->execute();
$result = $stmt->get_result();
$user = $result->fetch_assoc();
```
2) Дополнительные меры (всегда в комбинации):
- Валидация/вочлистинг входных данных (если имя — только буквы, применить регулярное ограничение).
- Использовать минимально необходимые привилегии для учётной записи БД (не root).
- Не возвращать `SELECT *`, перечислять только нужные поля.
- Логирование подозрительных запросов и ограничение количества результатов.
- На выводе в HTML — экранировать данные (prevent XSS), но это не заменяет параметризацию для SQL.
3) Что не стоит полагаться как основное:
- Ручное экранирование (`mysqli_real_escape_string`) — работает, но менее надёжно и легко ошибочно применяется; предпочтительны подготовленные выражения.
Кратко: не конкатенируйте пользовательский ввод в SQL — используйте параметризованные запросы (prepared statements), валидацию и принцип наименьших привилегий.