模板注入漏洞深度剖析:从字符串拼接代码执行

模板注入漏洞深度剖析:从字符串拼接代码执行

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加载恶意类

  • PHPTwig_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. 企业级防护策略

  1. WAF规则

    • 拦截__class__import等关键词

    • 检测模板语法特征(如{{<%

  2. 运行时防护(RASP)

// Java Agent检测模板引擎调用
public void checkTemplateInjection(String template) {
    if (template.contains("${") || template.contains("#{")) {
        throw new SecurityException("Template injection detected");
    }
}
  1. 云原生方案

    • 使用无服务器函数处理模板渲染

    • 通过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_stringeval等高危函数

    • 检查模板文件是否允许动态加载

© 版权声明
THE END
喜欢就支持一下吧
点赞8 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容