Blind SQL Injection

Что такое слепая SQL-инъекция?

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

Многие техники, такие как атаки UNION, неэффективны при уязвимостях слепой SQL-инъекции. Это потому, что они зависят от возможности видеть результаты внедрённого запроса в ответах приложения. Слепую SQL-инъекцию всё же можно эксплуатировать для доступа к несанкционированным данным, но необходимо использовать другие техники.

Эксплуатация слепой SQL-инъекции путём вызова условных ответов

Рассмотрим приложение, которое использует отслеживающие cookie для сбора аналитики об использовании. Запросы к приложению включают заголовок cookie вида:

Cookie: TrackingId=u5YD3PapBcR4lN3e7Tj4

Когда обрабатывается запрос, содержащий cookie TrackingId, приложение использует SQL-запрос, чтобы определить, известен ли это пользователь:

SELECT TrackingId FROM TrackedUsers WHERE TrackingId = 'u5YD3PapBcR4lN3e7Tj4'

Этот запрос уязвим к SQL-инъекции, но результаты запроса пользователю не возвращаются. Однако поведение приложения отличается в зависимости от того, возвращает ли запрос какие-либо данные. Если вы отправляете распознанный TrackingId, запрос возвращает данные, и в ответе отображается сообщение «Welcome back».

Такого поведения достаточно, чтобы эксплуатировать уязвимость слепой SQL-инъекции. Вы можете извлекать информацию, условно вызывая разные ответы в зависимости от внедрённого условия.

Чтобы понять, как работает эта эксплуатация, предположим, что последовательно отправляются два запроса, содержащие следующие значения cookie TrackingId:

…xyz' AND '1'='1
…xyz' AND '1'='2
  • Первое из этих значений заставляет запрос вернуть результаты, потому что внедрённое условие AND '1'='1 истинно. В результате отображается сообщение «Welcome back».

  • Второе значение приводит к тому, что запрос не возвращает результатов, потому что внедрённое условие ложно. Сообщение «Welcome back» не отображается.

Это позволяет нам определять истинность любого отдельного внедрённого условия и извлекать данные по частям.

Например, предположим, что есть таблица Users со столбцами Username и Password и пользователь Administrator. Вы можете определить пароль для этого пользователя, отправляя серию вводов, чтобы проверять пароль посимвольно.

Для этого начните со следующего ввода:

Это возвращает сообщение «Welcome back», указывая, что внедрённое условие истинно, и значит первый символ пароля больше, чем m.

Затем отправьте следующий ввод:

Это не возвращает сообщение «Welcome back», указывая, что внедрённое условие ложно, и первый символ пароля не больше, чем t.

В конечном счёте мы отправляем следующий ввод, который возвращает сообщение «Welcome back», тем самым подтверждая, что первый символ пароля — s:

Мы можем продолжать этот процесс, чтобы систематически определить полный пароль пользователя Administrator.

Примечание

Функция SUBSTRING на некоторых типах баз данных называется SUBSTR. Подробности см. в SQL injection cheat sheet.

SQL-инъекция на основе ошибок (error-based)

SQL-инъекция на основе ошибок относится к случаям, когда вы можете использовать сообщения об ошибках, чтобы извлечь или вывести чувствительные данные из базы даже в «слепых» контекстах. Возможности зависят от конфигурации базы данных и типов ошибок, которые вы можете спровоцировать:

  • Вы можете заставить приложение возвращать определённый ответ об ошибке в зависимости от результата булевого выражения. Это можно эксплуатировать так же, как условные ответы, рассмотренные в предыдущем разделе.

  • Вы можете вызывать сообщения об ошибках, которые выводят данные, возвращаемые запросом. Это по сути превращает в видимые те уязвимости слепой SQL-инъекции, которые иначе оставались бы «слепыми».

Эксплуатация слепой SQL-инъекции путём вызова условных ошибок

Некоторые приложения выполняют SQL-запросы, но их поведение не меняется независимо от того, возвращает ли запрос какие-либо данные. Техника из предыдущего раздела не сработает, потому что внедрение разных булевых условий не влияет на ответы приложения.

Часто можно заставить приложение возвращать другой ответ в зависимости от того, возникает ли SQL-ошибка. Вы можете модифицировать запрос так, чтобы он вызывал ошибку базы данных только если условие истинно. Очень часто необработанная ошибка, брошенная базой, вызывает некоторые различия в ответе приложения, например сообщение об ошибке. Это позволяет вам определить истинность внедрённого условия.

Чтобы увидеть, как это работает, предположим, что последовательно отправляются два запроса со следующими значениями cookie TrackingId:

Эти вводы используют ключевое слово CASE, чтобы проверить условие и вернуть разное выражение в зависимости от его истинности:

  • В первом вводе выражение CASE вычисляется в 'a', что не вызывает ошибки.

  • Во втором вводе оно вычисляется в 1/0, что вызывает ошибку деления на ноль.

