服务端模板注入 (Server Side Template Injection)
模板注入允许攻击者将模板代码包含到现有(或不存在的)模板中。模板引擎通过使用静态模板文件使设计 HTML 页面变得更容易,这些文件在运行时将 HTML 页面中的变量/占位符替换为实际值。
摘要 (Summary)
- 工具 (#tools)
- 方法论 (#methodology)
- 实验环境 (Labs)
- 参考资料 (#references)
工具 (Tools)
- Hackmanit/TInjA - 一个高效的 SSTI + CSTI 扫描器,利用了创新的混合载荷(Polyglots)。
tinja url -u "http://example.com/?name=Kirlia" -H "Authentication: Bearer ey..."
tinja url -u "http://example.com/" -d "username=Kirlia" -c "PHPSESSID=ABC123..."
- epinna/tplmap - 服务端模板注入与代码注入检测及利用工具。
python2.7 ./tplmap.py -u 'http://www.target.com/page?name=John*' --os-shell
python2.7 ./tplmap.py -u "http://192.168.56.101:3000/ti?user=*&comment=supercomment&link"
python2.7 ./tplmap.py -u "http://192.168.56.101:3000/ti?user=InjectHere*&comment=A&link" --level 5 -e jade
- vladko312/SSTImap - 基于 epinna/tplmap 改进的具有交互界面的自动 SSTI 检测工具。
python3 ./sstimap.py -u 'https://example.com/page?name=John' -s
python3 ./sstimap.py -i -u 'https://example.com/page?name=Vulnerable*&message=My_message' -l 5 -e jade
python3 ./sstimap.py -i -A -m POST -l 5 -H 'Authorization: Basic bG9naW46c2VjcmV0X3Bhc3N3b3Jk'
方法论 (Methodology)
检测与利用技术 (Detection and Exploitation Techniques)
原始研究成果:
- 回显型、时间型:服务端模板注入:现代 Web 应用的 RCE 手法 - James Kettle - 2015年8月5日
- 混合载荷型:改进大规模模板注入扫描中模板引擎的检测与识别 - Maximilian Hildebrand - 2023年9月19日
- 报错型、布尔型:成功的错误:新的代码注入与 SSTI 技术 - Vladislav Korchagin - 2026年1月3日
回显型 (Rendered)

适用场景:检测、利用
当渲染后的模板显示给攻击者时,可以使用回显技术在页面上包含注入代码的执行结果。
报错型 (Error-Based)

适用场景:检测、利用
当错误信息详细地展示给攻击者时,可以使用报错技术触发包含注入代码执行结果的错误消息。
布尔型 (Boolean-Based)

适用场景:检测、盲注利用、盲数据外带
布尔技术可用于有条件地触发错误,以指示注入代码的执行成功或失败。
时间型 (Time-Based)

适用场景:有限检测、盲注利用、盲数据外带
时间技术可用于有条件地触发延迟,以指示注入代码的执行成功或失败。
触发延迟通常需要猜测用于代码评估或操作系统命令执行的载荷。
带外型 (Out of Bounds)
适用场景:有限检测、利用
带外技术可用于通过其他渠道(例如通过连接到攻击者控制的服务器)获取注入代码的执行结果。
这种技术通常需要猜测用于代码评估或操作系统命令执行的载荷。
多载荷混合型 (Polyglot-Based)

适用场景:检测
混合载荷技术可通过检查模板引擎如何转换不同的载荷,来快速确定其类型。
通用探测载荷 (Universal Detection Payloads)
在存在 SSTI 漏洞时触发错误的混合载荷实例:
常用于测试带有代码评估功能的 SSTI 标签:
{{ ... }}
${ ... }
#{ ... }
<%= ... %>
{ ... }
{{= ... }}
{= ... }
\n= ... \n
*{ ... }
@{ ... }
@( ... )
可以通过在标签内使用数学表达式来检查回显型 SSTI:
可以通过在标签内使用此载荷来检查报错型 SSTI:
如果该载荷导致的错误被详细显示,则可以通过检查错误信息来猜测用于代码评估的语言:
| 错误信息 (Error) | 开发语言 (Language) |
|---|---|
| ZeroDivisionError | Python |
| java.lang.ArithmeticException | Java |
| ReferenceError | NodeJS |
| TypeError | NodeJS |
| Division by zero | PHP |
| DivisionByZeroError | PHP |
| divided by 0 | Ruby |
| Arithmetic operation failed | Freemarker (Java) |
为了利用布尔技术测试盲注,攻击者可以测试包装在标签内的一对相似载荷,其中一个载荷评估数学表达式,而另一个触发语法错误:
| 测试序号 | 正确状态 (ok) | 错误状态 (error) |
|---|---|---|
| 1 | (3*4/2) |
3*)2(/4 |
| 2 | ((7*8)/(2*4)) |
7)(*)8)(2/(*4 |
使用至少两对载荷可以避免由外部干扰引起的误报。
人工检测与利用 (Manual Detection and Exploitation)
识别存在漏洞的输入字段
攻击者首先定位输入字段、URL 参数或应用程序中任何用户可控的部分,这些部分会被传入服务器端模板而没有经过适当的清洗或转义。
例如,攻击者可能会识别出网页表单、搜索栏或模板预览功能,这些功能似乎会根据动态用户输入返回结果。
提示 (TIP):生成的 PDF 文件、发票和电子邮件通常使用模板引擎。
注入模板语法
攻击者通过注入特定于所用模板引擎的语法来测试识别出的输入字段。不同的 Web 框架使用不同的模板引擎(例如,Python 的 Jinja2,PHP 的 Twig,或 Java 的 FreeMarker)。
常见的模板表达式:
{{7*7}}适用于 Jinja2 (Python)。#{7*7}适用于 Thymeleaf (Java)。
在各技术专项页面(PHP, Python 等)查找更多模板表达式。

在大多数情况下,这个混合载荷(Polyglot)会在存在 SSTI 漏洞时触发错误:
Hackmanit/Template Injection Table 是一个交互式表格,包含最高效的模板注入混合载荷以及 44 个最重要的模板引擎的预期响应。
枚举模板引擎
根据成功的响应,攻击者确定正在使用哪个模板引擎。这一步至关重要,因为不同的模板引擎具有不同的语法、功能和利用潜力。攻击者可能会尝试不同的载荷来查看哪一个被执行,从而识别引擎。
- Python: Django, Jinja2, Mako, ...
- Java: Freemarker, Jinjava, Velocity, ...
- Ruby: ERB, Slim, ...
@0xAwali 的博客文章 "template-engines-injection-101" 总结了 JavaScript, Python, Ruby, Java 和 PHP 大部分模板引擎的语法和检测方法,以及如何区分使用相同语法的引擎。
提升至代码执行
一旦识别出模板引擎,攻击者就会注入更复杂的表达式,旨在执行服务器端命令或任意代码。
实验环境 (Labs)
参考资料 (References)
- 服务端模板注入:现代 Web 应用的 RCE 手法 - James Kettle - 2015年8月5日
- 改进大规模模板注入扫描中模板引擎的检测与识别 - Maximilian Hildebrand - 2023年9月19日
- 成功的错误:新的代码注入与 SSTI 技术 - Vladislav Korchagin - 2026年1月3日
- 渗透测试人员服务端模板注入 (SSTI) 指南 - Busra Demir - 2020年12月24日
- 利用服务端模板注入 (SSTI) 获取 Shell - David Valles - 2018年8月22日
- 模板引擎注入基础 101 - Mahmoud M. Awali - 2024年11月1日
- 在加固目标上进行模板注入 - Lucas 'BitK' Philippe - 2022年9月28日
- 限制只是幻觉——带 RCE 的高级服务端模板利用 - YesWeHack, Brumens - 2025年3月24日