平時接觸到的 python 專案并不多,對 python 的代碼審計更是沒有接觸,偶然朋友發來了一個漏洞 Flask send_file函式導致的絕對路徑遍歷 ,感覺打開了新世界的大門,于是就以一個初學者的角度,進行復現分析一下,詳情也可以根據 Python : Flask Path Traversal Vulnerability 進行分析學習
send_file 的妙用
在以 flask 框架開發的系統中,為了直接實作用戶訪問某一個 URL 時就可以下載到檔案,我們就使用 send_file 來實作
from flask import Flask
from flask import send_file
?
app = Flask(__name__)
?
?
@app.route('/download')
def downloadFile():
path = "test.txt"
return send_file(path)
?
?
if __name__ == '__main__':
app.run()
我們看到 如此運行的效果是直接回傳了檔案的內容,瀏覽器并沒有識別成一個檔案下載下來,
要想讓瀏覽器識別成為檔案下載的話,只需要加上 as_attachment=True
from flask import Flask
from flask import send_file
?
app = Flask(__name__)
?
?
@app.route('/download')
def downloadFile():
path = "test.txt"
return send_file(path, as_attachment=True)
?
?
if __name__ == '__main__':
app.run()
當下載的檔案名是中文時
from flask import Flask
from flask import send_file
?
app = Flask(__name__)
?
?
@app.route('/download')
def downloadFile():
path = "測驗.txt"
return send_file(path, as_attachment=True)
?
?
if __name__ == '__main__':
app.run()
?
Content-Disposition:
Content-Disposition
在常規的 HTTP 應答中,Content-Disposition 回應頭指示回復的內容該以何種形式展示,是以行內的形式(即網頁或者頁面的一部分),還是以附件的形式下載并保存到本地,其可以是inline(默認值,所以可以不指定)或者是attachment,attachment表示附件,瀏覽器看到這個值一般會彈出一個保持檔案的確認框,或者像chrome直接下載,
【----幫助網安學習,以下所有學習資料免費領!加vx:yj009991,備注 “博客園” 獲取!】
① 網安學習成長路徑思維導圖
② 60+網安經典常用工具包
③ 100+SRC漏洞分析報告
④ 150+網安攻防實戰技術電子書
⑤ 最權威CISSP 認證考試指南+題庫
⑥ 超1800頁CTF實戰技巧手冊
⑦ 最新網安大廠面試題合集(含答案)
⑧ APP客戶端安全檢測指南(安卓+IOS)
漏洞分析
漏洞的觸發是在 send_file 中,我們跟進看一下
flask.helpers.send_file
繼續跟進查看
werkzeug.utils.send_file
我們在本地構造一個簡單的陳述句進行嘗試
>>> import os.path
>>> _root_path = "path/to/mySafeStaticDir"
>>> path_or_file = "/../../../../../../../etc/passwd"
>>> os.path.join(_root_path,path_or_file)
'/../../../../../../../etc/passwd'
我們發現 os.path.join 使用不受信任的輸入呼叫時不安全的,當 os.path.join 呼叫遇到絕對路徑時,它會忽略在該點之前遇到的所有引數并開始使用新的絕對路徑,當引數可控時,我們控制惡意引數輸入絕對路徑,os.path.join 會完全忽略靜態目錄,所以,當 os.path.join 來獲取來自 flask.send_file 的不受信任的輸入時,可能會目錄遍歷攻擊,
漏洞復現
我們在本地構造簡單的代碼進行測驗,獲取從外部傳入的引數 filename
from flask import Flask, request
from flask import send_file
?
app = Flask(__name__)
?
?
@app.route('/download')
def downloadFile():
filename = request.args.get('filename')
return send_file(filename, as_attachment=True)
?
if __name__ == '__main__':
app.run()
通過控制 filename 為絕對路徑,就實作了目錄穿越漏洞
總結反思
這個漏洞非常的有趣,漏洞的修復是可以使用flask.safe_join加入不受信任的路徑或用flask.send_file呼叫替換flask.send_from_directory呼叫,
這個漏洞雖然很簡單,但是在 github 上很多用 python 開發的專案都用了這個函式,如果不加以修復,會造成很大的危害,
更多靶場實驗練習、網安學習資料,請點擊這里>>搜索
復制
合天智匯:合天網路靶場、網安實戰虛擬環境轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/499642.html
標籤:其他
