本帖最後由 IT_man 於 2015-7-3 10:47 編輯
: n1 Q: n+ S: O! r7 w) D2 M: J) G4 u/ E- z) z" f
很多網站都會有偵測使用者 IP 的功能,不管是判斷使用者來自哪邊,或者是記錄使用者的位置。但是你知道嗎?網路上大多數的教學全部都是「錯誤」的。正確的程式寫法可以確保知道訪客的 IP,但是錯誤的寫法卻可能讓網站管理者永遠不知道犯罪者的來源。
/ I3 K" s( `+ h( L
9 A# m/ B3 \' s3 x. I! e U這次我們單就偵測 IP 的議題來探討各種錯誤的寫法。; K3 m7 D4 l2 ] a# h
- l, k3 V ]& ~9 Z7 ]4 a$ G
' o! N1 x! g& Y& @你知道網路上的教學是不安全的嗎?' i4 a Y4 E) x V! E
我們先來看一下網路上的教學,讓我們 Google 找一下「PHP 取得 IP」,就可以看到許多人熱心的教學,我們隨意挑一個常見的教學來看看。
/ f o6 I1 _7 @% j; U2 \以 PHP 為例:
: T5 C! }5 u- R2 F+ l* R& a, r- <?php
8 a; L: r, _- @' D! u4 a - if(!empty($_SERVER['HTTP_CLIENT_IP'])){
+ G- n8 w, H' m1 P - $myip = $_SERVER['HTTP_CLIENT_IP'];
/ t/ {" T2 r4 G2 P - }else if(!empty($_SERVER['HTTP_X_FORWARDED_FOR'])){! ^+ [/ z |! [7 X/ {/ j4 d
- $myip = $_SERVER['HTTP_X_FORWARDED_FOR'];6 j( Q5 i; ~! ?4 p( w2 A
- }else{$ u+ W9 l9 v. W% E
- $myip= $_SERVER['REMOTE_ADDR'];) H" M) z1 {8 }
- }
% \* [6 `( P0 F% ]1 `6 A5 N - echo $myip;! T+ C2 D+ l4 g9 i3 K
- ?>
複製代碼
) p& o5 C% b! I7 n h- a3 E7 A' U! l# o; c+ V$ l2 Q
這是一個很基本的寫法、很正確的想法,如果 HTTP Header 中包含「Client-IP」,就先以他當作真實 IP。若包含「X-Forwarded-For」,則取他當作真實 IP。若兩者都沒有,則取「REMOTE_ADDR」變數作為真實 IP。因為當使用者連線時透過代理伺服器時,REMOTE_ADDR 會顯示為代理伺服器 Proxy 的 IP。部分代理伺服器會將使用者的原始真實 IP 放在 Client-IP 或 X-Forwarded-For header 中傳遞,如果在變數中呼叫則可以取得真實 IP。5 f+ o2 T% l- T$ p
但是你知道嗎?網路上 80% 的教學寫法全部都是「錯誤」的。
" [! V+ ]0 D) I9 X9 D/ s( k8 m9 m# f) ] J: l8 \5 ^" D( U/ K7 N
為什麼這樣說呢?請大家記得一件事情:「任何從客戶端取得的資料都是不可信任的!」7 I, l: B1 q/ z
7 p( x$ e- X* M2 V9 F1 R/ U; G
竄改 HTTP Header「X-Forwarded-For」這個變數雖然「有機會」取得使用者的真實 IP,但是由於這個值是從客戶端傳送過來的,所以「有可能」被使用者竄改。0 E. b0 A$ y4 q* Q
舉例來說,我寫了一個小程式,偵測這些常見的 HTTP Header 判斷 IP。並且使用 Burp Suite 這個工具來修改 HTTP Request。
9 u) z+ L) V) W6 I
( | D7 b' v* Z: p0 W
W3 b! R7 q* w0 }2 ]3 U/ G頁面上顯示目前我目前的 IP「49.50.68.17」,並且其他的 header 是空的。但如果我今天使用 Burp Suite 之類的 Proxy 工具自行竄改封包,加上 X-Forwarded-For 或是 Client-IP header:
w9 p# r5 U+ \3 D- Y# j- C
/ m. i+ N+ N& w( K修改完畢之後,再到原本的顯示 IP 介面,會發現網頁錯將我竄改的 header 當作正確的資料填入。& k7 g8 Q7 i8 k) k( b) f5 i; Z% Q
! c+ j- Z. ]: q+ g1 b' ` I
* q! A* u+ ]! v7 p8 q' J4 @4 Z使用代理伺服器 Proxy 的情況使用代理伺服器的情況下,HTTP Header 會有不同的行為。例如 Elite Proxy 如何隱藏客戶端的真實 IP。以下簡單介紹幾種常見的狀況給各位參考。/ C- Q0 a9 ~: v* p
直接連線 (沒有使用 Proxy)" ], Z9 Q8 d% I7 U3 i3 a
( ?8 Z. k7 T8 e: z# K) O$ ^4 i* q - REMOTE_ADDR: 客戶端真實 IP
- HTTP_VIA: 無
- HTTP_X_FORWARDED_FOR: 無
; C8 W% p! t& [' c Transparent Proxy5 i e; b C7 W$ N
+ I3 B+ G, t& h - REMOTE_ADDR: 最後一個代理伺服器 IP
- HTTP_VIA: 代理伺服器 IP
- HTTP_X_FORWARDED_FOR: 客戶端真實 IP,後以逗點串接多個經過的代理伺服器 IP
k8 ~. p7 M3 `# y P4 ^( w. a Anonymous Proxy
) {/ V1 F; Z/ h2 [6 Q% d1 m; X$ f
1 H4 j% R6 k0 F2 S* L$ Y0 [- v - REMOTE_ADDR: 最後一個代理伺服器 IP
- HTTP_VIA: 代理伺服器 IP
- HTTP_X_FORWARDED_FOR: 代理伺服器 IP,後以逗點串接多個經過的代理伺服器 IP
3 s$ m$ \7 [& |4 m# G High Anonymity Proxy (Elite Proxy)$ k# v4 W0 E$ I% L$ X
2 M7 v1 T0 P9 G* A4 `. ?
- REMOTE_ADDR: 代理伺服器 IP
- HTTP_VIA: 無
- HTTP_X_FORWARDED_FOR: 無 (或以逗點串接多個經過的代理伺服器 IP)
9 [" q+ H H. r0 S 實際情況在我們測試的過程中,通常我們都會讓瀏覽器自帶 X-Forwarded-For,並且自行填入 IP。常常會發現有一些網站出現如下的警告…
" H. T5 d! S( c/ H# G
% h+ O, s- V: P4 ~5 [: Y0 D有沒有搞錯?「上次登入位置 127.0.0.1」?沒錯,這個是知名論壇套件「Discuz!」的功能,抓取 IP 的功能也是不安全的寫法。也有這樣的經驗,之前開著 X-Forwarded-For 的 header 到一些網站,竟然直接出現管理者後台!$ y' I9 S/ u. U) w" h1 A
你覺得只有一般人撰寫的程式會有這樣的問題嗎?其實大型網站也可能會有類似的問題:
( ]: A6 s _& e" i: q# Z% V
9 R. ]% q! d6 f4 R先不論為什麼 127.0.0.1 會在美國,這樣的寫法可能會讓管理者永遠抓不到犯罪者的真實 IP,甚至攻擊者可以竄改 header 插入特殊字元,對網站進行 SQL Injection 或者 Cross-Site Scripting 攻擊。& ^+ U" a7 X/ }1 ?* ]& ^" T
7 h( R, A) O, z
正確又安全的方式「任何從客戶端取得的資料都是不可信任的!」
* D3 O6 E8 ]3 b+ Q請各位開發者、管理者記住這個大原則,雖然這些 Request Header 可能含有真實 IP 的資訊,但是因為他的安全性不高,因此我們絕對不能完全信賴這個數值。# P3 C6 z' c8 j
那我們該怎麼處理呢?我的建議是記錄所有相關的 header 欄位存入資料庫,包含「REMOTE_ADDR」「X-Forwarded-For」等等,真正有犯罪事件發生時,就可以調出所有完整的 IP 資訊進行人工判斷,找出真正的 IP。當然從 header 存入的數值也可能會遭到攻擊者竄改插入特殊字元嘗試 SQL Injection,因此存入值必須先經過過濾,或者使用 Prepared Statement 進行存放。9 N1 e& @, n6 b( ~6 I
可以參考的 HTTP Header(依照可能存放真實 IP 的順序)* HTTP_CLIENT_IP* HTTP_X_FORWARDED_FOR* HTTP_X_FORWARDED* HTTP_X_CLUSTER_CLIENT_IP* HTTP_FORWARDED_FOR* HTTP_FORWARDED* REMOTE_ADDR (真實 IP 或是 Proxy IP)* HTTP_VIA (參考經過的 Proxy)
6 G5 J) v0 O' j9 H" v P「駭客思維」就是找出網站任何可能竄改的弱點,從網頁上的元素到 HTTP Header 都是嘗試的對象。因此身為防禦者一定要清楚的知道哪些數值是不能信賴的,不要再參考網路上錯誤的教學了!5 G4 k; \+ G1 N, g( G, L) \% q
9 ?- N+ O2 K- C" W( ?
*原文參考 CEO Allen Own 大作 http://devco.re/blog/2014/06/19/client-ip-detection/: E0 h/ @" c$ G
|
|