在完全信任的環境中,列表中的第一個 IP 地址是原始客戶端的源 IP 地址。代理添加的第一個 IP 地址是您要選擇的 IP 地址。但是,軟件開發的世界并不是一個完全信任的環境。您只能信任您能控制的東西。

代理服務器默認不會清除此標頭,它們只會向其附加內容。攻擊者可以生成包含此標頭值的請求,如果您不小心,您的應用程序就會使用這些錯誤值。

用途X-Forwarded-For

我們可以通過多種方式利用X-Forwarded-For產品或監控體驗中的值。這樣做時,擁有準確的值非常重要。

如果我們想要依靠 IP 地址來實現上述任何功能,我們必須驗證 IP 地址的選擇方式,以確保我們獲得準確的值。對于上述任何功能,允許使用偽造或惡意的 IP 地址都會破壞該功能的價值主張。

X-Forwarded-For在云提供商中

云提供商遵循標頭的規范X-Forwarded-For,許多云提供商默認采用附加模式。亞馬遜網絡服務 (AWS)和Google Cloud Platform (GCP)會默認將 IP 地址添加到列表中,而不會對該列表中的現有 IP 地址進行任何驗證或驗證。需要強調的是,任何現有 IP 地址X-Forwarded-For都保留在列表的最前面。

您還可以自己運行代理,例如 NGINX,它也允許您配置如何X-Forwarded-For處理。雖然 NGINX 的配置性很高,但它們合理的默認函數的行為類似于 AWS,它將客戶端的遠程地址附加到標頭值列表中。

重要的是要強調 AWS 和 GCP 在處理這些標頭方面的區別。這說明每種情況都是獨一無二的,您的情況將取決于處理請求的云提供商、代理服務器和應用程序框架。

AWS 嚴格將調用客戶端的單個 IP 地址附加到X-Forwarded-For標頭。GCP 將附加兩個 IP 地址,即調用客戶端的 IP 地址,后跟請求通過的負載均衡器的 IP 地址。

AWS:'X-Forwarded-For: <whatever-was-on-the-request-before>, <aws-detected-client-ip>'

地源控制點(GCP): 'X-Forwarded-For: <whatever-was-on-the-request-before>, <gcp-detected-client-ip>, <gcp-load-balancer-ip>'

我們已經可以看到主要云提供商之間的分歧,以及為什么解析此標頭以獲取準確值會很困難。在這兩種情況下,<whatever-was-on-the-request-before>可能什么都沒有,可能是來自其他網絡代理的值,也可能是惡意或欺騙的值。唯一的共同點是兩者都將 IP 地址附加到原始標頭值。

如果您是具有可公開訪問的 API 層的服務提供商,則請求會來自您無法控制的層。無論這是您的 UI 還是直接 API 訪問,您都無法默認信任該請求。不受信任的客戶端可以將他們喜歡的任何 IP 放入X-Forwarded-For標頭中,這會用欺騙或惡意數據污染值。此標頭中的值范圍從左側最不受信任的值到右側最受信任的值。我們只能信任我們能夠控制的內容

X-Forwarded-For解析示例

許多流行的應用程序框架都提供自動解析此標頭的功能,但您的解決方案最終將取決于您的特定環境。解析此標頭的一種簡單方法是簡單地獲取列表中的第一個。在完全受信任的世界中,這是原始客戶端的 IP 地址。實際上不要在生產中這樣做,這是不安全的。

Spring Boot

Spring Boot 是一個流行的基于 Java 的應用程序框架,具有許多功能。這些功能之一就是自動處理標X-Forwarded-For頭。

Spring Boot 天真地抓取 X-Forwarded-For 標頭列表中的第一個值,沒有進行任何驗證,也無法自定義選擇哪個值。

鑒于我們對 的了解X-Forwarded-Header,如果請求中存在欺騙性的 IP 地址,Spring Boot 將始終選擇該 IP 地址。默認配置容易使用欺騙性的客戶端 IP 地址。

Tomcat

Tomcat 是一種流行的基于 Java 的 Web 服務器,能夠處理將 Java 應用程序作為 Web 服務運行的低級問題。

Tomcat 有一種更好的解析方法X-Forwarded-For,它以相反的順序遍歷 IP 地址列表,尋找第一個受信任的 IP 地址,同時提供跳過內部代理 IP 地址的機制。

我們要跳過的內部代理 IP 地址的一個示例就是<gcp-load-balancer-ip>上面的那個。

Tomcat 會選擇更準確的 IP 地址,并且可以配置為選擇第一個受信任的 IP 地址,無論它是在列表的末尾還是在中間的某個地方。

如果我們的應用程序前面有多個代理,那么 Tomcat 可以自動過濾掉內部代理 IP,從而選擇正確的客戶端 IP 地址,而 Spring Boot 則顯得太過天真。

配置您的框架

我們現在知道 Spring Boot 將選擇最不可信的客戶端 IP 地址,但 Tomcat 僅在您向其描述內部代理時才會選擇正確的客戶端 IP 地址。否則,它只會提取列表末尾的 IP 地址。根據網絡堆棧的最終形狀和代理服務器的行為,這可能是一個內部 IP 地址。

如果您已經驗證了您的配置有一分鐘X-Forwarded-For,或者您只是接受了框架的默認實現,那么現在是驗證如何使用此標題的最佳時機。

經驗教訓

當底層框架或平臺提供功能時,人們通常會毫不猶豫地使用其實現細節。

這些框架的性質是它們可能是不久前編寫的。它們不可能解釋所有使用方式。

這是一個很好的例子,說明我們的框架的默認實現如何讓我們面臨這種速率限制器繞過漏洞。

我們如何解決它

如上所述,此標頭中的第一個值僅在完全受信任的環境中才是準確的,因此我們的框架的默認實現是不安全的,因為它不考慮該標頭中不受信任的值。

這促使我們限制速率限制邏輯,優先使用用戶 ID 而不是 IP 地址,這樣 IP 地址僅用于未經身份驗證的 API 調用。我們的未經身份驗證的 API 調用非常少。更重要的是,我們發現我們的應用程序框架盲目地選擇了第一個 IP 地址作為X-Forwarded-For真實來源。

我們修改了此邏輯,使其更加智能地選擇這些 IP 地址,并且與 Tomcat 方法類似,我們現在從末尾抓取第一個有效 IP 地址。我們有意提取我們知道來自我們控制的可信來源的值。

這是輸入驗證的另一個典型示例。當它處于像這樣的低級網絡層時,它很可能在很大程度上被忽視。

你安全嗎?

您是否明確驗證了您自己的應用程序如何處理X-Forwarded-For? 

更重要的是,您必須通過像攻擊者一樣解決問題來驗證它。檢查依賴于此客戶端 IP 的功能。速率限制器、審計日志或地理使用情況統計信息,并嘗試發送欺騙X-Forwarded-For地址。

文章來源:Do You Trust Your X-Forwarded-For Header?

上一篇:

Kotlin 損壞 認證指南: 示例和預防

下一篇:

Web 應用程序安全檢查表:10 項改進
#你可能也喜歡這些API文章!

我們有何不同?

API服務商零注冊

多API并行試用

數據驅動選型,提升決策效率

查看全部API→
??

熱門場景實測,選對API

#AI文本生成大模型API

對比大模型API的內容創意新穎性、情感共鳴力、商業轉化潛力

25個渠道
一鍵對比試用API 限時免費

#AI深度推理大模型API

對比大模型API的邏輯推理準確性、分析深度、可視化建議合理性

10個渠道
一鍵對比試用API 限時免費