SSTI 服务端模板注入漏洞
概述
服务端模板注入(Server-Side Template Injection,简称 SSTI)是一种严重的 Web 应用漏洞,攻击者通过向模板引擎注入恶意代码,能够实现代码执行、文件读取等高危操作。SSTI 漏洞通常出现在 Web 应用程序使用模板引擎(如 Twig、Smarty、Jinja2 等)动态生成页面时,开发者未对用户输入进行严格过滤或转义,导致用户输入被直接拼接进模板,从而引发安全问题。
产生原因
SSTI 漏洞的根本原因在于开发者在处理用户输入时缺乏严格的验证与转义机制,导致参数被拼接到了模板中,具体包括以下几个方面:
- 未对用户输入进行过滤:用户输入的参数直接被拼接进模板引擎的渲染流程,未经过适当的转义或验证。
- 模板引擎配置不当:某些模板引擎允许执行动态代码,若未正确配置安全选项(如禁用危险函数或沙箱模式),可能导致漏洞。
- 动态模板拼接:开发者将用户输入直接嵌入模板字符串,导致攻击者可构造恶意模板代码。
- 第三方库依赖问题:使用未更新的模板引擎版本,存在已知漏洞可能被利用。
常见场景包括:
- 用户输入用于动态生成页面内容的参数(如用户名、搜索查询)。
- 动态路由或 URL 参数被直接传递到模板引擎。
- 配置文件或 CMS 系统允许用户自定义模板内容。
危害
SSTI 漏洞可能导致以下危害:
- 任意文件读取:攻击者可通过模板引擎访问服务器文件系统,读取敏感文件(如配置文件、源代码)。
- 远程代码执行(RCE):攻击者可注入恶意代码,直接在服务器上执行任意命令,控制服务器。
- ······
挖掘与利用
一般情况下,存在 SSTI 漏洞的参数同时存在反射型 XSS。
通用测试方法
- 基础测试:向可能存在漏洞的参数输入简单的模板表达式,如
{{7*7}}
或${7*7}
,观察页面是否返回计算结果(如49
)。若表达式被解析,则可能存在 SSTI 漏洞。 - 探针构造:尝试使用模板引擎特定的语法(如 Twig 的
{{}}
或 Jinja2 的{% %}
),观察服务器响应。 - 错误信息分析:故意输入错误模板代码,观察是否返回模板引擎相关的错误信息(如 Twig 或 Smarty 的调试信息),从而确认模板引擎类型。
PHP 模板引擎——Twig
测试方法
Twig 是 PHP 常用的模板引擎,语法使用 {{}}
表示变量或表达式,{# #}
表示注释。测试是否存在 Twig 的 SSTI 漏洞,可以输入以下代码:
bmjoker{# comment #}{{2*8}}0K
判断依据:
- 若
{# comment #}
消失(被识别为注释),说明目标使用 Twig 模板。 - 若
{{2*8}}
被解析为16
,进一步确认存在 SSTI 漏洞。
- 若
利用 EXP
Twig 允许通过特定方法调用系统命令,常见的利用方式包括:
{{_self.env.registerUndefinedFilterCallback("exec")}}{{_self.env.getFilter("id")}}
- 原理:通过
registerUndefinedFilterCallback
注册一个回调函数(如exec
),再通过getFilter
执行系统命令(如id
)。 - 效果:成功执行后,可返回服务器用户 ID 等信息,确认 RCE 能力。
高级利用
文件读取:利用 Twig 的
file_get_contents
或类似函数读取敏感文件:{{_self.env.registerUndefinedFilterCallback("file_get_contents")}}{{_self.env.getFilter("/etc/passwd")}}
代码执行:结合 PHP 的
eval
或system
函数执行任意命令。沙箱绕过:若 Twig 启用了沙箱模式,需研究特定版本的绕过方法(如利用未过滤的内置对象)。
截图实例:
PHP 模板引擎——Smarty
测试方法
Smarty 是另一款流行的 PHP 模板引擎,使用 {}
语法。测试方法包括输入以下代码:
{literal}{{7*7}}{/literal}
判断依据:
- 若
{literal}
被正确解析(不显示在页面上),且{7*7}
输出49
,说明使用 Smarty 模板。 - 若页面返回 Smarty 错误信息(如
undefined variable
),可进一步确认。
- 若
利用 EXP
Smarty 的 SSTI 利用通常涉及调用内置函数或 Smarty 的内部对象。例如:
{system("id")}
- 效果:可以执行系统命令。
截图示例:
Python 模板引擎——Jinja2
测试方法
Jinja2 是 Python 常用的模板引擎,语法与 Twig 类似,使用 {{}}
和 {% %}
。测试代码如下:
{{7*7}}
{% if 1 == 1 %}Jinja2{% endif %}
判断依据:
- 若
{{7*7}}
输出49
,说明 Jinja2 解析了表达式。 - 若
{% if 1 == 1 %}
被执行,输出Jinja2
,确认使用 Jinja2 模板。
- 若
利用 EXP
Jinja2 的 SSTI 利用通常涉及 Python 的内置对象或类。常见 EXP 如下:
{{ ''.__class__.__mro__[1].__subclasses__() }}
- 原理:通过访问 Python 的对象继承链(
__mro__
)获取所有可用类,寻找可用于 RCE 的类(如subprocess.Popen
)。 - 效果:列出 Python 环境中的类,可能用于进一步构造恶意代码。
截图示例:
工具
-
功能:自动化检测与利用 SSTI 漏洞,支持多种模板引擎(如 Twig、Smarty、Jinja2)。
使用场景:快速扫描目标,识别模板引擎类型并生成利用 Payload。
使用方法:
python sstimap.py -u http://URL/?key=value
优势:支持多种 Payload,自动化程度高。
-
- 功能:专门针对 SSTI 漏洞的自动化利用工具,支持 WAF 绕过。
- 使用场景:复杂环境中绕过 WAF 或过滤规则,生成隐蔽 Payload。
- 优势:内置多种绕过策略,适合高级利用场景。
截图示例: