• Что бы вступить в ряды "Принятый кодер" Вам нужно:
    Написать 10 полезных сообщений или тем и Получить 10 симпатий.
    Для того кто не хочет терять время,может пожертвовать средства для поддержки сервеса, и вступить в ряды VIP на месяц, дополнительная информация в лс.

  • Пользаватели которые будут спамить, уходят в бан без предупреждения. Спам сообщения определяется администрацией и модератором.

  • Гость, Что бы Вы хотели увидеть на нашем Форуме? Изложить свои идеи и пожелания по улучшению форума Вы можете поделиться с нами здесь. ----> Перейдите сюда
  • Все пользователи не прошедшие проверку электронной почты будут заблокированы. Все вопросы с разблокировкой обращайтесь по адресу электронной почте : info@guardianelinks.com . Не пришло сообщение о проверке или о сбросе также сообщите нам.

RainLoop. Проходим путь от шелла до кеша — через аттач

Sascha Оффлайн

Sascha

Заместитель Администратора
Команда форума
Администратор
Регистрация
9 Май 2015
Сообщения
1,480
Баллы
155
Представь: старый почтовый веб‑клиент, давно забытый и оставленный пылиться в закоулках интернета, но по‑прежнему таящий в себе кладезь... Это история о том, как глубокое погружение в RainLoop привело к тому, что я нашел RCE и способ получить доступ к данным пользователей крупной компании, которая не пожалела вознаграждения.


Это исследование получило первое место на

Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.

в категории «Пробив WEB». Соревнование ежегодно проводится компанией Awillix.


RainLoop — это проект на PHP с открытым исходным кодом и четырьмя тысячами звезд на GitHub. Мы совершим увлекательное путешествие по лабиринтам его кода, заглянем в механизмы криптографии и проделаем пару трюков с хостами, которые, казалось бы, в скоуп не входят, но позволят сорвать джекпот.

warning


Статья имеет ознакомительный характер и предназначена для специалистов по безопасности, проводящих тестирование в рамках контракта. Автор и редакция не несут ответственности за любой вред, причиненный с применением изложенной информации. Распространение вредоносных программ, нарушение работы систем и нарушение тайны переписки преследуются по закону.

Исходная позиция


Все началось обычным вечером, когда я, вооружившись чашкой кофе, проводил первичную разведку баг‑баунти‑скоупа хостера beget.com. В SSL-сертификате одного из сотен доменов мелькнул любопытный хост. Это был почтовый клиент, который компания предоставляла своим зарегистрированным пользователям, на поддомене вида fancy.beget.email.

Там был установлен RainLoop, что показалось мне довольно странным, так как основным веб‑мейлером выступал Roundcube. И тут я просто не смог устоять перед соблазном покопаться в исходниках.

Это приложение я видел впервые, к тому же версия оказалась не самой свежей — 1.12.1. Все говорит о том, что покопаться в исходниках будет отличной идеей, к тому же это моя страсть! Мотивирует одна только возможность найти что‑то интересное.

Проект оказался нишевым, но не совсем — поисковик FOFA находит 21 433 IP-адреса, по которым отвечает RainLoop.

alt


Что ж, отличное комбо! Приступаем к исследованию.

Опасная десериализация


Скачав

Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.

RainLoop, я начал искать потенциальные точки входа для атаки. Моей целью было найти уязвимость, которая позволила бы выполнить произвольный код или команды на сервере.

Одной из первых находок стал метод RainLoop\Utils::DecodeKeyValuesQ(). Он обрабатывает данные, которые затем попадают в функцию unserialize, классический такой вектор для RCE.

./rainloop/v/1.12.1/app/libraries/RainLoop/Utils.php


static public function DecodeKeyValuesQ($sEncodedValues, $sCustomKey = '')

{

$aResult = @\unserialize(

\RainLoop\Utils::DecryptStringQ(

\MailSo\Base\Utils::UrlSafeBase64Decode($sEncodedValues), \md5(APP_SALT.$sCustomKey)));

return \is_array($aResult) ? $aResult : array();

}


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

