понедельник, 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)))

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


среда, 25 ноября 2009 г.

SQLinj XYNTA

Это мой первый пост и он будет полон ненависти, как , сразу предупреждаю, и многие последующие.

Начну я с того, что

"sql инъекции являются типичной уязвимость web-приложений, основная их идея заключается в бла-бла-бла, ниже мы приводим нисколько примеров, которые описывают типичные способы проведения инъекций.. "

такую высокопарную пердь вы читали миллионы раз в сотнях мануалов "для начинающих "! То что эти примеры скопипижжены друг с друга, я принимаю как данность и напишу об этом позже. Больше всего выбешивает их близость к реальным условиям, а точнее её полное отсутствие. Можно привести десятки примеров для эксплуатации запроса типа

SELECT бла FROM бла_table WHERE id=*;

В примерах будет описан красочно обход разносортных WAF , mod_security и многий прочий всякий кал.
НО!..
Хоть бы один Ыксперт, мать его, заикнулся о том, что запросы бывают не только такие, но ещё и такие:

SELECT b.*, UNIX_TIMESTAMP(b.book_date) AS book_date, SUM(t.tran_cost) AS book_contribution, g.book_genre_title AS book_genre, g.book_genre_id, m.name FROM bookreview b LEFT JOIN theopenp_forums.prb_members m ON m.id = b.book_user LEFT JOIN transactions t ON t.tran_package_item = b.book_id LEFT JOIN packages pa ON t.tran_package = pa.pack_id LEFT JOIN book_genre g ON b.book_genre = g.book_genre_id WHERE book_id =* AND pa.pack_type in ('BK', 'BKS') AND b.book_approved = 1 AND b.book_denied = 0 GROUP BY b.book_id

И что для того, чтоб победоносно выхватить солёный хеш и носиться с ним, аки уездный мудак (так как пользы от такого хеша ...), нужно просидеть не 5 минут и даже не полчаса, насилуя своё абстрактное мышление и пытаясь понять, какого же монстра мы собираем таким запросом и чего им можно вытащить.

Конечно, в случае слепой инъекции, можно запустить перебор и пойти попить чайку, но имейте ввиду, что при херовой связи и большой базе, хешик может стать лучшим подарком к вашему 60летию.

Так вот, возвращаясь к нашим бумагомарателям, ГДЕ СЛОЖНЫЕ ПРИМЕРЫ!? ГДЕ СЛОЖНЫЕ ПРИМЕРЫ, БЛЕАТЬ!? Почему я всё время созерцаю в примерах несуразную хуйню, в то время, как в серьёзных приложениях из реального мира используются такие SQL оглобли, что даже с моим расширением монитора мне приходится нарезать их в 3 строчки!