全名 Server Side Request Forgery,是指利用伺服器端的漏洞,讓請求可以透過伺服器而發到其他機器或是所在內網中的其他機器上。因為內網的防範措施往往沒有那麼嚴謹,甚至沒有驗證權限,就可能出現能被利用的漏洞。
假設我們有一個頁面,只要使用者給一個圖片 URL,我們的伺服器就會發起請求去將該圖片儲存起來並顯示在頁面上,程式碼如下:
def show_image():
url = request.form['url']
response = requests.get(url)
filename = f'./images/{hash(url)}.jpg'
with open(filename, 'wb') as file:
file.write(response.content)
return f'<img src="{filename}"/>'
如果攻擊者提供的 URL 是內網的資源的話,就可能可以利用未經授權的請求來存取這些資源。
除了這個簡單的例子以外,還有一些例子可以通過其他協議來進行攻擊,例如 dict
、gopher
、file
等等協議。也有可能被利用來對內網進行掃描或者試探,更嚴重一點也有被 RCE 的可能。
另外需要注意的是,即便有針對輸入做驗證,如果不夠周詳的話,也有可能被以各種奇形怪狀的 payload 來繞過檢查。比如有個參數是 IP,邏輯中只以 regex 來驗證 10 進制的 IP 格式,就有可能被以改寫為 8 進制的 IP 位址來繞過驗證機制。詳情可以參考 CTF Wiki 的 SSRF 條目。
OWASP 提供了我們一些防範方案,可以分為從網路層或應用層來擋:
Ref: https://owasp.org/Top10/zh_TW/A10_2021-Server-Side_Request_Forgery_%28SSRF%29/
再者,我想最近幾年流行的 Zero Trust 對於防範 SSRF 應該也有很大的幫助才對。
起初在讀一些例子的時候,直覺上會覺得好像也不至於有什麼大問題,但越看就越發現自己的天真 XD,只能說資安真的是不可輕忽的一環,沒有觀念的話真的會寫出危險的程式碼。
我目前對於 SSRF 真的還不太熟,如果有講錯的地方請務必讓我知道 🫡