Года полтора назад, просматривая access-лог одного вебсервера, я обнаружил в нем попытку взлома сайта с помощью sql-инъекции. Версия SQL была 4.1.х и в логе можно было наблюдать как атакующий подобрал таблицу с пользователями:
?id=-1+union+select+1,2,3,4,5,6,7,8,9,10,11,12,13+from+users
Но ему никак не удавалось подобрать названия столбцов этой таблицы, чтоб получить вывод имен и паролей пользователей сайта. Тогда он проделал интересный трюк - он попытался получить содержимое таблицы users с помощью примерно такого запроса:
-1+union+select+*,1,2,3,4,5+from+users
Т.е. он использовал символ "*", чтобы включить в запрос все поля таблицы users дополнив его необходимым количеством полей, чтоб запрос перестал выдавать ошибку "different number of columns". Следует отметить, что все это возможно только в случае когда количество столбцов, которое извлекает запрос, в который внедряется инъекция, больше или равно общему количеству столбцов в таблице users. В итоге он получил вывод некоторых значений полей из таблицы users (тех что попадали под выводимые скриптом значения извлекаемые sql-запросом). Но искомые пароли пользователей ему этим запросом получить не удалось и эта sql-инъекция не привела к взлому сайта. Я же решил немного поэксперементировать, и попытаться "добить" эту нераскрученную sql-инъекцию.
Первое, что пришло в голову - попробовать поперемещать выводимые значения полей таблицы users с помощью запросов вида:
-1+union+select+1,*,2,3,4,5+from+users
-1+union+select+1,2,*,3,4,5+from+users
...
etc
Но такие запросы оказались неработоспособны. Поразмыслив, я все-таки нашел способ как осуществить задуманное:
-1+union+select+*+from+(select+1)y,users,(select+1,2,3,4)x
-1+union+select+*+from+(select+1,2)y,users,(select+1,2,3)x
-1+union+select+*+from+(select+1,2,3)y,users,(select+1,2)x
-1+union+select+*+from+(select+1,2,3,4)y,users,(select+1)x
-1+union+select+*+from+(select+1,2,3,4,5)x,users
В итоге мне удалось получить пользовательские пароли из users. В вышеприведенных примерах используются подзапросы с алиасами в качестве дополнительных таблиц, перечисляемых в from. Из-за подзапросов такое не сработает в версиях 4.0.x. Но как оказалось, все-таки есть более постой и универсальный способ, действующий во всех версиях => 4.x, просто нужно использовать запросы с следующим синтаксисом:
-1+union+select+1,users.*,2,3,4,5+from+users
-1+union+select+1,2,users.*,3,4,5+from+users
...
etc
Использование синтаксиса "table_name.*" уже не вызывает ошибки и корректно обрабатывается, в отличие от запросов вида "select+1,2,*,3,4,5+from+users". Такой способ решения данной проблемы мне подсказал
l1ght, за что получил мои скромные респекты. Кстати говоря, про это написано и
в документации по MySQL, но я, видимо, не очень внимательно ее читал. ( ;