Проанализируйте уязвимый PHP-фрагмент: $q = "SELECT * FROM users WHERE name='".$_GET['name']."'"; $res = mysql_query($q); — опишите виды атак (SQL-инъекция) с конкретными полезными нагрузками, предложите безопасную реализацию (подготовленные выражения, ORM, валидация), обсудите принцип минимизации привилегий и дополнительные меры защиты (WAF, мониторинг, журналирование)
Короткий вывод о проблеме - Уязвимый фрагмент строит SQL-конкатенацией: \(q = "SELECT * FROM users WHERE name='".$_GET['name']."'";\) — это прямой путь к SQL‑инъекции. Любой ввод пользователя попадает в запрос без экранирования/параметризации. Типы атак и примерные полезные нагрузки (только для тестирования на ваших/авторизованных системах) - Аутентификация/обход фильтров (всегда истинно): - payload: `' OR '111'='111' -- ` - результат: WHERE name='' OR '1'='1' — вернёт все строки. - UNION‑эксфильтрация данных: - payload: `' UNION SELECT username, password FROM users -- ` - результат: объединяет результаты другого SELECT. - Стекированные запросы (если включены MULTI_STATEMENTS): - payload: `'; DROP TABLE users; -- ` - результат: удаление таблицы. - Базовые (ошибко‑/информационные) инъекции: - payload: `"' OR (SELECT COUNT(*) FROM information_schema.tables)>'000' -- "` - Байн‑булевые (побайтовое определение символов пароля): - payload: `"' AND SUBSTRING(password,111,111)='a' -- "` - Временные (time‑based blind): - payload: `"' OR IF(SUBSTRING(password,111,111)='a', SLEEP(555), 0) -- "` - полезно, когда нет вывода, но есть задержка — цифры в KaTeX. Безопасная реализация (рекомендации) 1) Параметризованные запросы (PDO пример): - Используйте PDO с подготовленными выражениями: - $pdo = new PDO(...); - $stmt = $pdo->prepare("SELECT * FROM users WHERE name = :name"); - $stmt->execute(['name' => $_GET['name']]); - Подготовленные выражения отделяют структуру SQL от данных и полностью предотвращают инъекции. 2) MySQLi (prepared statements) — альтернатива, если не PDO: - $stmt = $mysqli->prepare("SELECT * FROM users WHERE name = ?"); - $stmt->bind_param("s", $name); - $stmt->execute(); 3) ORM (Eloquent, Doctrine и т.п.): - ORM обычно генерирует параметризованные запросы: e.g. User::where('name', $name)->get(); - ORM не заменяет валидацию, но снижает риск ручных ошибок. 4) Валидация и whitelist: - По возможности принимайте только ожидаемые форматы: например имя — буквы/цифры/нижнее подчёркивание, длина — до 50\,5050 символов. - Пример проверки: если ожидается простой логин — reject при несоответствии регулярному выражению. - Проверяйте длину, кодировку, запрещайте управляющие символы. 5) Экранирование — запасной механизм: - mysqli_real_escape_string() — ненадёжно как единственный метод; используйте только если невозможно параметризовать, и понимайте границы. 6) Отказ от mysql_*: - mysql_query и расширение mysql_* устарели и удалены в современных PHP; используйте PDO или mysqli. Принцип минимизации привилегий - БД‑пользователь приложения должен иметь минимально необходимые права: - для выборки — только SELECT на нужные таблицы. - не давать права DROP, CREATE, GRANT, ALTER, SHOW DATABASES и т.п. - Настройте отдельного пользователя для административных задач с ограниченным доступом по IP/ключам. Дополнительные меры защиты - Веб‑приложение: - WAF (Web Application Firewall) — блокирует известные паттерны инъекций и автоматические атаки. - Ограничение количества запросов / rate limiting. - Content Security Policy, минимизация клиент‑сайд рисков. - Инфраструктура: - Отключить MULTI_STATEMENTS если не нужны. - Включить безопасные SQL‑режимы (например strict modes). - Логирование и мониторинг: - Логировать аномалии запросов, ошибки SQL, неудачные попытки входа. - Настроить оповещения при всплесках 4xx/5xx, подозрительных паттернах. - Соблюдать баланс: не логировать пароли/секреты в открытом виде. - Тестирование и деплой: - Регулярные автоматизированные и ручные тесты на инъекции (SAST/DAST) — только на авторизованных окружениях. - Code review и CI проверки безопасности. - Обновления: - Держать СУБД и библиотеки в актуальном состоянии. Краткий практический пример (PDO + валидация) - Принцип: валидируем вход, используем подготовленное выражение, минимизируем привилегии: - $name = $_GET['name'] ?? ''; - if (!preg_match('/^[A-Za-z0-9_-]{1,50}$/', $name)) { /* error */ } - $stmt = $pdo->prepare("SELECT id, name, email FROM users WHERE name = :name"); - $stmt->execute(['name' => $name]); Заключение - Главный защитный механизм — параметризованные запросы + валидация. Дополняйте минимальными привилегиями БД, мониторингом, WAF и регулярным тестированием. Использование mysql_* в текущем коде — критическая уязвимость, её следует заменить на PDO/mysqli и пройти рефакторинг всего ввода данных.
- Уязвимый фрагмент строит SQL-конкатенацией: \(q = "SELECT * FROM users WHERE name='".$_GET['name']."'";\) — это прямой путь к SQL‑инъекции. Любой ввод пользователя попадает в запрос без экранирования/параметризации.
Типы атак и примерные полезные нагрузки (только для тестирования на ваших/авторизованных системах)
- Аутентификация/обход фильтров (всегда истинно):
- payload: `' OR '111'='111' -- `
- результат: WHERE name='' OR '1'='1' — вернёт все строки.
- UNION‑эксфильтрация данных:
- payload: `' UNION SELECT username, password FROM users -- `
- результат: объединяет результаты другого SELECT.
- Стекированные запросы (если включены MULTI_STATEMENTS):
- payload: `'; DROP TABLE users; -- `
- результат: удаление таблицы.
- Базовые (ошибко‑/информационные) инъекции:
- payload: `"' OR (SELECT COUNT(*) FROM information_schema.tables)>'000' -- "`
- Байн‑булевые (побайтовое определение символов пароля):
- payload: `"' AND SUBSTRING(password,111,111)='a' -- "`
- Временные (time‑based blind):
- payload: `"' OR IF(SUBSTRING(password,111,111)='a', SLEEP(555), 0) -- "`
- полезно, когда нет вывода, но есть задержка — цифры в KaTeX.
Безопасная реализация (рекомендации)
1) Параметризованные запросы (PDO пример):
- Используйте PDO с подготовленными выражениями:
- $pdo = new PDO(...);
- $stmt = $pdo->prepare("SELECT * FROM users WHERE name = :name");
- $stmt->execute(['name' => $_GET['name']]);
- Подготовленные выражения отделяют структуру SQL от данных и полностью предотвращают инъекции.
2) MySQLi (prepared statements) — альтернатива, если не PDO:
- $stmt = $mysqli->prepare("SELECT * FROM users WHERE name = ?");
- $stmt->bind_param("s", $name);
- $stmt->execute();
3) ORM (Eloquent, Doctrine и т.п.):
- ORM обычно генерирует параметризованные запросы: e.g. User::where('name', $name)->get();
- ORM не заменяет валидацию, но снижает риск ручных ошибок.
4) Валидация и whitelist:
- По возможности принимайте только ожидаемые форматы: например имя — буквы/цифры/нижнее подчёркивание, длина — до 50\,5050 символов.
- Пример проверки: если ожидается простой логин — reject при несоответствии регулярному выражению.
- Проверяйте длину, кодировку, запрещайте управляющие символы.
5) Экранирование — запасной механизм:
- mysqli_real_escape_string() — ненадёжно как единственный метод; используйте только если невозможно параметризовать, и понимайте границы.
6) Отказ от mysql_*:
- mysql_query и расширение mysql_* устарели и удалены в современных PHP; используйте PDO или mysqli.
Принцип минимизации привилегий
- БД‑пользователь приложения должен иметь минимально необходимые права:
- для выборки — только SELECT на нужные таблицы.
- не давать права DROP, CREATE, GRANT, ALTER, SHOW DATABASES и т.п.
- Настройте отдельного пользователя для административных задач с ограниченным доступом по IP/ключам.
Дополнительные меры защиты
- Веб‑приложение:
- WAF (Web Application Firewall) — блокирует известные паттерны инъекций и автоматические атаки.
- Ограничение количества запросов / rate limiting.
- Content Security Policy, минимизация клиент‑сайд рисков.
- Инфраструктура:
- Отключить MULTI_STATEMENTS если не нужны.
- Включить безопасные SQL‑режимы (например strict modes).
- Логирование и мониторинг:
- Логировать аномалии запросов, ошибки SQL, неудачные попытки входа.
- Настроить оповещения при всплесках 4xx/5xx, подозрительных паттернах.
- Соблюдать баланс: не логировать пароли/секреты в открытом виде.
- Тестирование и деплой:
- Регулярные автоматизированные и ручные тесты на инъекции (SAST/DAST) — только на авторизованных окружениях.
- Code review и CI проверки безопасности.
- Обновления:
- Держать СУБД и библиотеки в актуальном состоянии.
Краткий практический пример (PDO + валидация)
- Принцип: валидируем вход, используем подготовленное выражение, минимизируем привилегии:
- $name = $_GET['name'] ?? '';
- if (!preg_match('/^[A-Za-z0-9_-]{1,50}$/', $name)) { /* error */ }
- $stmt = $pdo->prepare("SELECT id, name, email FROM users WHERE name = :name");
- $stmt->execute(['name' => $name]);
Заключение
- Главный защитный механизм — параметризованные запросы + валидация. Дополняйте минимальными привилегиями БД, мониторингом, WAF и регулярным тестированием. Использование mysql_* в текущем коде — критическая уязвимость, её следует заменить на PDO/mysqli и пройти рефакторинг всего ввода данных.