Найдите уязвимость в следующем фрагменте на PHP и опишите варианты атак и защитных мер: $q = "SELECT * FROM users WHERE name = '".$_GET['name']."'"; $r = mysqli_query($db, $q); — обсудите подготовленные выражения, валидацию, принцип наименьших привилегий и другие слои защиты
Кратко — уязвимость: SQL‑инъекция. В строке $q = "SELECT * FROM users WHERE name = '".$_GET′name′'name'′name′."'"; пользовательский ввод ($_GET['name']) напрямую конкатенируется в SQL-запрос без очистки или параметризации, поэтому злоумышленник может подделать запрос.
Какие атаки возможны примерыполезныхполезадовпримеры полезных полезадовпримерыполезныхполезадов:
Простая логическая инъекция авторизация/доступкданнымавторизация/доступ к даннымавторизация/доступкданным: name=' OR '1'='1 => WHERE name = '' OR '1'='1' — вернутся все записи.UNION‑инъекция получениедополнительныхколонокполучение дополнительных колонокполучениедополнительныхколонок: name=' UNION SELECT email, password FROM secrets -- потребуетсяподобратьчислоитипыколонокпотребуется подобрать число и типы колонокпотребуетсяподобратьчислоитипыколонок.Stacked queries многозапросностьмногозапросностьмногозапросность: name='; DROP TABLE users; -- вMySQLмногозапросывыполняютсяприиспользованиисоответствующихAPI/флагов—ноеслионивключены,можновыполнятьдополнительныекомандыв MySQL многозапросы выполняются при использовании соответствующих API/флагов — но если они включены, можно выполнять дополнительные командывMySQLмногозапросывыполняютсяприиспользованиисоответствующихAPI/флагов—ноеслионивключены,можновыполнятьдополнительныекоманды.Blind слепаяслепаяслепая / временная инъекция для извлечения данных по битам/символам: name=' OR IFSUBSTRING((SELECTpasswordFROMusersWHEREname=′admin′),1,1)=′a′,SLEEP(5),0SUBSTRING((SELECT password FROM users WHERE name='admin'),1,1)='a', SLEEP(5), 0SUBSTRING((SELECTpasswordFROMusersWHEREname=′admin′),1,1)=′a′,SLEEP(5),0 -- — если сервер «задерживается», можно узнать символы пароля.Error‑based: специально вызвать ошибку и вывести содержимое через текст ошибки.
Последствия: утечка конфиденциальных данных логины/паролилогины/паролилогины/пароли, обход авторизации, уничтожение или изменение данных, получение управления БД/цепочки атак внутри сети.
Как защищаться — многоуровнево defenseindepthdefense in depthdefenseindepth:
1) Подготовленные выражения parameterizedqueriesparameterized queriesparameterizedqueries — основной способ предотвратить SQL‑инъекции:
Пример с MySQLi рекомендованныйрекомендованныйрекомендованный: stmt=stmt = stmt=db->prepare′SELECTid,name,emailFROMusersWHEREname=?′'SELECT id, name, email FROM users WHERE name = ?'′SELECTid,name,emailFROMusersWHEREname=?′; $stmt->bind_param('s', $_GET['name']); $stmt->execute; result=result = result=stmt->get_result;Пример с PDO: stmt=stmt = stmt=pdo->prepare′SELECTid,nameFROMusersWHEREname=:name′'SELECT id, name FROM users WHERE name = :name'′SELECTid,nameFROMusersWHEREname=:name′; $stmt->execute(['name' => $_GET['name']]); $rows = $stmt->fetchAll(); Преимущество: драйвер отделяет структуру SQL от данных, значения не интерпретируются как SQL.
2) Валидация и нормализация входа:
Белый список допустимых значений там, где возможно (например, имена, ID, перечисления).Регулярные выражения и длина: например, допустимы только буквы/цифры и ограничение длины.Нормализация кодировок и использование set_charset('utf8mb4') для соединения — предотвращает обходы через мультибайтовые кодировки.
3) Экранирование как запасной вариант:
mysqli_real_escape_string() — работает, но менее надежно, чем параметризованные запросы, и чувствительно к настройкам кодировки. $name = mysqli_real_escape_string($db, $_GET['name']); $q = "SELECT ... WHERE name = '$name'";
Пользователь БД, от имени которого выполняется веб‑приложение, должен иметь минимально необходимые права: обычно SELECT итольконанужныетаблицы/колонкии только на нужные таблицы/колонкиитольконанужныетаблицы/колонки. Не давать DROP, DELETE, ALTER, GRANT и т.п., если они не нужны.Разделение ролей: один пользователь для чтения, другой — для администрирования.
5) Закрытие возможности выполнения нескольких запросов:
Не допускайте использование multi‑statement, если не нужно. В PDO можно отключить эмуляцию и т. п.; в MySQLi — не использовать mysqli_multi_query и не включать соответствующие клиентские флаги.
6) Не позволять параметризовать идентификаторы:
Подставлять имена таблиц/столбцов через параметры нельзя. Для таких случаев используйте белые списки допустимых идентификаторов и строгую проверку.
7) Обработка ошибок и логирование:
Не показывайте пользователю подробные SQL‑ошибки этооблегчаетerror‑basedинъекцииэто облегчает error‑based инъекцииэтооблегчаетerror‑basedинъекции. Логи ошибок сохраняйте и анализируйте.Мониторьте аномальные запросы, медленные запросы и повторные неудачные попытки IDS/WAFIDS/WAFIDS/WAF.
8) Дополнительные слои защиты:
Веб‑файервол WAFWAFWAF — может блокировать типичные payload'ы, но не заменяет безопасное кодирование.Ограничение частоты запросов, капча для подозрительных сценариев.Хранение конфиденциальных данных в хешированном/шифрованном виде например,пароли—passwordhashнапример, пароли — password_hashнапример,пароли—passwordhash.Использование ORM или проверенных библиотек, которые по умолчанию параметризуют запросы.
9) Защита от вторичных инъекций:
Вторичные second‑ordersecond‑ordersecond‑order – когда неочищенные данные сохраняются и используются в другом контексте позже. Всегда параметризуйте запросы при их формировании, а не надеяться на раннюю очистку.
10) Безопасность на уровне БД/сети:
Отключите удалённый доступ к базе, используйте firewall, bind-address, chroot/контейнеризацию, шифрование каналов TLSTLSTLS.Регулярные обновления СУБД и библиотек.
Короткий пример безопасного варианта MySQLiMySQLiMySQLi: $db->set_charset('utf8mb4'); $stmt = $db->prepare('SELECT id, name, email FROM users WHERE name = ? LIMIT 1'); $stmt->bind_param('s', $_GET['name']); $stmt->execute(); $res = $stmt->get_result();
Итого: самая серьёзная уязвимость — SQL‑инъекция. Правильный базовый ответ — использовать подготовленные выражения + валидация входа + принцип наименьших привилегий + дополнительные слои (экранирование как запасной вариант, WAF, логирование, ограничение многозапросности, запрет вывода ошибок пользователю).
Кратко — уязвимость: SQL‑инъекция. В строке
$q = "SELECT * FROM users WHERE name = '".$_GET′name′'name'′name′."'";
пользовательский ввод ($_GET['name']) напрямую конкатенируется в SQL-запрос без очистки или параметризации, поэтому злоумышленник может подделать запрос.
Какие атаки возможны примерыполезныхполезадовпримеры полезных полезадовпримерыполезныхполезадов:
Простая логическая инъекция авторизация/доступкданнымавторизация/доступ к даннымавторизация/доступкданным:name=' OR '1'='1
=> WHERE name = '' OR '1'='1' — вернутся все записи.UNION‑инъекция получениедополнительныхколонокполучение дополнительных колонокполучениедополнительныхколонок:
name=' UNION SELECT email, password FROM secrets --
потребуетсяподобратьчислоитипыколонокпотребуется подобрать число и типы колонокпотребуетсяподобратьчислоитипыколонок.Stacked queries многозапросностьмногозапросностьмногозапросность:
name='; DROP TABLE users; --
вMySQLмногозапросывыполняютсяприиспользованиисоответствующихAPI/флагов—ноеслионивключены,можновыполнятьдополнительныекомандыв MySQL многозапросы выполняются при использовании соответствующих API/флагов — но если они включены, можно выполнять дополнительные командывMySQLмногозапросывыполняютсяприиспользованиисоответствующихAPI/флагов—ноеслионивключены,можновыполнятьдополнительныекоманды.Blind слепаяслепаяслепая / временная инъекция для извлечения данных по битам/символам:
name=' OR IFSUBSTRING((SELECTpasswordFROMusersWHEREname=′admin′),1,1)=′a′,SLEEP(5),0SUBSTRING((SELECT password FROM users WHERE name='admin'),1,1)='a', SLEEP(5), 0SUBSTRING((SELECTpasswordFROMusersWHEREname=′admin′),1,1)=′a′,SLEEP(5),0 --
— если сервер «задерживается», можно узнать символы пароля.Error‑based: специально вызвать ошибку и вывести содержимое через текст ошибки.
Последствия: утечка конфиденциальных данных логины/паролилогины/паролилогины/пароли, обход авторизации, уничтожение или изменение данных, получение управления БД/цепочки атак внутри сети.
Как защищаться — многоуровнево defenseindepthdefense in depthdefenseindepth:
1) Подготовленные выражения parameterizedqueriesparameterized queriesparameterizedqueries — основной способ предотвратить SQL‑инъекции:
Пример с MySQLi рекомендованныйрекомендованныйрекомендованный:stmt=stmt = stmt=db->prepare′SELECTid,name,emailFROMusersWHEREname=?′'SELECT id, name, email FROM users WHERE name = ?'′SELECTid,name,emailFROMusersWHEREname=?′;
$stmt->bind_param('s', $_GET['name']);
$stmt->execute;
result=result = result=stmt->get_result;Пример с PDO:
stmt=stmt = stmt=pdo->prepare′SELECTid,nameFROMusersWHEREname=:name′'SELECT id, name FROM users WHERE name = :name'′SELECTid,nameFROMusersWHEREname=:name′;
$stmt->execute(['name' => $_GET['name']]);
$rows = $stmt->fetchAll();
Преимущество: драйвер отделяет структуру SQL от данных, значения не интерпретируются как SQL.
2) Валидация и нормализация входа:
Белый список допустимых значений там, где возможно (например, имена, ID, перечисления).Регулярные выражения и длина: например, допустимы только буквы/цифры и ограничение длины.Нормализация кодировок и использование set_charset('utf8mb4') для соединения — предотвращает обходы через мультибайтовые кодировки.3) Экранирование как запасной вариант:
mysqli_real_escape_string() — работает, но менее надежно, чем параметризованные запросы, и чувствительно к настройкам кодировки.$name = mysqli_real_escape_string($db, $_GET['name']);
$q = "SELECT ... WHERE name = '$name'";
4) Ограничение привилегий принципнаименьшихпривилегийпринцип наименьших привилегийпринципнаименьшихпривилегий:
Пользователь БД, от имени которого выполняется веб‑приложение, должен иметь минимально необходимые права: обычно SELECT итольконанужныетаблицы/колонкии только на нужные таблицы/колонкиитольконанужныетаблицы/колонки. Не давать DROP, DELETE, ALTER, GRANT и т.п., если они не нужны.Разделение ролей: один пользователь для чтения, другой — для администрирования.5) Закрытие возможности выполнения нескольких запросов:
Не допускайте использование multi‑statement, если не нужно. В PDO можно отключить эмуляцию и т. п.; в MySQLi — не использовать mysqli_multi_query и не включать соответствующие клиентские флаги.6) Не позволять параметризовать идентификаторы:
Подставлять имена таблиц/столбцов через параметры нельзя. Для таких случаев используйте белые списки допустимых идентификаторов и строгую проверку.7) Обработка ошибок и логирование:
Не показывайте пользователю подробные SQL‑ошибки этооблегчаетerror‑basedинъекцииэто облегчает error‑based инъекцииэтооблегчаетerror‑basedинъекции. Логи ошибок сохраняйте и анализируйте.Мониторьте аномальные запросы, медленные запросы и повторные неудачные попытки IDS/WAFIDS/WAFIDS/WAF.8) Дополнительные слои защиты:
Веб‑файервол WAFWAFWAF — может блокировать типичные payload'ы, но не заменяет безопасное кодирование.Ограничение частоты запросов, капча для подозрительных сценариев.Хранение конфиденциальных данных в хешированном/шифрованном виде например,пароли—passwordhashнапример, пароли — password_hashнапример,пароли—passwordh ash.Использование ORM или проверенных библиотек, которые по умолчанию параметризуют запросы.9) Защита от вторичных инъекций:
Вторичные second‑ordersecond‑ordersecond‑order – когда неочищенные данные сохраняются и используются в другом контексте позже. Всегда параметризуйте запросы при их формировании, а не надеяться на раннюю очистку.10) Безопасность на уровне БД/сети:
Отключите удалённый доступ к базе, используйте firewall, bind-address, chroot/контейнеризацию, шифрование каналов TLSTLSTLS.Регулярные обновления СУБД и библиотек.Короткий пример безопасного варианта MySQLiMySQLiMySQLi:
$db->set_charset('utf8mb4');
$stmt = $db->prepare('SELECT id, name, email FROM users WHERE name = ? LIMIT 1');
$stmt->bind_param('s', $_GET['name']);
$stmt->execute();
$res = $stmt->get_result();
Итого: самая серьёзная уязвимость — SQL‑инъекция. Правильный базовый ответ — использовать подготовленные выражения + валидация входа + принцип наименьших привилегий + дополнительные слои (экранирование как запасной вариант, WAF, логирование, ограничение многозапросности, запрет вывода ошибок пользователю).