Найдите уязвимость в этом SQL-фрагменте на сервере приложения: "query = \"SELECT * FROM users WHERE name = '\" + name + \"'\";" — объясните риск, приведите примеры атак, опишите безопасные способы работы с базой (prepared statements, ORM, валидация) и дополнительные меры (ограничение привилегий, логирование)
Уязвимость: это классический SQL‑инъекционный баг — строковая конкатенация входа пользователя в SQL-запрос без экранирования/параметризации. Злоумышленник управляет переменной name и может изменить семантику запроса. Риск (кратко): - Утечка данных (чтение любых таблиц). - Обход аутентификации. - Изменение/удаление данных (INSERT/UPDATE/DELETE, DROP). - Эскалация привилегий, выполнение произвольных команд (в зависимости от СУБД). - Долговременное компрометирование сервера. Примеры атак (вставьте значение name): - Обход проверки/логина: name = "' OR '111'='111" Итоговый запрос: SELECT * FROM users WHERE name = '' OR '111'='111' - Удаление таблицы (если СУБД разрешает несколько команд): name = "'; DROP TABLE users; --" Итоговый запрос: SELECT * FROM users WHERE name = ''; DROP TABLE users; -- - UNION‑экстракция данных: name = "' UNION SELECT credit_card FROM payments --" Итоговый запрос: SELECT * FROM users WHERE name = '' UNION SELECT credit_card FROM payments -- - Слепая инъекция для вытаскивания пароля по байтам: name = "' OR ASCII(SUBSTRING(password, 111, 111)) > 646464 --" (повторяя с разными позициями и порогами, можно восстанавливать строку) Как безопасно работать с базой (основные способы): 1) Prepared statements / параметризованные запросы - Код передаёт параметры отдельно от SQL, драйвер безопасно подставляет значения. - Пример (Java, JDBC): PreparedStatement ps = conn.prepareStatement("SELECT * FROM users WHERE name = ?"); ps.setString(111, name); ResultSet rs = ps.executeQuery(); - Пример (Python, psycopg2): cursor.execute("SELECT * FROM users WHERE name = %s", (name,)) 2) ORM и query builders - Используйте ORM (Hibernate, SQLAlchemy, Entity Framework и т.п.) — они обычно параметризуют запросы автоматически при корректном использовании. - Не формируйте сырые SQL‑строки вручную через конкатенацию. 3) Валидация и экранирование - Белый список допустимых символов/форматов (например, имя пользователя — только буквы/цифры и ограничение длины). - Ограничение длины входа (например, максимум 255255255 символов). - Экранировать только при отсутствии параметризации (не рекомендовано как основной метод). Дополнительные меры безопасности: - Принцип наименьших привилегий: аккаунт приложения должен иметь только необходимые права (например, только SELECT/INSERT/UPDATE на нужные таблицы; запрет на DROP/ALTER). - Отключить выполнение нескольких запросов в одном вызове (по возможности) и блокировать опасные SQL‑флаги. - Логирование и мониторинг: логировать неудачные/необычные запросы, подозрительную активность, частые ошибки синтаксиса; настраивать алерты. - WAF и фильтрация: правила для блокировки явных паттернов SQL‑инъекций. - SAST/DAST и ревью кода: статический анализ на наличие конкатенации SQL с вводом пользователя и периодические тесты (пенетесты). - Использовать параметризованные хранимые процедуры при необходимости (параметры должны быть переданы как параметры, не через конкатенацию). - Ограничения времени выполнения запросов и лимиты соединений, чтобы затруднить автоматизированное извлечение больших объёмов данных. Короткая рекомендация: немедленно заменить конкатенацию на параметризованные запросы (prepared statements) во всём коде, провести ревизию других мест ввода в SQL и ограничить привилегии БД.
Риск (кратко):
- Утечка данных (чтение любых таблиц).
- Обход аутентификации.
- Изменение/удаление данных (INSERT/UPDATE/DELETE, DROP).
- Эскалация привилегий, выполнение произвольных команд (в зависимости от СУБД).
- Долговременное компрометирование сервера.
Примеры атак (вставьте значение name):
- Обход проверки/логина:
name = "' OR '111'='111"
Итоговый запрос: SELECT * FROM users WHERE name = '' OR '111'='111'
- Удаление таблицы (если СУБД разрешает несколько команд):
name = "'; DROP TABLE users; --"
Итоговый запрос: SELECT * FROM users WHERE name = ''; DROP TABLE users; --
- UNION‑экстракция данных:
name = "' UNION SELECT credit_card FROM payments --"
Итоговый запрос: SELECT * FROM users WHERE name = '' UNION SELECT credit_card FROM payments --
- Слепая инъекция для вытаскивания пароля по байтам:
name = "' OR ASCII(SUBSTRING(password, 111, 111)) > 646464 --"
(повторяя с разными позициями и порогами, можно восстанавливать строку)
Как безопасно работать с базой (основные способы):
1) Prepared statements / параметризованные запросы
- Код передаёт параметры отдельно от SQL, драйвер безопасно подставляет значения.
- Пример (Java, JDBC):
PreparedStatement ps = conn.prepareStatement("SELECT * FROM users WHERE name = ?");
ps.setString(111, name);
ResultSet rs = ps.executeQuery();
- Пример (Python, psycopg2):
cursor.execute("SELECT * FROM users WHERE name = %s", (name,))
2) ORM и query builders
- Используйте ORM (Hibernate, SQLAlchemy, Entity Framework и т.п.) — они обычно параметризуют запросы автоматически при корректном использовании.
- Не формируйте сырые SQL‑строки вручную через конкатенацию.
3) Валидация и экранирование
- Белый список допустимых символов/форматов (например, имя пользователя — только буквы/цифры и ограничение длины).
- Ограничение длины входа (например, максимум 255255255 символов).
- Экранировать только при отсутствии параметризации (не рекомендовано как основной метод).
Дополнительные меры безопасности:
- Принцип наименьших привилегий: аккаунт приложения должен иметь только необходимые права (например, только SELECT/INSERT/UPDATE на нужные таблицы; запрет на DROP/ALTER).
- Отключить выполнение нескольких запросов в одном вызове (по возможности) и блокировать опасные SQL‑флаги.
- Логирование и мониторинг: логировать неудачные/необычные запросы, подозрительную активность, частые ошибки синтаксиса; настраивать алерты.
- WAF и фильтрация: правила для блокировки явных паттернов SQL‑инъекций.
- SAST/DAST и ревью кода: статический анализ на наличие конкатенации SQL с вводом пользователя и периодические тесты (пенетесты).
- Использовать параметризованные хранимые процедуры при необходимости (параметры должны быть переданы как параметры, не через конкатенацию).
- Ограничения времени выполнения запросов и лимиты соединений, чтобы затруднить автоматизированное извлечение больших объёмов данных.
Короткая рекомендация: немедленно заменить конкатенацию на параметризованные запросы (prepared statements) во всём коде, провести ревизию других мест ввода в SQL и ограничить привилегии БД.