Что такое SQL-инъекция

1920x1080 Что такое SQL-инъекция.jpg

SQL‑инъекция — кибератака, нацеленная на уязвимости веб‑приложений, одна из старейших в истории интернета. Злоумышленники внедряют вредоносный код в запросы, которые веб‑приложение отправляет к системам управления базами данных (СУБД), чтобы украсть, изменить или удалить данные в БД. В статье расскажем, почему спустя столько лет SQL‑инъекции остаются популярными, как их обнаружить и, самое главное — как предотвратить.

История SQL берет свое начало еще в 1990‑х годах, когда приложения стали активно использовать базы данных — и эта практика продолжается по сей день. 

В 1979 году компания Oracle разработала поисковый инструмент, который напоминал Excel. Он использовался для работы с данными. Со временем этот инструмент стал языком программирования SQL (Structured Query Language) и теперь повсеместно используется для создания баз данных и разработки сайтов.

SQL востребован практически во всех сферах, с которыми сталкиваются миллионы пользователей по всему миру: от банковского дела до маркетплейсов. Скажем, пользователю в интернет-магазине нужно найти коврик для мыши до 1000 рублей. При поиске нужного товара вручную можно пересмотреть десятки тысяч вариантов, но если воспользоваться фильтрацией и поставить галочки на нужные категории по размеру, цвету и цене, появится подходящий список позиций, который сильно облегчит задачу. Здесь и используется язык запросов SQL. 

Когда пользователь ищет нужный ему коврик для мыши, веб‑приложение также выполняет свою работу по поиску и отправляет запросы к базе данных, чтобы искомые товары появились в строке товаров и показались на сайте. Все эти действия происходят незаметно для пользователя — он видит лишь результат своего поиска, который выдает ему веб‑приложение. 

Условный запрос, который формирует веб-приложение по фильтрам пользователя, выглядит так:

sql
SELECTFROM products
WHERE category'коврик для мыши' AND price < 1000;

Здесь category и price — значения, которые приходят из формы фильтра на сайте, а не жестко заданы в коде. Проблема в том, что если приложение просто подставляет введенные пользователем данные в текст запроса (конкатенацией строк), вместо цены атакующий может ввести не число, а часть SQL-кода. Например, строка 1000 OR 1=1 превратит запрос в:

sql
SELECTFROM products
WHERE category'коврик для мыши' AND price < 1000 OR 1=1;

Условие 1=1 истинно всегда, поэтому запрос вернет вообще все товары из таблицы, игнорируя фильтр. Это и есть SQL-инъекция: внедрение вредоносного кода в поле ввода, из-за которого база данных выполняет не тот запрос, что задумал разработчик. В более серьезных случаях так можно не просто обойти фильтр, а вытащить чужие данные (например, через UNION SELECT) или изменить/удалить записи в таблице.
 

SQL‑инъекции делят по каналу, через который атакующий получает данные из БД, — это самая распространенная классификация, ее используют OWASP, PortSwigger, Imperva. Существуют три основных вида: 

  • внутриполосные (in‑band) — код внедряется и результат виден в том же ответе приложения;
  • слепые (blind) — прямого ответа нет, вывод делается по косвенным признакам вроде задержки или наличия ошибки;
  • внеполосные (out‑of‑band) — данные утекают через сторонний канал, например, DNS-запрос на сервер атакующего.

В примере выше злоумышленник обошел проверку пароля через SELECT‑инъекцию, которую сервер выполнил и сразу вернул результат в ответе, — это классический случай внутриполосной атаки. 

Разберем все три вида и приемы внутри них подробнее, а отдельно — еще два признака, по которым инъекции различают независимо от канала: момент срабатывания и формат входных данных.

Внутриполосные (in‑band) инъекции

Определение версии БД или получение скрытых/конфидициальных данных (например, логины и пароли). Самый простой случай: злоумышленник вводит код и получает результат в том же ответе приложения, что и обычный пользователь. Делится на два приема.

  • Error‑based. Атакующий намеренно провоцирует ошибку СУБД так, чтобы текст ошибки содержал нужные данные. Например, для MSSQL:
sql
' AND 1=CONVERT(int, (SELECT @@version))--

Попытка привести текстовую версию СУБД к числу вызывает ошибку преобразования (приведения) типов данных, и в сообщении об ошибке приложение случайно выводит саму версию базы.

  • UNION‑based. Атакующий добавляет к исходному запросу собственный SELECT через UNION, чтобы вытащить данные из другой таблицы. Пример с товарами интернет‑магазина:
sql
' AND 1=CONVERT(int, (SELECT @@version))--products WHERE category_id = 1
UNION
SELECT username, password FROM users;

Вместе с товарами на странице отображаются чужие логины и пароли.

Слепые (blind) инъекции

Приложение не показывает ни данные, ни текст ошибки — только «страница загрузилась» или «страница не загрузилась». Атакующий узнает данные по косвенным признакам, задавая базе вопросы «да/нет».

  • Boolean‑based. Ответ сервера отличается в зависимости от истинности условия:
sql
1 AND (SELECT COUNT(*) FROM users WHERE id=5)=1

