任意文件读取
抽老婆
打开首先发现是一个图片下载(老婆们都很不错( ̄▽ ̄)*),感觉也没什么其他的东西,先F12看一下代码,发现有一处标注,感觉跟任意文件下载有关:
(一开始的错误思路:)
想着先扫一遍看看能不能发现啥,于是用dirsearch扫了一下,
发现了/console,访问显示需要PIN,
也没有什么提示不知道能不能爆破出来,先抓个包看看,发现返回的响应包中有,改一下值,改为true,
发现验证就通过了:
但是我不会了。。。。后来看了一下wp,发现这个思路是错的,还是应该从文件读取入手。
(正确思路:)
于是先试一试读取flag:
被过滤了🤪,不过不要气馁,多试试,再尝试随便读一个111.jpg:
发现没有过滤了,出现了报错:
里面暴露了一些路径,猜测app.py是网站源文件,下载下来先看看(但是这个路径,我不太了解为什么就是返回两层,是开发经验吗):
# !/usr/bin/env python
# -*-coding:utf-8 -*-"""
# File : app.py
# Time :2022/11/07 09:16
# Author :g4_simon
# version :python 3.9.7
# Description:抽老婆,哇偶~
"""from flask import *
import os
import random
from flag import flag#初始化全局变量
app = Flask(__name__)
app.config['SECRET_KEY'] = 'tanji_is_A_boy_Yooooooooooooooooooooo!'@app.route('/', methods=['GET'])
def index(): return render_template('index.html')@app.route('/getwifi', methods=['GET'])
def getwifi():session['isadmin']=Falsewifi=random.choice(os.listdir('static/img'))session['current_wifi']=wifireturn render_template('getwifi.html',wifi=wifi)@app.route('/download', methods=['GET'])
def source(): filename=request.args.get('file')if 'flag' in filename:return jsonify({"msg":"你想干什么?"})else:return send_file('static/img/'+filename,as_attachment=True)@app.route('/secret_path_U_never_know',methods=['GET'])
def getflag():if session['isadmin']:return jsonify({"msg":flag})else:return jsonify({"msg":"你怎么知道这个路径的?不过还好我有身份验证"})if __name__ == '__main__':app.run(host='0.0.0.0',port=80,debug=True)
有个/secret_path_U_never_know路径,但是从代码里可以看出还需要绕过身份验证:
flask中的session伪造
看代码只需要让session中的isadmin为真就可,这个用的应该是JWT方式认证,里面签名要用到SECRET_KEY;于是我们将isadmin的值更改后,使用密钥SECRET_KEY重新加密生成一个session。有一个开源脚本可以帮我们自动生成:github—flask-session-cookie-manager下载链接
下载之后,使用脚本进行重新加密:
生成以后我们在burp拦截的请求包中用此session替换之前的session,发现flag出现:
总结:
了解到了flask框架,以及flask框架中会使用的登录认证:
现在流行两种方式登录认证方式:Session和JWT,无论是哪种方式其原理都是保存凭证:session,JWT,token的区别
- 前端发起登录认证请求
- 后端登录验证通过,返回给前端一个凭证
- 前端发起新的请求时携带凭证
只不过session的重点是会在服务端存储凭证;而JWT不会在服务端存储凭证,而是会将返回的凭证根据签名和加密方式来校验其是否被篡改。
JWT的格式及加密形式(JWT的介绍及使用);