Проанализируйте уязвимость SQL-инъекции в следующем PHP-примере: $query = "SELECT * FROM users WHERE name = '".$_GET['name']."'"; — объясните, почему это опасно, и опишите шаги по устранению и защите на уровне архитектуры
Почему опасно (коротко) - Встроенная конкатенация пользовательского ввода в SQL позволяет злоумышленнику изменить структуру запроса — выполнить чтение/изменение данных, обход аутентификации, удаление таблиц или извлечение паролей. - Пример уязвимого запроса: \(`$query = "SELECT * FROM users WHERE name = '".$_GET['name']."'";`\). Примеры атак (payloadы) - Получить всех пользователей: если `name = ' OR '1'='1` запрос станет SELECT∗FROMusersWHEREname=′′OR′1′=′1′SELECT * FROM users WHERE name = '' OR '1'='1'SELECT∗FROMusersWHEREname=′′OR′1′=′1′
— вернёт все строки. - Выполнить вредоносный SQL (при разрешённых множественных запросах): `name = x'; DROP TABLE users; -- ` SELECT∗FROMusersWHEREname=′x′;DROPTABLEusers;−−′SELECT * FROM users WHERE name = 'x'; DROP TABLE users; -- 'SELECT∗FROMusersWHEREname=′x′;DROPTABLEusers;−−′
- Время‑ориентированная экстракция (blind SQLi): `name = ' OR IF(SUBSTRING(password,1,1)='a', SLEEP(5),0) -- ` Как устранить (код и практики) 1. Параметризованные запросы (prepared statements) — основной и надёжный способ. - PDO (рекомендуется): \[`$stmt = $pdo->prepare("SELECT * FROM users WHERE name = :name");` `$stmt->execute([':name' => $_GET['name']]);` `$user = $stmt->fetch();`\] - mysqli: \[`$stmt = $mysqli->prepare("SELECT * FROM users WHERE name = ?");` `$stmt->bind_param("s", $_GET['name']);` `$stmt->execute();`\] 2. Белый список и валидация: - Если ожидается конкретный формат (имя, id, email), валидируйте/нормализуйте: регулярные выражения, приведение типов (intintint для id). - Отдавайте предпочтение валидации/нормализации над попытками «очистить» ввод. 3. Экранирование — только как запасной вариант: - `mysqli_real_escape_string()` — допустимо, если нет возможности использовать подготовленные выражения, но это менее надёжно и легко ошибиться. 4. Ограничение прав БД: - Приложение должно подключаться под пользователем с минимумом привилегий (SELECT/INSERT/UPDATE только на нужные таблицы). - Отключить выполнение множественных операторов, если не требуется. 5. Обработка ошибок: - Не возвращать подробные SQL‑ошибки в ответ пользователю. Логи — в защищённое хранилище. Архитектурные меры и защита на уровне системы - Централизованный слой доступа к данным (DAO/Repository/ORM): предотвращает раскиданные ad‑hoc SQL и упрощает применение параметризации везде. - Использование ORM/Query Builder (например, Doctrine, Eloquent) — они по умолчанию параметризуют запросы. - Входной фильтр/валидатор на уровне API шлюза: базовая валидация и нормализация до попадания в сервисы. - WAF (Web Application Firewall) и IDS/IPS: блокировка известных атак и подозрительных паттернов, защита от массовых попыток. - Мониторинг и логирование запросов и аномалий (не хранить чувствительные данные в логах). - Политика управления секретами и ротация учётных записей БД. - Минимизация возвращаемых данных и применение постраничности (limit), чтобы уменьшить ущерб при утечке. - Ревью кода и автоматизированное сканирование на уязвимости (SAST/DAST). Короткое резюме - Не вставляйте напрямую пользовательский ввод в SQL. Используйте подготовленные выражения (PDO/mysqli), валидацию по белому списку, минимальные привилегии БД и централизованный слой доступа к данным. Дополнительно — WAF, мониторинг и регулярные аудиты.
- Встроенная конкатенация пользовательского ввода в SQL позволяет злоумышленнику изменить структуру запроса — выполнить чтение/изменение данных, обход аутентификации, удаление таблиц или извлечение паролей.
- Пример уязвимого запроса: \(`$query = "SELECT * FROM users WHERE name = '".$_GET['name']."'";`\).
Примеры атак (payloadы)
- Получить всех пользователей: если `name = ' OR '1'='1` запрос станет
SELECT∗FROMusersWHEREname=′′OR′1′=′1′SELECT * FROM users WHERE name = '' OR '1'='1'SELECT∗FROMusersWHEREname=′′OR′1′=′1′ — вернёт все строки.
- Выполнить вредоносный SQL (при разрешённых множественных запросах): `name = x'; DROP TABLE users; -- `
SELECT∗FROMusersWHEREname=′x′;DROPTABLEusers;−−′SELECT * FROM users WHERE name = 'x'; DROP TABLE users; -- 'SELECT∗FROMusersWHEREname=′x′;DROPTABLEusers;−−′ - Время‑ориентированная экстракция (blind SQLi): `name = ' OR IF(SUBSTRING(password,1,1)='a', SLEEP(5),0) -- `
Как устранить (код и практики)
1. Параметризованные запросы (prepared statements) — основной и надёжный способ.
- PDO (рекомендуется):
\[`$stmt = $pdo->prepare("SELECT * FROM users WHERE name = :name");`
`$stmt->execute([':name' => $_GET['name']]);`
`$user = $stmt->fetch();`\]
- mysqli:
\[`$stmt = $mysqli->prepare("SELECT * FROM users WHERE name = ?");`
`$stmt->bind_param("s", $_GET['name']);`
`$stmt->execute();`\]
2. Белый список и валидация:
- Если ожидается конкретный формат (имя, id, email), валидируйте/нормализуйте: регулярные выражения, приведение типов (intintint для id).
- Отдавайте предпочтение валидации/нормализации над попытками «очистить» ввод.
3. Экранирование — только как запасной вариант:
- `mysqli_real_escape_string()` — допустимо, если нет возможности использовать подготовленные выражения, но это менее надёжно и легко ошибиться.
4. Ограничение прав БД:
- Приложение должно подключаться под пользователем с минимумом привилегий (SELECT/INSERT/UPDATE только на нужные таблицы).
- Отключить выполнение множественных операторов, если не требуется.
5. Обработка ошибок:
- Не возвращать подробные SQL‑ошибки в ответ пользователю. Логи — в защищённое хранилище.
Архитектурные меры и защита на уровне системы
- Централизованный слой доступа к данным (DAO/Repository/ORM): предотвращает раскиданные ad‑hoc SQL и упрощает применение параметризации везде.
- Использование ORM/Query Builder (например, Doctrine, Eloquent) — они по умолчанию параметризуют запросы.
- Входной фильтр/валидатор на уровне API шлюза: базовая валидация и нормализация до попадания в сервисы.
- WAF (Web Application Firewall) и IDS/IPS: блокировка известных атак и подозрительных паттернов, защита от массовых попыток.
- Мониторинг и логирование запросов и аномалий (не хранить чувствительные данные в логах).
- Политика управления секретами и ротация учётных записей БД.
- Минимизация возвращаемых данных и применение постраничности (limit), чтобы уменьшить ущерб при утечке.
- Ревью кода и автоматизированное сканирование на уязвимости (SAST/DAST).
Короткое резюме
- Не вставляйте напрямую пользовательский ввод в SQL. Используйте подготовленные выражения (PDO/mysqli), валидацию по белому списку, минимальные привилегии БД и централизованный слой доступа к данным. Дополнительно — WAF, мониторинг и регулярные аудиты.