SSTIServer Side Template Injection,即服务端模板注入
0x00 前言
SSTI:Server Side Template Injection,即服务端模板注入。
在web开发中,为了使用户界面与业务数据分离,提升开发效率,因此会使用模板引擎来生成一个标准的HTML文档用来数据的展示。
本文主要针对java中Velocity、FreeMarker以及Thymeleaf三个模板的注入漏洞进行分析
0x01 velocity
1.1 Velocity简介
Apache Velocity是一个基于Java的模板引擎,它提供了一个模板语言去引用由Java代码定义的对象。Velocity旨在确保Web应用程序在表示层和业务逻辑层之间的隔离(即MVC设计模式)。
语法概要
在 Velocity 中所有的关键字都是以#开头的,而所有的变量则是以$开头
"#"用来标识Velocity的脚本语句,包括#set、#if 、#else、#end、#foreach、#end、#iinclude、#parse、#macro等;
"$"用来标识一个对象(或理解为变量);如$i、$msg、$TagUtil.options(...)等;
"{}"用来明确标识Velocity变量;
"!"用来强制把不存在的变量显示为空白;
1.2 漏洞利用
环境:java-sec-code(https://github.com/JoyChou93/java-sec-code/)
服务端代码:
访问/ssti/velocity?template=并提交payload
断点进行拦截提交的payload,并跟进Velocity.evaluate方法进行分析
继续跟进evaluate方法
RuntimeInstance类中封装了evaluate方法
继续跟进分析,可以看到parse方法对reader进行解析
跟进分析,可以看出进行一次判断,如果nodeTree不为空则进入render方法
继续跟进分析,多次循环后会进行execute方法下进行for循环,进行payload的遍历
遍历完成后命令成功执行
0x02 FreeMarker
2.1 FreeMarker简介
FreeMarker 是一款模板引擎:即一种基于模板和要改变的数据, 并用来生成输出文本(HTML网页,电子邮件,配置文件,源代码等)的通用工具。 它不是面向最终用户的,而是一个Java类库,是一款程序员可以嵌入他们所开发产品的组件。
当需要一个类似Output的页面时,就可以利用FreeMarker模板代码来进行生成。
FreeMarker模板代码:
<html>
<head>
<title>Welcome</title>
</head>
<body>
<h1>Welcome ${user}!</h1>
</body>
</html>
模板文件存放在Web服务器上,就像通常存放静态HTML页面那样。当有人来访问这个页面, FreeMarker将会介入执行,然后动态转换模板,用最新的数据内容替换模板中 ${...} 的部分, 之后将结果发送到访问者的Web浏览器中。
FreeMarker模板注入主要利用freemarker.template.utility里面的Excute类来执行命令,利用FreeMarker中的内建函数new,new是用来创建一个确定的 TemplateModel 实现变量的内建函数,新建一个Excute类,并将需要执行的命令传入其中。
具体的payload的构造按照该内建函数的用法进行构造,可以参考http://freemarker.foofun.cn/ref_builtins_expert.html#ref_builtin_new,具体用法如下:
<#-- Creates an user-defined directive be calling the parameterless constructor of the class -->
<#assign word_wrapp = "com.acmee.freemarker.WordWrapperDirective"?new()>
<#-- Creates an user-defined directive be calling the constructor with one numerical argument -->
<#assign word_wrapp_narrow = "com.acmee.freemarker.WordWrapperDirective"?new(40)>
2.2 漏洞利用
服务端代码:
模板代码:
payload:<#assign ex="freemarker.template.utility.Execute"?new()>${ ex("calc") }
请求/hello获取模板,可以看出成功实现,对应数据提交到了模板中展示
构造payload,请求/template
post提交payload,注入恶意模板代码,并在for循环中进行断点调试
可以看出stringLoader,也就是StringTemplateLoader函数下的putTemplate通过key:value的形式获取到传入的payload,达到注入hello.ftl的效果
再访问/hello获取模板,达到恶意代码执行的效果。
0x03 Thymeleaf
3.1 Thymeleaf简介
Thymeleaf是springboot官方推荐使用的java模板引擎,提供spring标准方言和一个与 SpringMVC 完美集成的可选模块,可以快速的实现表单绑定、属性编辑器、国际化等功能。
Thymeleaf简单表达式:
- 变量表达式: ${...}
- 选择变量表达式: *{...}
- 消息表达式: #{...}
- 链接网址表达式: @{...}
- 片段表达式: ~{...}
简单的Thymeleaf模板代码
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Good Thymes Virtual Grocery</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link rel="stylesheet" type="text/css" media="all"
href="../../css/gtvg.css" th:href="@{/css/gtvg.css}" />
</head>
<body>
<p th:text="#{home.welcome}">Welcome to our grocery store!</p>
</body>
</html>
3.2 漏洞利用
环境:spring-view-manipulation(https://github.com/veracode-research/spring-view-manipulation/)
服务端代码:
模板代码:
漏洞利用方法一:
payload:__$%7bnew%20java.util.Scanner(T(java.lang.Runtime).getRuntime().exec(%22calc%22).getInputStream()).next()%7d__::.x
uri:/path?lang=__$%7bnew%20java.util.Scanner(T(java.lang.Runtime).getRuntime().exec(%22calc%22).getInputStream()).next()%7d__::.x
进行数据提交,成功获取到提交的payload
进行跟进,在 org.thymeleaf.spring5.view 中的 ThymeleafView类中thymeleaf 在解析包含 :: 的模板名时,会将其作为表达式去进行执行
继续跟进,在StandarExpressionPreprocessor类中利用正则对__(.*?)__进行匹配,也就是payload__中间的内容
匹配处理完成后为${new.java.util.Scanner(T(java.lang.Runtime).getRuntime().exec("calc").getInputStream()).next()}
继续跟进execute
可以看到是使用的SPEL 引擎,满足**(${SPEL})**::格式达到注入的效果
进入后成功执行代码
漏洞利用方法二:
payload:__$%7BT(java.lang.Runtime).getRuntime().exec(%22calc%22)%7D__::.x
uri:/doc/__$%7BT(java.lang.Runtime).getRuntime().exec(%22calc%22)%7D__::.x
因为该请求无返回值,因此返回值无法作为模板名,这个时候传入的参数也就是payload便作为了视图名
进行跟进,在 org.thymeleaf.spring5.view 中的 ThymeleafView类中thymeleaf 在解析包含 :: 的模板名时,会将其作为表达式去进行执行
继续跟进,在StandarExpressionPreprocessor类中利用正则对__(.*?)__进行匹配,也就是payload__中间的内容,匹配处理完成后为${T(java.lang.Runtime).getRuntime().exec(%22calc%22)}
可以看到是使用的SPEL 引擎,满足**(${SPEL})**::格式达到注入的效果
- 本文作者: 阿蓝
- 本文来源: 奇安信攻防社区
- 原文链接: https://forum.butian.net/share/1661
- 版权声明: 除特别声明外,本文各项权利归原文作者和发表平台所有。转载请注明出处!