Напишите и объясните SQL-инъекцию для уязвимого запроса в PHP: $q = "SELECT * FROM users WHERE name='".$_GET['name']."'"; — как её обнаружить, продемонстрировать и как правильно исправить в рамках текущего кода
Коротко: уязвимость — конкатенация ненадёжного входа в SQL-запрос. Это позволяет злоумышленнику изменить синтаксис запроса (например, добавить логическое условие) и получить/изменить данные. 1) Что происходит и демонстрация (в безопасной тестовой среде только) - Исходный код: $q = "SELECT * FROM users WHERE name='".$_GET['name']."'"; - Если в тесте задать параметр name = x' OR '1'='1, то итоговый SQL станет: SELECT * FROM users WHERE name='x' OR '1'='1' (логическое условие ′1′=′1′ '1'='1' ′1′=′1′ всегда истинно, поэтому запрос вернёт все строки) — это иллюстрация того, как ввод ломает структуру запроса. Тестировать можно только на собственных/тестовых БД с разрешения владельца. 2) Как обнаружить - Ревью кода: искать конкатенацию строк с внешними данными (GET/POST/cookie) при формировании SQL. - Поведение приложения: неожиданный большой набор результатов при вводе специальных символов (кавычки, OR, --). - Логирование/мониторинг SQL-запросов: очевидные вставки из входа пользователя. - Автотестирование/пентесты — только с разрешения; используйте тестовые стенды и инструменты сканирования в контролируемой среде. 3) Как правильно исправить (в рамках текущего кода) - Использовать подготовленные выражения (prepared statements) и параметризацию вместо конкатенации. Пример с mysqli: $mysqli = new mysqli($host, $user, $pass, $db); $stmt = $mysqli->prepare("SELECT * FROM users WHERE name = ?"); $stmt->bind_param("s", $_GET['name']); $stmt->execute(); $result = $stmt->get_result(); Пример с PDO: $pdo = new PDO($dsn, $user, $pass, [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]); $stmt = $pdo->prepare("SELECT * FROM users WHERE name = ?"); $stmt->execute([$_GET['name']]); $rows = $stmt->fetchAll(PDO::FETCH_ASSOC); Пояснение: параметризация передаёт значение отдельно от SQL-синтаксиса, поэтому любые кавычки или ключевые слова в вводе рассматриваются как данные, а не как часть запроса. 4) Дополнительные меры (рекомендации) - Валидация и белый список: при возможности проверять формат/длину/символы имени до запроса. - Минимальные привилегии для DB-пользователя (чтение/запись только где нужно). - Логирование аномалий и внедрение WAF/IDS на уровне приложения/инфраструктуры. - Регулярные ревью безопасности и тесты на тестовом окружении. Важно: не выполняйте демонстрационные payload'ы против чужих систем без явного разрешения — это незаконно.
1) Что происходит и демонстрация (в безопасной тестовой среде только)
- Исходный код:
$q = "SELECT * FROM users WHERE name='".$_GET['name']."'";
- Если в тесте задать параметр name = x' OR '1'='1, то итоговый SQL станет:
SELECT * FROM users WHERE name='x' OR '1'='1'
(логическое условие ′1′=′1′ '1'='1' ′1′=′1′ всегда истинно, поэтому запрос вернёт все строки)
— это иллюстрация того, как ввод ломает структуру запроса. Тестировать можно только на собственных/тестовых БД с разрешения владельца.
2) Как обнаружить
- Ревью кода: искать конкатенацию строк с внешними данными (GET/POST/cookie) при формировании SQL.
- Поведение приложения: неожиданный большой набор результатов при вводе специальных символов (кавычки, OR, --).
- Логирование/мониторинг SQL-запросов: очевидные вставки из входа пользователя.
- Автотестирование/пентесты — только с разрешения; используйте тестовые стенды и инструменты сканирования в контролируемой среде.
3) Как правильно исправить (в рамках текущего кода)
- Использовать подготовленные выражения (prepared statements) и параметризацию вместо конкатенации.
Пример с mysqli:
$mysqli = new mysqli($host, $user, $pass, $db);
$stmt = $mysqli->prepare("SELECT * FROM users WHERE name = ?");
$stmt->bind_param("s", $_GET['name']);
$stmt->execute();
$result = $stmt->get_result();
Пример с PDO:
$pdo = new PDO($dsn, $user, $pass, [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);
$stmt = $pdo->prepare("SELECT * FROM users WHERE name = ?");
$stmt->execute([$_GET['name']]);
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
Пояснение: параметризация передаёт значение отдельно от SQL-синтаксиса, поэтому любые кавычки или ключевые слова в вводе рассматриваются как данные, а не как часть запроса.
4) Дополнительные меры (рекомендации)
- Валидация и белый список: при возможности проверять формат/длину/символы имени до запроса.
- Минимальные привилегии для DB-пользователя (чтение/запись только где нужно).
- Логирование аномалий и внедрение WAF/IDS на уровне приложения/инфраструктуры.
- Регулярные ревью безопасности и тесты на тестовом окружении.
Важно: не выполняйте демонстрационные payload'ы против чужих систем без явного разрешения — это незаконно.