Pull to refresh

MySQL: Взламываем черный ящик

Reading time2 min
Views13K
О чем пойдет речь: забавный и экстравагантный способ «взлома» веб-сайта, у которого «всего-лишь» не экранируются кавычки одного из параметров. При этом пропустим рассуждения о том, почему все не экранируется на стороне самого языка программирования или ORM.

Вводная: веб-сайт, у которого не экранируется один из параметров в простом SELECT запросе. При этом все ошибки перехватываются, обрабатываются и выводится скромное «Нет данных» или «Произошла ошибка».

Казалось бы: не велика беда. Обновление или изменение данных в него втереть, данные наружу не открываются, все сводится к «Извините, нет данных» — черный ящик.

Но, что на самом деле можно сделать в данной ситуации?

Сразу соль: техника базируется на функции sleep(N) которую мы будем использовать как лакмус. Замеряем сколько «отдается» страница в обычной жизни. И сколько времени она «отдается» если мы введем ' OR sleep(10) вместо всех параметров которые присутствую в форме. Если время отдачи страницы выросло — дело в шляпе и дальше только дело техники.

Например, подбираем имя таблицы, основываясь на мета-базе INFORMATION_SCHEMA, которая всегда присутствует и доступна всем:

' OR 1 = if((select count(*) from INFORMATION_SCHEMA.tables where TABLE_SCHEMA=database() and TABLE_NAME='users') = 1, sleep(10), null)

Если время «отдачи» страницы существенно увеличилось — угадали, если нет — пробуем еще варианты, обычно их до 10. Дальше «угадываем» имена полей:

' OR 1 = if((select count(*) from INFORMATION_SCHEMA.columns where TABLE_SCHEMA=database() and TABLE_NAME='users' and COLUMN_NAME='login') = 1, sleep(5), null)

Зная имена таблицы и полей, можно «подобрать» длину логина, пароля а так же посимвольно вытащить сами логин и пароль.

if((select count(*) from users where login='admin') = 1, sleep(5), null)
if((select length(password) from users where login='admin') = 1, sleep(5), null)
select if((select mid(password, 5,1) from users where login='admin') = 'a', sleep(5), null)


При двоичном поиске пароля посимвольно потребуется всего 8 запросов на каждый символ.

Да, не ахти какой взлом, но забавный способ исследовать вслепую структуру БД, имена полей (так же можно подбирать посимволно) а так же сами данные.

Кстати, экранировать надо в том числе и постраничную навигацию — метод тот же, но с применением UNION SELECT…

Мораль сей басни: даже единственный не экранируемый параметр из-за которого ну максимум будет «извините, ошибка» может слить всю базу.

Заметка родилась в следствии анализа запросов к одному из сайтов и попыток их осмыслить.

Просьба не холиварить касательно ущербности MySQL как базы данных а так же «единственно истинного» способа экранирования данных.
Tags:
Hubs:
Total votes 122: ↑95 and ↓27+68
Comments25

Articles