Читалка секретов


Следующим этапом стал поиск других уязвимостей, которые помогли бы раскрыть этот ключ. Благо приложение имеет большой пласт самых разных фич.

Один из десятка методов, RainLoop\Actions\DoComposeUploadExternals(), оказался настоящим подарком для атакующего. Данные, поступающие от пользователя, без какой‑либо постобработки попадают напрямую в CURLOPT_URL.

/rainloop/v/1.12.1/app/libraries/RainLoop/Actions.php


public function DoComposeUploadExternals()

{

...

$aExternals = $this->GetActionParam('Externals', array());

if (\is_array($aExternals) && 0 < \count($aExternals))

{

...

foreach ($aExternals as $sUrl)

{

if ($rFile && $oHttp->SaveUrlToFile($sUrl, $rFile, '', $sContentType, $iCode, $this->Logger(), 60,

...

}

return $this->DefaultResponse(__FUNCTION__, $mResult);

}

./rainloop/v/1.12.1/app/libraries/MailSo/Base/Http.php


public function SaveUrlToFile($sUrl, $rFile, ...){

...

$aOptions = array(

CURLOPT_URL => $sUrl,

...

$oCurl = \curl_init();

\curl_setopt_array($oCurl, $aOptions);

...

$bResult = \curl_exec($oCurl);

...

return $bResult;

}


И это открывает двери для множества атак, включая SSRF через схемы вроде gopher://, так как curl поддерживает десятки разных протоколов, в том числе чтение локальных файлов через file://, что было для меня главным!

Метод сам по себе не отдавал содержимое файла сразу, поэтому для успешной эксплуатации требовалась совокупность действий:

  • Создать новое письмо и прикрепить к нему произвольный аттач, например 123.txt.
  • Сохранить письмо в черновики и перехватить этот запрос (1).

  • В запросе (1) заменить POST-данные такими:


    XToken=__CSRF_TOKEN__&Action=ComposeUploadExternals&Externals[]=file:///var/www/html/data/SALT.php


  • Отправить и скопировать хеш аттача из респонса (2).


  • Поменять хеш в (1) на (2) и отправить запрос.


  • В аттаче нового письма в черновиках будет содержимое файла SALT.php.
alt


Так я наконец смог прочитать файл, в котором хранилась секретная соль.

/var/www/html/data/SALT.php


<?php //a58a35a5c3c08f4f047364531dee2dc3fbd99005c0c7e5abedcc0f531def5b1b329e151c4b801d27248bce1d27996eca3364


Соль, как видишь, имеет внушительный размер и полностью используется для шифрования строк.

./rainloop/v/1.12.1/include.php


$sSalt = @file_get_contents(APP_DATA_FOLDER_PATH.'SALT.php');


Это тот самый ключ, который нужен для обхода криптографической защиты. Теперь пазл начал складываться, но не хватало главной детали.

Извилистая цепочка до RCE


На этом этапе я столкнулся с новой головоломкой. RainLoop оказался довольно скромным в плане используемых библиотек, да и те, что были, не всегда подгружались через autoload. Мой арсенал для создания цепочки десериализации был, мягко говоря, ограниченным. На «закуску» у меня было всего несколько библиотек:


array(7) {

[0]=>

string(8) "RainLoop"

[1]=>

string(8) "Facebook"

[2]=>

string(8) "PHPThumb"

[3]=>

string(6) "Predis"

[4]=>

string(16) "SabreForRainLoop"

[5]=>

string(7) "Imagine"

[6]=>

string(9) "Detection"

}



Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.

, мой верный спутник в таких делах, лишь грустно вздохнул и самоустранился. Стандартные гаджеты здесь неприменимы... Конечно же, я сразу помчался к великому «Гроку» и не менее умному «Клоду», ведь они за считаные промпты соберут мне то, что нужно. Но как только я начал разгребать их глюки, понял, что проще разбираться самому.

Источник:

Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.

 
Вверх Снизу