понедельник, 15 февраля 2010 г.

ISO.ORG

Наткнулся на красноречивый случай SQLinj на сайте ISO.org .
После беглого просмотра сайта, тезис ,о том что безопасность вебприложений слабо зависит от размеров организации и её бюджета, подтвердился очередной раз =(



Здесь ,например, можно созерцать почтовые ящики участников комитетов. Хотя после более глубокого исследования, становится понятно, что всё не совсем плохо с точки зрения администрирования СУБД. Так же не найдено признаков админки, доступной из интернета, то есть сайт по-видимому пушится откуда-то из недров intraneta.

На исправление данной уязвимости ISO понадобилось около 3 недель с момента первого моего репорта, который я отправлял еженедельно. Кроме того, не смотря на заплатку, искушённому читателю не составит труда продолжить моё исследование через другие дырки.

Танцы вокруг Order by

Добрый день. Сегодня я расскажу про некоторые особенности эксплуатации инъекции в среде MySQL, когда уязвимым является параметр идущий за директивой order by, то есть как-то так:

... order by [inj] ... ;


Эта тема довольно интересна , так как многие "веб-мостера" почему-то настойчиво отказываются хоть как-то фильтровать входящие данные, хардкодя в сайтах название колонок из своих баз. То есть, если пользователь получает какой-то список или таблицу, то сортировку ему предлагается делать по следующей ссылке:

...ager/run/?sD[sortby]=blablabla&sD[direction]=asc

Что с этим можно сделать?

1. Юные подаваны могут впасть в уныние, узнав, что union в таких случаях можно сделать только , когда конструкция имеет вид:

(SELECT ... ORDER BY blablabal) UNION (SELECT ....)

Если кто-то не понял, то соль в скобке, которая находится в неуязвимой части запроса.
Хотя для справедливости стоит отметить, что особо "прогрессивные" разработчики скобки зачем-то используют...

2. Если в открытую данные получить не удалось, но остаётся только вслепую. То есть нам нужно найти такие данные, передавая которые мы сможем получить однозначную логическую связь между данными в базе и ответом сервера. Первый способ, который приходит в голову это

... ORDER BY IF(1=1,'blablabla',(SELECT 2 UNION SELECT 1))

Как можно видеть, что в случае когда выражение, которое мы поставим вместо 1=1, вернёт ложь, нарушится выполнение всего запроса (Subquery returns more than 1 row) и данные мы получить не сможем. Этого уже достаточно, чтоб пройтись бинарным поиском по атакуемой базе. Кстати, стоит заметить, что представленный здесь blablabla, с точки зрения СУБД не имеет никакого отношения к колонке blablabla и воспринимается как случайная строка.

3. Этого пункта здесь бы вообще не было, если бы некоторые разработчики не были бы фанатами логов и отчётности ( встречается это обычно в бизнес-приложениях) . Если коротко, то есть ресурсы в которых есть рассматриваемая уязвимость, но все запросы, которые вызывают ошибку при обработке SQL запросов с CУБД записываются и отправляются по почте администратору. На моём опыте весб процесс информирования, анализа и забанивания занимал около 20 минут, которых недостаточно для какого-либо обстоятельного знакомства с базой...

Итак, нам нужен запрос, передавая который мы сможем получить однозначную логическую связь между данными в базе и ответом сервера, не вызывая ошибок. Для этого воспользуемся способом, описание которого я видел в этой статье . Суть его в том, чтоб инвертировать сортировку по параметру. Сделать это можно вот так:

...ORDER BY blablabla*(-1)...

Сочетая это с предыдущим способом, получаем:

...ORDER BY blablabla*(if(1=1,1,(-1)))

То есть логическим выводом для нас будет направление сортировки данных.В результаты мы, как и требовалось, получаем однозначные данные, не вызывая никаких ошибок или исключений со стороны СУБД.