1. 模板注入漏洞核心原理
模板注入(Template Injection)发生在应用程序将用户输入直接拼接到模板指令中时,允许攻击者注入恶意模板代码,导致:
-
远程代码执行(RCE)
-
敏感信息泄露
-
服务端文件系统访问
高危模板引擎:
☠️ Java:FreeMarker、Velocity
☠️ Python:Jinja2、Mako、Tornado
☠️ PHP:Twig、Smarty
☠️ JavaScript:Handlebars、EJS
2. 攻击类型与利用场景
(1) 服务端模板注入(SSTI)
漏洞代码示例(Python Flask + Jinja2):
from flask import render_template_string
@app.route('/welcome')
def welcome():
name = request.args.get('name')
return render_template_string(f"Hello {name}") # 直接拼接用户输入
攻击Payload:
http://example.com/welcome?name={{7*7}} # 测试表达式
http://example.com/welcome?name={{config.items()}} # 泄露配置
http://example.com/welcome?name={{%27%27.__class__.__mro__[1].__subclasses__()[408](%27cat+/etc/passwd%27,shell=True,stdout=-1).communicate()}} # RCE
(2) 客户端模板注入(CSTI)
AngJS示例:
$scope.userInput = '{{constructor.constructor("alert(1)")()}}';
(3) 沙箱逃逸技术
-
Python:通过
__class__
链获取object基类 -
Java:利用
ClassLoader
加载恶意类 -
PHP:
Twig
的_self
环境变量
3. 自动化检测与利用
工具 | 功能 | 示例命令 |
---|---|---|
tplmap | 自动检测和利用SSTI | python tplmap.py -u "http://example.com?name=*" |
Burp Suite Scanner | 被动扫描模板语法 | 自动检测${7*7} 等模式 |
手工检测 | 分步验证 | 测试${7*7} 、<%= 7*7 %> 等 |
4. 漏洞防御方案
(1) 引擎层防护
-
禁用危险功能(Jinja2示例):
-
env = Environment(autoescape=True, undefined=StrictUndefined)
- 沙箱模式(FreeMarker示例):
-
Configuration cfg = new Configuration(); cfg.setNewBuiltinClassResolver(TemplateClassResolver.SAFER_RESOLVER);
(2) 输入过滤
-
严格白名单(仅允许字母数字)
-
上下文转义:
-
from markupsafe import escape escape(user_input)
(3) 架构设计
-
前后端分离:避免服务端拼接模板
-
逻辑与展示分离:使用React/Vue等纯前端渲染
(4) 安全编码示例
# 安全用法 - 明确参数传递
template = """
Hello {{ safe_name }}
"""
render_template_string(template, safe_name=user_input)
5. 历史重大漏洞
CVE | 影响组件 | 利用方式 |
---|---|---|
CVE-2021-25748 | Kubernetes Dashboard | Jinja2 SSTI |
CVE-2019-3396 | Confluence | Velocity SSTI |
CVE-2016-4977 | Spring Boot | Thymeleaf SSTI |
Confluence攻击链:OGNL表达式注入
→ Runtime.getRuntime().exec()
→ RCE
6. 企业级防护策略
-
WAF规则:
-
拦截
__class__
、import
等关键词 -
检测模板语法特征(如
{{
、<%
)
-
-
运行时防护(RASP):
// Java Agent检测模板引擎调用
public void checkTemplateInjection(String template) {
if (template.contains("${") || template.contains("#{")) {
throw new SecurityException("Template injection detected");
}
}
-
云原生方案:
-
使用无服务器函数处理模板渲染
-
通过OPA策略限制模板引擎权限
-
7. 开发最佳实践
避免直接拼接:
// 错误示范(EJS)
ejs.render("Hello " + userInput);
// 正确做法
ejs.render("Hello <%= name %>", {name: userInput});
定期组件升级:
<!-- Maven依赖安全版本 -->
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.32</version> <!-- 修复SSTI的版本 -->
</dependency>
安全审计重点:
-
-
查找
render_template_string
、eval
等高危函数 -
检查模板文件是否允许动态加载
-
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END
暂无评论内容