Рассмотрите пример уязвимости: в веб‑форме используется SQL = "SELECT * FROM users WHERE login='"+login+"' AND pass='"+pass+"';" — объясните, как происходит SQL‑инъекция, приведите конкретные примеры полезной нагрузки и детализируйте меры защиты на уровне кода, СУБД и архитектуры
Кратко — как это происходит - Уязвимый код конкатенирует пользовательский ввод прямо в SQL: "SELECT * FROM users WHERE login='"+login+"' AND pass='"+pass+"';" В результате злоумышленник может включить в `login` или `pass` SQL‑синтаксис (кавычки, операторы, комментарии), который изменит структуру запроса и добьётся выполнения нежелательных команд. Примеры полезной нагрузки и пояснения - Обход аутентификации (логично сделать логин/пароль всегда истинным): login = `' OR '1'='1` pass = `' OR '1'='1` Получаем WHERE login='' OR 1=11=11=1 AND pass='' OR 1=11=11=1 — условие истинно, вход разрешён. - Комментирование оставшейся части запроса (MySQL/SQL Server): login = `admin' -- ` pass = `anything` Результат: WHERE login='admin' -- ' AND pass='anything'; — часть с паролем закомментирована. - Stacked queries (если СУБД/драйвер разрешают несколько выражений): login = `x'; DROP TABLE users; -- ` Может выполнить удаление таблицы. - UNION‑инъекция для чтения других таблиц: login = `' UNION SELECT card_number,expiry,cvv FROM cards -- ` (нужно подогнать число и типы столбцов под `SELECT *`). - Blind/time‑based (если нет прямого вывода): проверка символа пароля через задержку, например в MySQL: pass = `' OR IF(SUBSTRING(password,1,1)='a', SLEEP(555), 0) -- ` Если ответ задерживается на 555 секунд, первая буква = 'a'. Меры защиты — на уровне кода - Prepared statements / parameterized queries. НИКОГДА не составлять SQL конкатенацией. Примеры: - PHP (PDO): $stmt = $pdo->prepare("SELECT * FROM users WHERE login = :login AND pass = :pass"); $stmt->execute(['login'=>$login, 'pass'=>$pass]); - Python (psycopg2): cur.execute("SELECT * FROM users WHERE login = %s AND pass = %s", (login, pass)) Параметры не влияют на синтаксис запроса. - Хеширование паролей (никогда не хранить plain text): используйте Argon2/Bcrypt/PBKDF2 с солью; сравнивайте хеши, а не пароли в SQL. - Валидация и нормализация входа: запрет или жёсткая allow‑list для логина (например, только [A‑Z0‑9._-], длина ограничена). Проверка длины и кодировки. - Отказ от функционала "много запросов в одном выражении": используйте драйверы/настройки, которые запрещают множественные инструкции в одном запросе. - Минимизация возвращаемых данных: SELECT нужных полей вместо `SELECT *`. Меры защиты — на уровне СУБД и конфигурации - Минимальные права для учётной записи БД: web‑пользователь должен иметь ровно те права, которые нужны (обычно только SELECT/INSERT/UPDATE/DELETE, без DROP/ALTER/CREATE). - Отключить/ограничить возможность выполнять несколько выражений в одном запросе (MySQL option CLIENT_MULTI_STATEMENTS). - Использовать подготовленные планы/statement caching на стороне СУБД. - Включить аудит и логирование подозрительных запросов; настроить уведомления. - Использовать роли/ограничения и, при возможности, Row‑Level Security (Postgres). - Шифрование данных в покое и в транзите; хранить секреты (пароли доступа) в безопасном хранилище (vault). Меры защиты — на уровне архитектуры и процессов - Разделение привилегий и сетей: база на закрытой подсети, доступ только с приложения через пул соединений. - API‑слой / сервис между фронтом и БД, чтобы фронт не обращался к БД напрямую. - WAF (Web Application Firewall) как дополнительный барьер (не замена безопасному коду). - Регулярные тесты: статический анализ, SAST/DAST, пентесты/bug bounty, CI‑проверки. - Мониторинг/IDS/IPS и реагирование на инциденты, лимиты скорости/блокировка по IP. - Резервное копирование и планы восстановления на случай успешной атаки. Краткий чек‑лист (приоритеты) 1. Перейти на параметризованные запросы + убрать конкатенацию. 2. Хешировать пароли сильным алгоритмом. 3. Ограничить права БД учётной записи. 4. Ввести валидацию входных данных и ограничение длины. 5. Включить логирование/аудит и мониторинг. 6. Добавить WAF и сетевую сегментацию. Эти меры в совокупности значительно снижают риск SQL‑инъекций и ущерб от них.
- Уязвимый код конкатенирует пользовательский ввод прямо в SQL:
"SELECT * FROM users WHERE login='"+login+"' AND pass='"+pass+"';"
В результате злоумышленник может включить в `login` или `pass` SQL‑синтаксис (кавычки, операторы, комментарии), который изменит структуру запроса и добьётся выполнения нежелательных команд.
Примеры полезной нагрузки и пояснения
- Обход аутентификации (логично сделать логин/пароль всегда истинным):
login = `' OR '1'='1`
pass = `' OR '1'='1`
Получаем WHERE login='' OR 1=11=11=1 AND pass='' OR 1=11=11=1 — условие истинно, вход разрешён.
- Комментирование оставшейся части запроса (MySQL/SQL Server):
login = `admin' -- `
pass = `anything`
Результат: WHERE login='admin' -- ' AND pass='anything'; — часть с паролем закомментирована.
- Stacked queries (если СУБД/драйвер разрешают несколько выражений):
login = `x'; DROP TABLE users; -- `
Может выполнить удаление таблицы.
- UNION‑инъекция для чтения других таблиц:
login = `' UNION SELECT card_number,expiry,cvv FROM cards -- `
(нужно подогнать число и типы столбцов под `SELECT *`).
- Blind/time‑based (если нет прямого вывода): проверка символа пароля через задержку, например в MySQL:
pass = `' OR IF(SUBSTRING(password,1,1)='a', SLEEP(555), 0) -- `
Если ответ задерживается на 555 секунд, первая буква = 'a'.
Меры защиты — на уровне кода
- Prepared statements / parameterized queries. НИКОГДА не составлять SQL конкатенацией. Примеры:
- PHP (PDO):
$stmt = $pdo->prepare("SELECT * FROM users WHERE login = :login AND pass = :pass");
$stmt->execute(['login'=>$login, 'pass'=>$pass]);
- Python (psycopg2):
cur.execute("SELECT * FROM users WHERE login = %s AND pass = %s", (login, pass))
Параметры не влияют на синтаксис запроса.
- Хеширование паролей (никогда не хранить plain text): используйте Argon2/Bcrypt/PBKDF2 с солью; сравнивайте хеши, а не пароли в SQL.
- Валидация и нормализация входа: запрет или жёсткая allow‑list для логина (например, только [A‑Z0‑9._-], длина ограничена). Проверка длины и кодировки.
- Отказ от функционала "много запросов в одном выражении": используйте драйверы/настройки, которые запрещают множественные инструкции в одном запросе.
- Минимизация возвращаемых данных: SELECT нужных полей вместо `SELECT *`.
Меры защиты — на уровне СУБД и конфигурации
- Минимальные права для учётной записи БД: web‑пользователь должен иметь ровно те права, которые нужны (обычно только SELECT/INSERT/UPDATE/DELETE, без DROP/ALTER/CREATE).
- Отключить/ограничить возможность выполнять несколько выражений в одном запросе (MySQL option CLIENT_MULTI_STATEMENTS).
- Использовать подготовленные планы/statement caching на стороне СУБД.
- Включить аудит и логирование подозрительных запросов; настроить уведомления.
- Использовать роли/ограничения и, при возможности, Row‑Level Security (Postgres).
- Шифрование данных в покое и в транзите; хранить секреты (пароли доступа) в безопасном хранилище (vault).
Меры защиты — на уровне архитектуры и процессов
- Разделение привилегий и сетей: база на закрытой подсети, доступ только с приложения через пул соединений.
- API‑слой / сервис между фронтом и БД, чтобы фронт не обращался к БД напрямую.
- WAF (Web Application Firewall) как дополнительный барьер (не замена безопасному коду).
- Регулярные тесты: статический анализ, SAST/DAST, пентесты/bug bounty, CI‑проверки.
- Мониторинг/IDS/IPS и реагирование на инциденты, лимиты скорости/блокировка по IP.
- Резервное копирование и планы восстановления на случай успешной атаки.
Краткий чек‑лист (приоритеты)
1. Перейти на параметризованные запросы + убрать конкатенацию.
2. Хешировать пароли сильным алгоритмом.
3. Ограничить права БД учётной записи.
4. Ввести валидацию входных данных и ограничение длины.
5. Включить логирование/аудит и мониторинг.
6. Добавить WAF и сетевую сегментацию.
Эти меры в совокупности значительно снижают риск SQL‑инъекций и ущерб от них.