Если ошибка вызывает различие в HTTP-ответе приложения, вы можете использовать это, чтобы определить, истинно ли внедрённое условие.

Используя эту технику, вы можете извлекать данные, проверяя символы по одному:

Примечание

Существуют разные способы вызова условных ошибок, и различные техники лучше работают на разных типах баз данных. Подробности см. в SQL injection cheat sheet.

Извлечение чувствительных данных через подробные сообщения SQL-ошибок

Иногда из-за неверной конфигурации базы появляются подробные сообщения об ошибках. Они могут предоставлять информацию, полезную для атакующего. Например, рассмотрим следующее сообщение об ошибке, которое возникает после внедрения одинарной кавычки в параметр id:

Здесь показан полный запрос, который приложение сформировало с нашим вводом. Мы видим, что в данном случае мы внедряем внутрь строки в одинарных кавычках в операторе WHERE. Это упрощает конструирование валидного запроса с вредоносной полезной нагрузкой. Закомментировав остальную часть запроса, можно предотвратить «поломку» синтаксиса из-за лишней одинарной кавычки.

Иногда вы можете заставить приложение сгенерировать сообщение об ошибке, которое содержит некоторые данные, возвращаемые запросом. Это по сути превращает уязвимость слепой SQL-инъекции в видимую.

Для этого можно использовать функцию CAST(). Она позволяет конвертировать один тип данных в другой. Например, представьте запрос, содержащий следующее выражение:

Часто данные, которые вы пытаетесь прочитать, являются строкой. Попытка преобразовать её в несовместимый тип, например int, может вызвать ошибку, подобную следующей:

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

Эксплуатация слепой SQL-инъекции путём вызова задержек по времени

Если приложение перехватывает ошибки базы при выполнении SQL-запроса и обрабатывает их аккуратно, различий в ответе приложения не будет. Это означает, что предыдущая техника для вызова условных ошибок не сработает.

В такой ситуации часто можно эксплуатировать уязвимость слепой SQL-инъекции, инициируя задержки по времени в зависимости от истинности внедрённого условия. Поскольку SQL-запросы обычно обрабатываются приложением синхронно, задержка выполнения SQL-запроса также задерживает HTTP-ответ. Это позволяет определить истинность внедрённого условия по времени, за которое приходит HTTP-ответ.

Техники вызова задержек зависят от типа используемой базы данных. Например, в Microsoft SQL Server вы можете использовать следующее, чтобы проверить условие и вызвать задержку в зависимости от истинности выражения:

  • Первое из этих введений не вызывает задержку, потому что условие 1=2 ложно.

  • Второе вызывает задержку в 10 секунд, потому что условие 1=1 истинно.

Используя эту технику, мы можем извлекать данные, проверяя символы по одному:

Примечание

Существует множество способов вызвать задержки внутри SQL-запросов, и разные техники применяются к разным типам баз. Подробности см. в SQL injection cheat sheet.

Эксплуатация слепой SQL-инъекции с использованием внеполосных (OAST) техник

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

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

Для этой цели можно использовать различные сетевые протоколы, но обычно наиболее эффективен DNS (Domain Name Service). Многие промышленные сети позволяют свободный исходящий трафик DNS-запросов, потому что они необходимы для нормальной работы систем.

Самый простой и надёжный инструмент для использования внеполосных техник — это Burp Collaborator. Это сервер, предоставляющий кастомные реализации различных сетевых сервисов, включая DNS. Он позволяет обнаруживать, когда сетевые взаимодействия происходят в результате отправки отдельных полезных нагрузок уязвимому приложению. В Burp Suite Professional есть встроенный клиент, настроенный для работы с Burp Collaborator «из коробки». Подробнее см. документацию по Burp Collaborator.

Техники вызова DNS-запроса зависят от типа используемой базы данных. Например, на Microsoft SQL Server следующий ввод можно использовать, чтобы инициировать DNS-поиск указанного домена:

Это заставляет базу выполнить поиск следующего домена:

Вы можете использовать Burp Collaborator, чтобы сгенерировать уникальный поддомен и опрашивать сервер Collaborator для подтверждения, когда происходят какие-либо DNS-запросы.

Подтвердив возможность вызывать внеполосные взаимодействия, вы можете затем использовать внеполосный канал для эксфильтрации данных из уязвимого приложения. Например:

Этот ввод считывает пароль пользователя Administrator, добавляет уникальный поддомен Collaborator и инициирует DNS-поиск. Этот поиск позволяет вам увидеть перехваченный пароль:

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

Примечание

Существует множество способов инициировать внеполосные взаимодействия, и разные техники применяются к разным типам баз данных. Подробности см. в SQL injection cheat sheet.

Как предотвратить атаки слепой SQL-инъекции?

Хотя техники, необходимые для поиска и эксплуатации уязвимостей слепой SQL-инъекции, отличаются и более сложны, чем для обычной SQL-инъекции, меры по предотвращению SQL-инъекции одинаковы.

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

Last updated