ЖУРНАЛ ХАКЕР

SQL Hacking

Xakep, номер #030, стр. 030-044-2


Самый простой способ

Некоторые извращенцы берут название таблицы прямо из URL. Ну, скажем, у чувака несколько форумов с разными названиями, для удобства он назвал таблицы в SQL, которые содержат мессаги форумов, также как сами форумы. Типа http://blabla.ru/forum.php?forum=main выводит основной форум, а http://blabla.ru/forum.php?forum=sex выводит форум для сексуально озабоченных. Параметр "forum", передаваемый из URL, в PHP/Perl-скрипте будет заноситься в переменную $forum. Таким образом, чувак везде в своих скриптах может писать что-то типа:

SELECT * FROM $forum;

DELETE FROM $forum WHERE id=5;

и так далее...

Проблема в том, что название таблицы обычно не проверяют на правильность. Тогда, если мы укажем в URL значение forum типа "main; DROP TABLE main; SELECT * FROM main", скрипт чувака может запустить команду:

SELECT * FROM main; DROP TABLE main; SELECT * FROM main;

Как видно, это не то, на что рассчитывал творец с самого начала. Таким же образом мы можем вывести таблицу с логинами и паролями форума (если таковые есть).

Опять же оператор DROP сработает только в том случае, если чувак настолько тупой, что не убрал право стирать таблицы у SQL-ного юзера, под которым юзается скрипт. Поверь мне, таких даунов не мало.

Заморочки

Описанный выше способ часто применим и для других параметров, передаваемых в URL. Переменные типа символа или строки чаще всего обособляют, ведь иначе SQL сервер заплачет, что ему неправильно параметр дали. Но вот числа передаются "как есть", и проверку, что это действительно числа, делают далеко не все. Обычная команда, вставляющая данные, полученные от юзера, выглядит так:

UPDATE <таблица> first_name='$fname', last_name='$lname', age=$age WHERE id=<id юзера>;

Допустим, это у нас база юзеров какого-то тупого чата (и мы находимся в настройках), а также знаем, что там есть еще поле level, в котором содержится уровень привилегий, который, по дефолту, у юзверов, как несложно догадаться, "user", а у крутых и злых админов - "supervisor".

Параметр "age", являющийся числом, отдается SQL'у без обособления (как и название таблицы), а также не проверяется в скрипте на корректность. Следовательно, если мы скажем им, что age = "25, level='supervisor'", то их тупой скрипт обновления установок юзверя пошлет такую команду на SQL-сервер:

UPDATE <таблица> first_name='$fname', last_name='$lname', age=25, level='supervisor' WHERE id=<id юзера>;

Оп-ля, мы получили уровень админа. Напомню, что параметры можно передавать из URL (http://blabla.ru/cgi-bin/change.pl?first_name=...&last_name=...?age=...) или из HTML файла. В последнем случае потребуется сохранить нужную страничку у себя на диске. Затем отредактировать, просмотреть со своего винта и нажать "submit" (это сработает не везде, многие смотрят в поле http_referer и на cookies, которые, правда, тоже можно подделать ;).

Назад на стр. 030-044-1  Содержание  Вперед на стр. 030-044-3