抽老婆
依旧是CTF.show
这次是菜狗杯的一道题——抽老婆
看这名字有点意思,就点开了看看,没想到考点还不少。
开启靶场。
只有开抽和抽老婆两个可点,功能一致。
随便右击一张老婆,查看源代码;在新标签页打开图片,F12,查看网络
直接说我的结论吧。这个抽老婆的功能的业务逻辑是——Get请求 /getwifi 这个页面,它就随机的在 /static/img 中选一张图片返回给用户,并给用户提供了一个接口下载(熟不知就是这个接口害了自己),这个接口的访问路劲是 /download?file=XXX 。
我们直接访问/download 这个路径,有意思的事情发生了。
如果是熟悉开发的同学的话,应该一眼就看出这个界面是什么了——python中flask框架的Debug。
从这个页面中我们知道两个信息,一是 /app/app.py 这个后端启动文件路径(不清楚的可以自学一下Flask),二是 file 不能传 flag,被过滤了。
既然不能把 flag 下载下来,但我们可以把 app.py 下载下来啊,路径知道,又没有敏感字段。
访问
/download?file=../../../app/app.py
为什么是这样的,自行审计代码。
总之,我们成功将app.py文件下载下来了。查看它的内容,其业务逻辑跟我们分析的差不多。
我将比较重要的路由放在下面
app.config['SECRET_KEY'] = 'tanji_is_A_boy_Yooooooooooooooooooooo!'
@app.route('/getwifi', methods=['GET'])
def getwifi():
session['isadmin']=True
wifi=random.choice(os.listdir('static/img'))
session['current_wifi']=wifi
return render_template('getwifi.html',wifi=wifi)
@app.route('/secret_path_U_never_know',methods=['GET'])
def getflag():
if session['isadmin']:
return jsonify({"msg":flag})
else:
return jsonify({"msg":"你怎么知道这个路径的?不过还好我有身份验证"})
我们要的东西就在 /secretXXXX 里面,不过这里有个认证,要求 isadmin = True。这里就涉及到另一个考点了,Flask框架的Session伪造。
Session伪造需要知道SECRET_KEY,这个在 app.py 文件中就有。
打开BurpSuite,抓包,查看Cookie
找解密工具了,这里使用Github上的开源项目——GitHub - noraj/flask-session-cookie-manager: :cookie: Flask Session Cookie Decoder/Encoder
按照教程,解密结果为
从解密结果中,我们仿造一个Session,值为
{'isadmin':True}
加密结果如下
回到Burpsuite中,将加密结果复制替换Session,重新发包。
查看响应包
结束。
总结,这道题涉及了代码审计和Flask的Session伪造,不算太难。
从这道题中也可以学习到一些开发的知识,比如上线的应用就不要开Debug了。
if __name__ == '__main__':
app.run(host='0.0.0.0',port=80,debug=True)#这里改成 False