Найдите уязвимость в этом PHP-скрипте: $q = "SELECT * FROM users WHERE name = '".$_GET['name']."'"; $r = mysqli_query($db, $q); — объясните, какие атаки возможны, как исправить код (prepared statements, ORM, валидация), рассмотрите дополнительные меры (права БД, логирование, WAF) и последствия безопасности в дизайне API
Уязвимость: SQL‑инъекция. Код напрямую конкатенирует пользовательский ввод в SQL: q = "SELECT * FROM users WHERE name = '".$_GET['name']."'" Это позволяет злоумышленнику изменить структуру запроса. Какие атаки возможны (кратко): - Получение данных: извлечение дополнительных строк/таблиц (UNION, раскрытие колонок). - Аутентификация/авторизация: обход проверки (например, логин по условию всегда истинно). - Блайнд‑инъекции (time‑/boolean‑based) — вытянуть данные по времени/ошибкам. - Изменение/удаление данных при разрешении нескольких запросов (stacked queries), если разрешены. - Информационные утечки через ошибки SQL и поведение API. - Эскалация в дальнейшие атаки (получение паролей, доступ к внутренним системам). Как исправить (приоритеты): 1) Подготовленные выражения (parameterized statements) — самый надёжный способ. Пример mysqli: $rq = $db->prepare("SELECT * FROM users WHERE name = ?"); $rq->bind_param("s", $_GET['name']); $rq->execute(); $res = $rq->get_result(); Пример PDO: $sth = $pdo->prepare("SELECT * FROM users WHERE name = :name"); $sth->execute([':name' => $_GET['name']]); $rows = $sth->fetchAll(); 2) ORM/абстракция запросов — Eloquent, Doctrine и т.п. автоматически параметризуют запросы и уменьшают шанс ошибок, но проверяйте, как ORM формирует запросы для сложных выражений. 3) Валидация и нормализация входа: - Whitelist (разрешённые шаблоны) предпочтительнее black‑list. Например, если name — только буквы/пробелы: проверить `preg_match('/^[\p{L}\s]{1,100}$/u', $name)`. - Ограничение длины и кодировки. - Для чисел — явно приведение к int. 4) Если по каким‑то причинам нельзя сразу перейти на prepared statements — как временный шаг можно использовать escaping: $name = mysqli_real_escape_string($db, $_GET['name']); но это менее надёжно и не заменяет параметризацию. Дополнительные меры безопасности: - Права БД: least privilege — пользователь БД должен иметь только нужные права (SELECT/INSERT/UPDATE/DELETE только на нужные таблицы; без права DROP, GRANT и т.д.). - Отключить/не использовать мульти‑запросы (stacked queries) на уровне приложения/драйвера. - Логирование и мониторинг: логировать аномальные запросы/ошибки, настроить оповещения по частым ошибкам/повторным попыткам. - WAF (Web Application Firewall): блокировка известных паттернов инъекций и rate‑limit. - Безопасные сообщения об ошибках: не отдавать пользователю сырые SQL‑ошибки. - Шифрование чувствительных данных в БД и защита каналов (TLS). Последствия для дизайна API: - Нельзя доверять клиенту: вся валидация и авторизация — на сервере. - Ограничивайте возвращаемые поля (не возвращайте пароли/хэши). - Используйте пагинацию/лимиты, чтобы уменьшить эффект инъекции (например, LIMIT). - Разделение прав доступа по ролям и проверка каждого запроса (RBAC). - Проектируйте API так, чтобы сложные динамические запросы не конструировались строковой конкатенацией; используйте абстракции/фильтры с чёткой схемой полей, разрешённых для фильтрации/сортировки. Краткое резюме: - Проблема: SQL‑инъекция из-за конкатенации $_GET['name']. - Решение: в первую очередь — подготовленные выражения (parameterized queries) или ORM; дополнительно — строгая валидация, минимальные права БД, логирование и WAF; в дизайне API — серверная валидация, минимизация выдачи данных и управление правами.
q = "SELECT * FROM users WHERE name = '".$_GET['name']."'"
Это позволяет злоумышленнику изменить структуру запроса.
Какие атаки возможны (кратко):
- Получение данных: извлечение дополнительных строк/таблиц (UNION, раскрытие колонок).
- Аутентификация/авторизация: обход проверки (например, логин по условию всегда истинно).
- Блайнд‑инъекции (time‑/boolean‑based) — вытянуть данные по времени/ошибкам.
- Изменение/удаление данных при разрешении нескольких запросов (stacked queries), если разрешены.
- Информационные утечки через ошибки SQL и поведение API.
- Эскалация в дальнейшие атаки (получение паролей, доступ к внутренним системам).
Как исправить (приоритеты):
1) Подготовленные выражения (parameterized statements) — самый надёжный способ.
Пример mysqli:
$rq = $db->prepare("SELECT * FROM users WHERE name = ?");
$rq->bind_param("s", $_GET['name']);
$rq->execute();
$res = $rq->get_result();
Пример PDO:
$sth = $pdo->prepare("SELECT * FROM users WHERE name = :name");
$sth->execute([':name' => $_GET['name']]);
$rows = $sth->fetchAll();
2) ORM/абстракция запросов — Eloquent, Doctrine и т.п. автоматически параметризуют запросы и уменьшают шанс ошибок, но проверяйте, как ORM формирует запросы для сложных выражений.
3) Валидация и нормализация входа:
- Whitelist (разрешённые шаблоны) предпочтительнее black‑list. Например, если name — только буквы/пробелы: проверить `preg_match('/^[\p{L}\s]{1,100}$/u', $name)`.
- Ограничение длины и кодировки.
- Для чисел — явно приведение к int.
4) Если по каким‑то причинам нельзя сразу перейти на prepared statements — как временный шаг можно использовать escaping:
$name = mysqli_real_escape_string($db, $_GET['name']);
но это менее надёжно и не заменяет параметризацию.
Дополнительные меры безопасности:
- Права БД: least privilege — пользователь БД должен иметь только нужные права (SELECT/INSERT/UPDATE/DELETE только на нужные таблицы; без права DROP, GRANT и т.д.).
- Отключить/не использовать мульти‑запросы (stacked queries) на уровне приложения/драйвера.
- Логирование и мониторинг: логировать аномальные запросы/ошибки, настроить оповещения по частым ошибкам/повторным попыткам.
- WAF (Web Application Firewall): блокировка известных паттернов инъекций и rate‑limit.
- Безопасные сообщения об ошибках: не отдавать пользователю сырые SQL‑ошибки.
- Шифрование чувствительных данных в БД и защита каналов (TLS).
Последствия для дизайна API:
- Нельзя доверять клиенту: вся валидация и авторизация — на сервере.
- Ограничивайте возвращаемые поля (не возвращайте пароли/хэши).
- Используйте пагинацию/лимиты, чтобы уменьшить эффект инъекции (например, LIMIT).
- Разделение прав доступа по ролям и проверка каждого запроса (RBAC).
- Проектируйте API так, чтобы сложные динамические запросы не конструировались строковой конкатенацией; используйте абстракции/фильтры с чёткой схемой полей, разрешённых для фильтрации/сортировки.
Краткое резюме:
- Проблема: SQL‑инъекция из-за конкатенации $_GET['name'].
- Решение: в первую очередь — подготовленные выражения (parameterized queries) или ORM; дополнительно — строгая валидация, минимальные права БД, логирование и WAF; в дизайне API — серверная валидация, минимизация выдачи данных и управление правами.