Я устал видеть распространённую ошибку пользователей связанную с использованием union-a и существующего значения параметра, поэтому решил написать это не большое дополнение, может кому то будет полезно...
Зачем нужно использовать несуществующее значение в sql инъекциях при объединении запросов union-ом? и нужно ли вообще?
Union объеденяет два запроса, делая результат запроса общим, а вот скольно информации будет выведено зависит от php скрипта.
В тех случаях когда скрипт получает еденичные данные из БД (конкретная запись (к примеру новость или сообщение на форуме)) (т.е. когда получение результата запоса не помещено в цикл: $result = mysql_fetch_row($query)), то будет выведена только первая строка результата запроса:
Код:
Возьмём к примеру запрос:
select 111, 222 union select 333, 444
Его результатом будет:
111, 222 - раз строка
333, 444 - два строка
Если ограничить вывод лимитом, то можно получить вывод одной строки:
select 111, 222 union select 333, 444 limit 0,1
Результат:
111, 222
А теперь лимитом выведем вторую строку:
select 111, 222 union select 333, 444 limit 1,1
Результат:
333, 444
Так вот, вернёмся к тому как выводит данные скрипт:
Каждая итерация $result = mysql_fetch_row($query) получает только одну строку результата запроса, и если получение результата запроса не помещено в цикл, то будет получена только одна строка.
А какая строка будет выведена - первая, но это "первеность" зависит от самого запроса:
Код:
select title from news - здесь первой строкой будет та, которая первой сохранена в БД
select title from news where id > 5 - здесь первой строкой будет первая строка в БД удовлетворяющая этому условию
select title from news limit 3, 1 - а вот здесь первая строка = третьей записи в БД и никакой другой она быть не может
На то что будет выведено в результате запроса мы можем влиять меняя сам запрос.
Подставляя в параметр не существующие значение (к примеру подставляя в него минус), мы делаем его результат никаким (т.е. результата не будет вообще):
Код:
select title from news where id = -5 - т.к. новости id которой равен минус пяти нет, то никакого результа у запроса не будет.
А теперь заюзаем union, объеденив тем самым два запроса:
Код:
select title from news where id = -5 union select 1 - т.к. первый запрос результата не даст, то единственным результатом будет результат второго запроса
Здесь первой выведенной строкой будет результат второго запроса, т.к. больше выводить нечего.
Теперь подставим существующие значение:
Код:
select title from news where id = 5 union select 1 - id новости существующее значение, значит первой строкой результата будет результат первого запроса, а второй строкой будет результат второго запроса.
И если получение результата запроса ($result = mysql_fetch_row($query)) не прописано в цикле (а мы такую ситуацию и рассматриваем), то мы увидим только результат первого запроса.
А заюзав лимит и указав вывод второй строки мы получим результат второго запроса:
Код:
select title from news where id = 5 union select 1 limit 1,1
Теперь ситуация когда получение результата в цикле - здесь вначале будут выведены все строки из первого запроса, а затем все строки из второго запроса, т.е. желаемый результат мы увидим где нибудь в конце списка выводимых данных.
Но ситуации когда получение данных идет в цикле и при этом используется условие отбора (where) параметр которого можно менять - все таки некоторая редкость.
Поэтому что бы видеть результат второго запроса, нужно или "вырубать" несуществующим значением первый запрос или с помощью limit-а указвать вывод второй строки "общего" результата запроса:
Код:
?id=1+union+select+1,2,3 - если получение запроса не в цикле, то ничего нового мы здесь не увидим
?id=-1+union+select+1,2,3 - а вот здесь увидим уже результат второго запроса
?id=1+union+select+1,2,3+limit+1,1 - здесь тоже
Помоему удобнее "вырубать" первый запрос несуществующим значением (или условием), чем использовать limit.
Кстати если вы всё таки хотите использовать limit, то учтите что limit 1,1 - будет выводить первую строку второго запроса, а limit 0,1 первый запрос (опять же если получение результата идёт не в цикле и результат первого запроса - одна строка).
-------------------------------------- --------------------------------------
union поддерживается в mysql начиная с 4.0 версии, а вот подзапросы только с 4.1.
Т.е. "раскручивать" не слепую инъекцию через подзапросы возможно в меньших случаях чем через объединение запросов (некоторые скрипты/проги/сплойты могут быть написаны с использованием подзапросов).