当前位置: 首页 > 教程 > Web安全 > 正文

模板注入(SSTI):从页面渲染到代码执行

admin 2026-10-27 09:21 141人看过 免费
# SSTI 服务器端模板注入(软件设计师 / 安全考点) 全称:**Server-Side Template Injection,服务器端模板注入** > 一句话核心:**服务器使用模板引擎渲染页面,把用户可控输入直接塞进模板,而非单纯传入变量,导致攻击者可以执行模板语法,最终读取文件、执行系统命令。** ## 一、正常页面渲染(安全,无SSTI) 模板文件:`hello.html` ```jinja2 <h1>Hello {{ name }}</h1> ``` 后端代码(Python Flask/Jinja2) ```python # 用户输入:name = request.args.get("name") render_template("hello.html", name=name) ``` ✅ 原理:模板文件固定写死,**用户输入只作为变量值传入**,`name`只是字符串,不会被解析为模板语法。 用户输入 `{{7*7}}`,页面只会原样输出字符串`{{7*7}}`,不会计算49。 ## 二、存在SSTI漏洞(危险写法!) 后端直接**拼接字符串生成模板**,把用户输入嵌入模板源码: ```python # 危险!直接字符串拼接 user_input = request.args.get("name") tmpl = f"<h1>Hello {user_input}</h1>" render_template_string(tmpl) ``` 此时用户传入:`{{7*7}}` 服务器把它当成模板语法解析,执行表达式,页面输出:`Hello 49` 👉 这就是SSTI触发点:**用户可控内容被当作模板代码解析** > 区分重点(考题常坑) > - `render_template(模板文件,变量)`:一般安全 > - `render_template_string(用户拼接字符串)`:极易SSTI ## 三、漏洞利用链路:表达式 → 对象查找 → 代码执行(Jinja2为例) 1. 测试判断是否存在SSTI payload:`{{7*7}}` 返回49 → 确认Jinja2 SSTI存在 2. 查找可用对象,python沙箱逃逸 ``` {{''.__class__.__mro__[2].__subclasses__()}} ``` - `''.__class__`:空字符串的类(str) - `__mro__`:继承链 - `__subclasses__()`:获取所有子类列表 找到`subprocess.Popen`类,就可以执行系统命令 3. 命令执行payload(读取文件 / 执行系统命令) ```jinja2 # 执行系统id命令 {{''.__class__.__mro__[2].__subclasses__()[xxx]('id',shell=True,stdout=-1).communicate()}} ``` ## 四、模板引擎差异(选择题考点) - Jinja2(Flask):`{{ 表达式 }}`,最常考SSTI - Twig(PHP):`{{ }}` - Smarty(PHP):`{$变量}`,老版本存在SSTI - Django模板:**默认沙箱,不支持直接执行代码**,Django原生模板很难直接RCE(重要考点!Django模板和jinja2不一样) > ⚠️高频考点:Django模板本身限制严格,单纯`{{}}`不能直接调用函数执行系统命令;Flask+Jinja2是SSTI重灾区。 ## 五、漏洞成因总结 1. 使用服务器模板引擎 2. **用户可控数据,直接拼接进模板源代码** 3. 模板引擎解析了用户传入的语法表达式 ## 六、防御手段(简答考点) 1. 严禁使用字符串拼接模板;用户输入**只作为模板变量传入** 2. 不要使用`render_template_string`接收外部输入 3. 沙箱加固,过滤危险属性`__class__`、`__subclasses__`、`__mro__` 4. 最小权限运行Web进程,即使被拿下,限制危害 5. 输入过滤、WAF拦截SSTI特征payload ## 七、一句话背诵 SSTI:**用户输入被服务器模板引擎解析执行,不是前端注入;和XSS区别:XSS在浏览器执行,SSTI在服务器执行** > XSS:前端浏览器解析JS;SSTI:服务器解析模板代码。

附件资料

附件仅对登录用户可见,请先 登录。

版权声明:倡导尊重与保护知识产权。未经许可,任何人不得复制、转载或以其他方式使用本站原创内容。