在現(xiàn)代Web架構(gòu)中,反向代理、負(fù)載均衡器和CDN的廣泛使用,使得服務(wù)器無法直接獲取客戶端的真實(shí)IP地址,為了實(shí)現(xiàn)用戶身份識(shí)別、日志記錄、地理定位和訪問控制等功能,開發(fā)者通常使用某些HTTP請求頭獲取客戶端來源IP,其中最常用的就是X-Forwarded-For(XFF)。本文將以XFF請求偽造為例,從漏洞介紹、實(shí)際案例、修復(fù)方式出發(fā),詳細(xì)了解客戶端來源IP偽造攻擊與防護(hù)。
X-Forwarded-For(XFF)是一個(gè)HTTP頭字段,主要用于識(shí)別原始客戶端的IP地址,通常由反向代理或負(fù)載均衡服務(wù)器添加。當(dāng)應(yīng)用程序依賴X-Forwarded-For 獲取客戶端IP進(jìn)行安全控制時(shí),攻擊者可以偽造該頭,繞過安全限制,例如:
·繞過IP訪問控制:攻擊者偽造XFF頭繞過基于IP的白名單機(jī)制。
·日志污染與溯源欺騙:攻擊者偽造XFF頭,干擾日志記錄,影響取證調(diào)查。
·Web應(yīng)用防火墻 (WAF) 繞過:某些WAF依賴XFF進(jìn)行訪問控制,可能被繞過。
該漏洞的根本原因在于,服務(wù)端代碼沒有對X-Forwarded-For進(jìn)行有效校驗(yàn):
1. 直接信任XFF作為客戶端IP:許多應(yīng)用程序直接從HTTP頭中讀取X-Forwarded-For,并將其用于訪問控制或日志記錄。
2. 多層代理下錯(cuò)誤解析:
·XFF頭可能包含多個(gè)IP(如 X-Forwarded-For: 192.168.1.1, 10.0.0.1, 8.8.8.8)。
·如果服務(wù)器未正確解析,可能錯(cuò)誤地使用攻擊者提供的IP。
1. 攔截請求,添加X-Forwarded-For偽造 IP:
GET /admin HTTP/1.1
Host: target.com
X-Forwarded-For: 192.168.1.100
2. 發(fā)送請求,觀察是否成功繞過訪問限制或造成日志記錄了偽造的IP。
burpFakeIP(https://github.com/TheKingOfDuck/burpFakeIP) 插件可自動(dòng)插入X-Forwarded-For以及其他獲取客戶端IP的HTTP頭,如X-Forwarded、X-Real-IP等。
插件中除X-Forwarded-For外,還包含 X-Real-IP等頭,也是常見用于傳遞客戶端 IP 的 HTTP 請求頭:
·X-Forwarded-For:最常用的頭,格式為 客戶端IP, 代理1IP, 代理2IP。
·X-Forwarded:與X-Forwarded-For類似,但較少使用。
·X-Real-IP:通常由反向代理(如Nginx)設(shè)置,直接傳遞客戶端IP。
·Ali-Cdn-Real-Ip:阿里云CDN專用的頭,用于傳遞客戶端真實(shí)IP。
·WL-Proxy-Client-IP:WebLogic服務(wù)器使用的頭。
附錄中列舉了更詳細(xì)的說明。
這些HTTP請求頭在配置不正確的情況下,也會(huì)被偽造。下一節(jié)中將介紹相關(guān)案例。
某系統(tǒng)記錄用戶操作,例如登錄、刪除、修改系統(tǒng)配置等,可在系統(tǒng)日志功能中可查看。
經(jīng)驗(yàn)證使用Proxy-Client-Ip可偽造客戶端IP。
經(jīng)溝通得知獲取Client IP的代碼段如下:
從代碼段可以看出,服務(wù)端直接信任客戶端傳來的HTTP請求頭作為客戶端IP,導(dǎo)致偽造。
在搜索引擎搜索獲取客戶端IP的方式,大概率會(huì)得到類似代碼,如果開發(fā)不理解代碼原理,直接應(yīng)用到業(yè)務(wù)中來,則會(huì)面臨客戶端請求頭偽造的風(fēng)險(xiǎn)。
比如這段代碼中,后端獲取Proxy-Client-Ip和WL-Proxy-Client-IP,Proxy-Client-IP字段和WL-Proxy-Client-IP字段只在Apache(Weblogic Plug-In Enable)+ WebLogic搭配下出現(xiàn),而實(shí)際業(yè)務(wù)中并未使用到Apache和Weblogic,因此這段代碼并無實(shí)際作用,反而引入了漏洞。
如何防止XFF偽造,獲取用戶真實(shí)IP呢?
現(xiàn)在Web應(yīng)用部署,一般會(huì)經(jīng)過多重代理,如CDN、負(fù)載均衡、Nginx反向代理,以Nginx代理為例來看多重代理環(huán)境下如何獲取真實(shí)客戶端IP。
防御原理很簡單,nginx不使用客戶端傳來的X-Forwarded-For,在直接對外的Nginx(即直接對外提供服務(wù)的Nginx)配置,修改nginx.conf。
1. 反向代理Nginx配置X-Forwarded-For
在nginx.conf中通過proxy_set_header傳遞X-Forwarded-For:
server {
listen 80;
location / {
proxy_pass <http://backend>;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Real-IP $remote_addr;
}
}
·$remote_addr:Nginx直接接收到的IP(通常是上游代理的 IP)。$remote_addr是獲取的是直接TCP連接的客戶端IP(類似于Java中的request.getRemoteAddr())這個(gè)是無法被偽造的。該設(shè)置可直接覆蓋掉客戶端傳來的X-Forwarded-For頭。
2. 應(yīng)用服務(wù)器,以java應(yīng)用為例
public String getClientIp(HttpServletRequest request) {
String xff = request.getHeader("X-Forwarded-For");
if (xff != null && !xff.isEmpty()) {
String[] ipList = xff.split(",");
return ipList[0].trim();
}
return request.getRemoteAddr();
}
這段代碼的作用是獲取并解析請求頭X-Forwarded-For,經(jīng)過代理,X-Forwarded-For形式可能為X-Forwarded-For:clientIP, proxy1, proxy2, proxy3
需提取第一個(gè)非代理IP。
如果中間經(jīng)過多層代理,比如雙重Nginx如何配置?
1. 第一層Nginx配置X-Forwarded-For
與5.1配置相同.
server {
listen 80;
location / {
proxy_pass <http://backend>;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Real-IP $remote_addr;
}
}
2. 第二層Nginx配置X-Forwarded-For
server {
listen 80;
location / {
proxy_pass <http://backend>;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
}
}
·這里需注意$proxy_add_x_forwarded_for:自動(dòng)追加原始X-Forwarded-For頭,以保留完整的IP鏈。
·也可以不做配置,直接透傳Nginx1發(fā)送過來的請求。
3. 后端獲取真實(shí)IP
與5.1相同
閱讀原文:原文鏈接
該文章在 2025/6/6 12:12:16 編輯過