Если страница отобразилась как обычно — условие истинно, пользователь с id=5 существует. Если вернулась ошибка/пустая страница — условие ложно.

  • Time‑based. Используется, когда разницы в содержимом ответа нет. Атакующий заставляет СУБД сделать паузу, если условие верно:
sql
' AND IF(1=1, SLEEP(5), 0)--

Ответ приходит с задержкой в 5 секунд — значит, условие истинно. Долго, зато работает даже там, где страница всегда выглядит одинаково.

Внеполосные (out‑of‑band) инъекции

Здесь атакующий не смотрит ни на содержимое ответа, ни на задержку — вместо этого заставляет сервер БД самостоятельно обратиться к внешнему ресурсу, который контролирует атакующий (DNS‑запрос, HTTP‑запрос). Такой подход называют OAST (out‑of‑band application security testing) и применяют, когда ни in‑band, ни blind не дают результата — например, ответ приложения вообще не меняется. 

Схема: инъекция заставляет СУБД выполнить сетевой запрос, в который «зашиты» украденные данные (например, как часть DNS‑имени), а атакующий читает их из логов своего DNS‑сервера.

Дополнительные признаки

Два термина, которые часто путают с видами выше, на деле описывают не канал, а другое измерение атаки — и могут сочетаться с любым из трех видов.

По моменту срабатывания

Инъекция первого порядка выполняется сразу при вводе. Инъекция второго порядка сначала сохраняется в БД как обычные данные — например, в поле имени профиля:

sql
John'; DROP TABLE users;--

В момент ввода ничего не происходит. Код срабатывает позже, когда это значение используется в другом запросе — например, при формировании отчета администратором.

По формату входных данных

Классическая инъекция — это внедрение в строковый параметр формы или URL, как в примерах выше. Отдельно выделяют JSON/XML‑инъекцию — то же самое, но payload передается через структурированный формат API‑запроса:

json
{
  "username": "john",
  "password": "' OR '1' = '1"
}

Если сервер подставляет значение поля в SQL-запрос без проверки, результат тот же — обход проверки пароля.

Чтобы обнаружить SQL-инъекцию, важно регулярно анализировать базы данных, а также мониторить сетевой трафик и поведение системы на предмет аномальных признаков: 

  • Странные параметры в логах, содержащие кавычки, комментарии, ключевые слова SQL: union, select, drop. 
  • Резкое увеличение объема сетевого трафика к базе данных.
  • Подозрительные внешние DNS/HTTP-запросы от сервера баз данных — чаще всего при внеполосных атаках.
  • Внеплановое изменение прав пользователей, добавление новых записей, изменение паролей. 
  • Обнаружение нестандартного или зашифрованного кода в базе данных. 

Стоит отметить, что один из перечисленных признаков не всегда указывает на наличие SQL-инъекции, но он точно будет сигналом к дополнительной проверке во избежание возможных атак. 

SQL‑инъекции несут серьезную угрозу для проектов: несанкционированный доступ к базам данных может привести к утечке конфиденциальных данных клиентов, значительным финансовым потерям и подрыву репутации компании. В отдельных случаях результат выходит за рамки экономического ущерба — возможны правовые последствия и уголовная ответственность. Нормативные акты РФ, которые регулируют ответственность за последствия SQL-инъекций: 

  • Федеральный закон от 27.07.2006 № 152‑ФЗ «О персональных данных» — обязывает операторов принимать меры по защите персональных данных от несанкционированного доступа. Утечка данных через SQL‑инъекцию расценивается как нарушение закона.
  • КоАП РФ, статья 13.11 — устанавливает административную ответственность (в том числе крупные штрафы) за нарушение порядка обработки и защиты персональных данных, включая их неправомерную передачу вследствие уязвимостей.
  • УК РФ, статья 272.1 — предусматривает уголовную ответственность за незаконное использование, передачу, сбор и хранение персональных данных, полученных через уязвимости (в том числе и SQL‑инъекции).

В сфере защиты от атак и превентивных мер критически важна регулярность. Все приведенные ниже рекомендации необходимо внедрить и поддерживать на постоянной основе.

  • Всегда отслеживайте обновления и устанавливайте актуальные версии серверного ПО, библиотек и CMS. 
  • Регулярно проверяйте производительность приложений с помощью комплексных инструментов. Например, Apache JMeter, Gatling или SQLMap.
  • Используйте WAF, который с помощью соответствующих настроек будет фильтровать вредоносные SQL-запросы. 
  • Тщательно проверяйте данные, вводимые пользователями, — независимо от того, поступают ли они от авторизованных или внутренних пользователей. Кроме того, учетные записи, имеющие доступ к SQL‑базе данных, следует наделить ограниченными правами, достаточными для выполнения их прямых задач.
  • Изучите официальные документы и руководства по борьбе с SQL-инъекциями от OWASP: Annotated Application Security Verification Standard (AASVS)SQL Injection Prevention Cheat SheetQuery Parameterization Cheat SheetOWASP Top 10 и другие. Эти документы содержат комплексную информацию о SQL-инъекциях, их типах, методах обнаружения и предотвращения.