[HFCTF 2021 Final]easyflask
[HFCTF 2021 Final]easyflask
考点
Flask代码审计
pickle反序列化
wp
提示/file?file=index.js访问继续提示Source at /app/source,访问/file?file=/app/source得到源码
#!/usr/bin/python3.6
import os
import pickle
from base64 import b64decode
from 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)首先使用type()生成新的类型对象User,有2个属性uname和is_admin,1个方法__repr__()把对象当做字符串使用时调用。python中type()有2个用法,只有第一个参数则返回对象的类型,三个参数则会新建一个类。
后面的操作都和session有关,看一下session内容
进行反序列化后是一个User对象
接着看源码
访问/会生成根据User类生成session,访问/file?file=会读取相应文件
访问/file?file=/proc/self/environ,得到secret_key=glzjin22948575858jfjfjufirijidjitg3uiiuuh
之后可以伪造session了
访问/admin会对session进行反序列化,结合前面的可以控制session,反序列化RCE
exp
再重新加密

最后更新于