• XSS.stack #1 – первый литературный журнал от юзеров форума

Статья RCE через Server-Side Template Injection

WDBlue

ripper
КИДАЛА
Регистрация
06.10.2020
Сообщения
61
Реакции
32
Пожалуйста, обратите внимание, что пользователь заблокирован
В этой статье мы увидим, как я обнаружил уязвимость удаленного выполнения кода и обошел правило(а) Akamai WAF. Пока я проводил сканирование на безопасность, я заметил endpoint, который включает управляемые пользователем данные в строку и отражает их обратно в ответе. Заметив отражение текста, я попробовал несколько XSS-payloads, но не смог успешно выполнить JavaScript, так как типом ответа Content-Type было application/json. Однако, при вводе полезной нагрузки, такой как ${191*7}. Я был удивлен, увидев, что арифметическое выражение было успешно выведено в ответе как

getApprovalGroupByContext.contextType: 1337

1606209407800.png

Примечание: "RCE_" не является частью полезной нагрузки, он используется только для поиска отраженного текста.


Требование символа $ в синтаксисе для успешной оценки выражения обычно указывает на то, что при обработке выражения задействован некий шаблонный движок/обработка со стороны сервера.

Шаблонные движки широко используются веб-приложениями для представления динамических данных через веб-страницы и электронную почту. Небезопасное встраивание пользовательского ввода в шаблоны позволяет выполнять Server-Side Template Injection.

В этом случае пользователь управляет содержимым параметра context_type в запросе . После обнаружения инъекции шаблона, следующим шагом было определение используемого шаблонного движка. Этот шаг иногда столь же тривиален, как и отправка некорректного синтаксиса, так как шаблонизаторы могут идентифицировать себя в сообщениях об ошибках. Однако, эта техника не работает, когда вывод сообщений об ошибках отключен. После немного большего исследования в Интернете, у меня появилось несколько догадок о том, какой шаблонный движок это приложение могло бы использовать.

Для оценки воздействия уязвимости я провел еще несколько исследований, чтобы найти полезную нагрузку, которую я мог бы использовать для выполнения команд удаленно, и обнаружил, что следующую полезную нагрузку можно было бы использовать для выполнения команды ls на удаленном сервере:

Код:
${"".getClass().forName("java.lang.Runtime").getMethods()[6].invoke("".getClass().forName("java.lang.Runtime")).exec("ls")}

1606210373500.png


После выполнения я не видел результатов команды в ответе, потому что это была слепая инъекция, но я получил ссылку на Unix-процесс (выделена в теле ответа выше). Это подтвердило, что команда была выполнена успешно.

Теперь все стало интереснее, так как я хотел загрузить reverse shell (тип оболочки, в котором целевая машина взаимодействует обратно с атакующей машиной). Я выполнил еще две команды, чтобы посмотреть, установлены ли уже модули python и wget, чтобы загрузить и выполнить обратный скрипт оболочки. В результате выполнения я получил ссылку на процесс, указывающую, что утилиты предустановлены. Это неудивительно, так как такие утилиты очень часто встречаются в комплекте на многих Unix.

1606210447900.png



Поэтому я запустил HTTP-сервер на порту 80 с помощью python и разместил обратный скрипт оболочки, как показано ниже:

1606210683700.png



Сначала я загрузил reverse shell на уязвимый сервер.

1606210825700.png



Ссылки на процесс Unix в ответе было достаточно, чтобы понять, что reverse shell был загружен на удаленную машину. Следующим шагом был запуск Netcat listener на порту 443 (чтобы поймать шелл) и выполнение скрипта. Как вы видите на скриншоте ниже, я смог получить reverse shell и выполнить команды.

1606210924600.png




Следующей задачей было обойти Akamai WAF для выполнения RCE на производственном сервере.

Я получил такой же ответ от производственного сервера для основных математических операций, таких как умножение и деление, который подтвердил, что ошибка существует и на производственном сервере. Однако, конечная полезная нагрузка не выполнилась, в результате чего появилась страница 403 ошибки, отображающая сообщение "Access Denied" (Доступ запрещен).

Я решил разбить полезную нагрузку на несколько частей, чтобы проверить, что безопасно и опасно согласно правилам WAF. Этот метод проб и ошибок помог мне вычислить следующие два ключевых слова как небезопасную строку для WAF:
  • “java.lang.Runtime”
  • ().
Payload для выполнения:
Код:
${"".getClass().forName("java.lang.Runtime").getMethods()[6].invoke("".getClass().forName("java.lang.Runtime")).exec("wget")}

Я начал просматривать документацию по языку Java, чтобы узнать, есть ли альтернативный способ вернуть строку "java.lang.Runtime". Потратив некоторое время, я обнаружил несколько способов сделать это, но для этого случая сработал только метод concat.
1606211227800.png


“java.lang.Runtime” === “java.lang”.concat(“.Runtime”)

Так я смог обойти первую проверку. Пока что полезная нагрузка:
Код:
${"".getClass().forName("java.lang".concat("Runtime")).getMethods()[6].invoke("".getClass().forName("java.lang".concat("Runtime"))).exec("wget")}

Следующей задачей было обойти (). проверку по ключевым словам. После проведения некоторого анализа я заметил, что если я поставлю какой-нибудь символ между () и . брандмауэром не блокирует его, но это сломает нашу полезную нагрузку, так как метод цепочки не будет работать.

Есть ли способ сделать это, не сломав цепочку? Пока я вспоминал основы JavaScript, я думал о самоназванных функциях. Я никогда не программировал на Java, так что я не был уверен, что это вообще сработает, но я подумал о том, что можно попробовать.

В случае JavaScript console.log(“hello”), (console.log(“hello”)) и (console.log)(“hello”) имеют одинаковое значение.
1606212105100.png


Я заменил getClass() на (getClass()) и так как не было никакой проверки по ключевому слову ()), я смог обойти и вторую проверку.

Конечный payload был:
Код:
${("".getClass()).forName("java.lang".concat("Runtime")).getMethods()[6].invoke(("".getClass()).forName("java.lang".concat("Runtime"))).exec("wget")}


Я выполнил полезную нагрузку и в ответе получил номер процесса, похожий на тот, который я получил для инсценировки, это подтвердило, что я смог удаленно выполнять команды на рабочем сервере.
1606212195900.png


По понятным причинам я не пытался загрузить шелл/вредный код на рабочий сервер, однако я проверил, возможно ли сделать исходящий запрос с рабочего сервера к Burp Collaborator.

Я выполнил запрос, чтобы узнать, будет ли производственный сервер выполнять DNS поиск или нет.

1606212276400.png


Через несколько секунд я получил запрос на поиск, раскрывающий реальный IP адрес производственного (исходного) сервера.

1606213303300.png



Противодействие:
Лучший способ предотвратить инъекцию шаблонов на стороне сервера - не позволять никаким пользователям изменять или отправлять новые шаблоны. Однако иногда это неизбежно в связи с требованиями бизнеса.

Один из простейших способов избежать SSTI - всегда использовать "беслогичный" шаблонный движок, такой как Mustache, если в этом нет абсолютной необходимости. Максимально возможное отделение логики от вывода информации может значительно уменьшить вашу подверженность наиболее опасным атакам на основе шаблонов.

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

Наконец, еще одним дополнительным подходом является признание того, что произвольное выполнение кода практически неизбежно, и применение собственной "песочницы" путем развертывания среды шаблонов, например, в заблокированном контейнере Docker.

Другие предложения:

Для предотвращения загрузки злоумышленниками вредоносного кода или обхода фильтрации данных, должны быть установлены белые списки URL-адресов.


Ключевые моменты:

  • Ни один WAF не является 100% точным, и ни один WAF не является непобедимым
  • Если вы нашли ошибку, попробуйте исправить ее на уровне кода и не полагайтесь полностью на WAF.
  • Всегда старайтесь повысить уязвимость до максимального уровня.
  • Знание о внутренних и внешних зависимостях, структурах и т.д., это плюс.
Источник
 


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх