Показать сообщение отдельно

SQL injection полный FAQ: использование оператора union
  #43  
Старый 04.08.2008, 20:38
Grey
Познавший АНТИЧАТ
Регистрация: 10.06.2006
Сообщений: 1,113
Провел на форуме:
17668503

Репутация: 5826


По умолчанию SQL injection полный FAQ: использование оператора union

Я устал видеть распространённую ошибку пользователей связанную с использованием 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.
Т.е. "раскручивать" не слепую инъекцию через подзапросы возможно в меньших случаях чем через объединение запросов (некоторые скрипты/проги/сплойты могут быть написаны с использованием подзапросов).

Последний раз редактировалось Grey; 27.09.2008 в 22:01..