Дан SQL‑фрагмент в веб‑приложении: query = "SELECT * FROM users WHERE name = '" + user_input + "'"; — опишите все уязвимости и вектор атаки, предложите безопасные альтернативы, учтите особенности подготовленных выражений, ORM и фильтрации пользовательских данных

26 Мая в 08:51
14 +1
0
Ответы
1
Коротко: исходная конструкция
query = "SELECT * FROM users WHERE name = '" + user_input + "'";
уязвима к SQL‑инъекции — пользователь может подставить фрагмент SQL, закрыть строку и выполнить произвольный запрос.
1) Какие уязвимости и векторы атаки
- Классическая SQL‑инъекция: ввод, закрывающий строковый литерал и добавляющий выражение, например payload "' OR ′1′=′1′'1'='1'1=1 --" приведёт к возврату всех записей или обходу авторизации.
- UNION‑injection: добавление "UNION SELECT ..." для вытаскивания данных из других таблиц/колонок.
- Stacked queries (если СУБД/драйвер позволяет): выполнение нескольких запросов через `;` для изменения/удаления данных.
- Error‑based: вызов функций/конструкций, вызывающих ошибки, которые раскрывают данные.
- Time‑based (blind): вызов SLEEP(555) или аналогов для поразрядного извлечения данных.
- Out‑of‑band (OOB): использование функций, отправляющих данные вне канала БД (HTTP/DNS).
- Second‑order SQLi: безопасный при вставке, но уязвимый при дальнейшем использовании сохранённого значения в запросе.
- Инъекции в динамические идентификаторы (имена таблиц/столбцов/ORDER BY/LIMIT) — подготовленные выражения не защищают, если идентификатор подставляется в строку.
- Проблемы кодировок/многобайтовых символов: обход фильтров через unicode/byte‑encoding.
- Сопутствующие риски: обход авторизации, утечка PII/паролей/ключей, выполнение команд на сервере (xp_cmdshell, LOAD_FILE), привилегированное изменение данных, DoS.
2) Частые приёмы злоумышленника (коротко)
- Логический обход: "' OR ′1′=′1′'1'='1'1=1 --"
- UNION SELECT для вытягивания колонок
- time‑based: "IF(substring(password,1,1)='a', SLEEP(555), 0)"
- использование комментариев (--, #, /* */) и кодировок
3) Безопасные альтернативы (практика)
- Параметризованные запросы / подготовленные выражения (placeholders)
- Java (PreparedStatement):
PreparedStatement ps = conn.prepareStatement("SELECT * FROM users WHERE name = ?");
ps.setString(1, userInput);
- Python (psycopg2):
cur.execute("SELECT * FROM users WHERE name = %s", (user_input,))
- PHP (PDO, отключить эмуляцию):
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$stmt = $pdo->prepare("SELECT * FROM users WHERE name = ?");
$stmt->execute([$user_input]);
- ORM: использовать встроенные методы/фильтры с привязкой параметров, не конкатенировать строки
- Django: User.objects.filter(name=user_input)
- SQLAlchemy: session.query(User).filter(User.name == user_input)
- Hibernate: query.setParameter(...)
- Для динамических идентификаторов (таблицы/столбцы/ORDER BY): не подставлять напрямую; использовать whitelist/маппинг безопасных значений (например словарь допустимых колонок).
- Для списков IN: генерировать placeholders по длине массива и биндить значения, либо использовать ORM/QueryBuilder который это делает.
- Stored procedures: безопасны только если принимают параметры и внутри не собирают динамический SQL. Динамический SQL в процедурe также уязвим.
- Экранирование (escape) — как крайний и менее предпочтительный способ; зависит от кодировки и драйвера (mysqli_real_escape_string, pg_escape_string) — использовать только при невозможности параметризации.
- Длинные/типовые проверки: валидация/whitelist (тип, регулярка, длина), canonicalize вход, reject/normalize опасные символы.
- Ограничение привилегий: отдельный DB‑пользователь с минимально необходимыми правами; запрет на DROP/FILE/EXEC для приложений.
- Отключение эмуляции prepared statements в драйверах (PDO::ATTR_EMULATE_PREPARES = false).
- Логирование, мониторинг, WAF, регулярные сканирования и тестирование (SAST/DAST/pen‑tests).
4) Особенности подготовленных выражений и ORM — чего остерегаться
- Подготовленные выражения защищают от подстановки данных в места литералов, но не от подстановки SQL‑идентификаторов (имена таблиц/столбцов) или динамической конструкции SQL, если вы формируете её вручную.
- Некоторые драйверы эмулируют prepared statements — это не всегда безопасно, отключайте эмуляцию и используйте нативные prepares.
- ORM может скрывать SQL, но позволяет raw SQL — любые raw‑запросы должны использовать бинд параметров.
- LIKE: при использовании параметров нужно экранировать пользовательские `%` и `_`, если они нежелательны.
- IN/массовые вставки: не используйте конкатенацию для списков — применять placeholders или ORM‑функции.
- Second‑order: данные, безопасно сохранённые сейчас, могут стать источником инъекции позже — при любом использовании сохранённых значений применять параметры.
5) Быстрый чек‑лист для исправления примера
- Заменить конкатенацию на параметр:
"SELECT * FROM users WHERE name = ?"
- Проверить, что драйвер реально использует нативные prepares.
- Ограничить права БД; логировать и мониторить аномалии.
- Добавить валидацию/whitelist для ожидаемых форматов (имена — буквы/знаки).
- Провести тесты: автоматические SQLi‑сканеры и ручной pentest.
Если нужно — приведу конкретные примеры кода для вашей платформы/ЯП и варианты защиты для динамических частей запроса.
26 Мая в 09:24
Не можешь разобраться в этой теме?
Обратись за помощью к экспертам
Гарантированные бесплатные доработки в течение 1 года
Быстрое выполнение от 2 часов
Проверка работы на плагиат
Поможем написать учебную работу
Прямой эфир