|
模板注入(SSTI)——服务端模板的噩梦 摘要:服务端模板注入(Server-Side Template Injection, SSTI)是一种让黑客向模板引擎注入恶意语法,从而在服务器端执行任意代码的渗透手段。当Web应用将用户输入直接拼接到模板(如Jinja2、Twig、Freemarker)中时,攻击者可利用模板引擎的内置函数、对象属性链执行系统命令、读取文件。本文详细讲解SSTI的检测手法、常见攻击载荷(仅用于教育),并提供沙箱环境、禁用危险类等防御措施。 关键词:黑客网站攻击;SSTI;模板注入;渗透测试;代码执行;模板引擎安全;Jinja2 一、引言现代Web开发广泛使用模板引擎(如Python的Jinja2、PHP的Twig、Java的Freemarker)来动态生成HTML。然而,如果开发者错误地将用户输入作为模板代码的一部分进行渲染,黑客便可注入模板语法,突破模板沙箱,直接执行操作系统命令。SSTI漏洞一旦被利用,危害与RCE相当,常出现在邮件模板、页面配置、主题编辑等功能中。 二、SSTI攻击原理2.1 漏洞起因典型危险代码(Python Flask + Jinja2): [size=12.573px]python
from flask import Flask, request, render_template_stringapp = Flask(__name__)@app.route('/page')def page(): name = request.args.get('name') template = f"<h1>Hello, {name}</h1>" return render_template_string(template)
正常请求:/page?name=Alice → 输出 <h1>Hello, Alice</h1>
恶意请求:/page?name={{7*7}} → 若返回 49,证明模板引擎执行了表达式。 2.2 攻击链条(Jinja2示例)一旦确认存在SSTI,黑客可深入利用: 获取配置:{{ config }} 可能泄露SECRET_KEY。 执行命令:利用 __class__、__mro__、__subclasses__ 找到 os._wrap_close 或 subprocess.Popen 调用系统命令。 [size=12.573px]jinja2
{{ ''.__class__.__mro__[1].__subclasses__() }}
找到 os.system 或 popen 后注入 {{ ..popen('id').read() }}。
2.3 其他引擎的载荷特征三、渗透测试中的SSTI检测黑客在进行网站渗透时,会先探测所有注入点(URL参数、POST body、Header),依次尝试: {{7*7}} → 49 ${7*7} → 49 {{7*'7'}} → 7777777 #{7*7} → 49(针对某些模板)
若响应包含计算结果,则可判定SSTI存在。随后使用自动化工具(如Tplmap)生成提权载荷。 四、防御SSTI4.1 永不将用户输入作为模板代码使用模板引擎的“渲染数据”功能(即数据上下文),而非字符串拼接。 正确做法:render_template_string("<h1>Hello, {{ name }}</h1>", name=request.args.get('name'))。
4.2 使用沙箱环境4.3 禁用危险属性和函数4.4 框架默认配置五、检测措施六、总结SSTI漏洞的危害等同于远程代码执行。防御关键在于明确区分模板代码与数据:永远不要把用户输入当作模板源码。同时使用沙箱和禁用危险类,可有效阻止黑客的渗透尝试。
|