SSTI模板注入利用链全解析:从{{7*7}}到命令执行

发布时间:2026/10/13 3:54:25
SSTI模板注入利用链全解析:从{{7*7}}到命令执行
第一次在某个CTF练习平台上看到这道题我其实是有点懵的。页面就一个孤零零的输入框我传什么它回显什么看起来完全就是一个随手写的前端Demo。直到我抱着试试看的心态往输入框里敲了一句{{7*7}}页面居然回显了49。那一瞬间我意识到这不是普通回显而是服务端模板注入Server-Side Template InjectionSSTI。这篇文章我会把整个链路从头到尾讲清楚不预设你了解Jinja2语法也不预设你熟悉Python对象模型全程胎教级拆解。它适合刚接触Web安全、想搞懂模板注入到底怎么回事的人你也完全可以把它当成一份能照着操作的题解打开题目后跟我一步步走过从探测、利用链构造到命令执行的完整过程。1. 这道题到底考什么SSTI不看回显看“执行”1.1 模板渲染的正常流程与异常用法先解释一下“模板”是什么。Web框架把动态页面拆成两部分一个是写死的 HTML 骨架一个是需要动态填充的数据。比如hello.html里写h1Hello, {{ name }}/h1后端控制器可能这样渲染render_template(hello.html, namerequest.args.get(name))模板引擎负责读取磁盘上的hello.html把里面的{{ name }}替换成用户传入的值。这个过程里用户传入的name只是“数据”模板引擎把它当成纯字符串处理不会去执行里面的任何代码。这是安全的。危险的情况出现在第二种写法render_template_string(h1Hello, request.args.get(name) /h1)这里用户输入不是被当作变量值而是直接被拼进模板源码。此时再传{{7*7}}模板引擎会认为用户输入里就包含模板语法于是先解析、求值再把结果49输出到页面上。这就是SSTI的根因用户输入进入了“代码”的位置而不是“数据”的位置。CTF题里出现SSTI特别常见因为题目为了降低难度经常会用后端render_template_string直接拼接收的参数。等后端处理完再回来翻前端页面时回显本身没有太大价值有价值的是服务端是否执行了模板表达式。1.2 为什么探测要用 {{7*7}} 而不是