Завершаем проект разбором первопричины и рекомендациями — это то, что отличает "просто взломал учебную лабу" от полноценного анализа безопасности.
В исходном коде DVWA (уровень Low) запрос строится через прямую конкатенацию строк:
$query = "SELECT first_name, last_name FROM users WHERE user_id = '$id';";Значение $id берётся напрямую из GET-параметра без экранирования и без валидации —
это классический пример конкатенации пользовательского ввода в SQL-запрос.
| Уязвимость | Рекомендация |
|---|---|
| Конкатенация ввода в SQL-запрос | Использовать подготовленные выражения (prepared statements) / параметризованные запросы |
| Отсутствие валидации входных данных | Валидировать тип и формат id (например, приводить к int) до использования в запросе |
| Избыточные права БД-пользователя | Использовать принцип наименьших привилегий — отдельный пользователь БД без прав на DROP/ALTER |
| WAF как единственная защита | Не полагаться только на WAF — он обходится (см. Этап 5); WAF должен быть дополнительным слоем, а не заменой безопасного кода |
| Подробные сообщения об ошибках БД | Отключать вывод детальных SQL-ошибок пользователю в продакшене (display_errors=Off), логировать их отдельно |
$stmt = $pdo->prepare("SELECT first_name, last_name FROM users WHERE user_id = :id");
$stmt->execute(['id' => $id]);Параметризованный запрос отделяет код запроса от данных — СУБД никогда не интерпретирует
$id как часть SQL-синтаксиса, независимо от того, что в нём передано.
Заполнить после прохождения всех этапов: 2-3 предложения — что показал проект, какие навыки продемонстрированы (recon → эксплуатация → обход защиты → рекомендации по фиксу).