本帖最後由 IT_man 於 2015-7-3 10:47 編輯
6 _' C, q$ J" p# z$ Y3 B/ g, [4 m# @$ C; t( s
很多網站都會有偵測使用者 IP 的功能,不管是判斷使用者來自哪邊,或者是記錄使用者的位置。但是你知道嗎?網路上大多數的教學全部都是「錯誤」的。正確的程式寫法可以確保知道訪客的 IP,但是錯誤的寫法卻可能讓網站管理者永遠不知道犯罪者的來源。
2 d- Y+ p; U ~5 F0 q: Y
) a! Q& c: k. n這次我們單就偵測 IP 的議題來探討各種錯誤的寫法。$ f* V; I- x6 E8 i2 h7 q
! i& u/ T( E% p1 U, C
8 Z3 R3 o* c( j& J. E0 ~* w
你知道網路上的教學是不安全的嗎?$ h0 u( v! w# d! ^
我們先來看一下網路上的教學,讓我們 Google 找一下「PHP 取得 IP」,就可以看到許多人熱心的教學,我們隨意挑一個常見的教學來看看。 b2 X ?" k7 |& G5 ~- |
以 PHP 為例:/ K2 Q- y* c- D9 H9 m/ F
- <?php
- D* A; ]' a9 O - if(!empty($_SERVER['HTTP_CLIENT_IP'])){
$ R5 q+ m9 d" d& Q, X( o1 D3 V; G - $myip = $_SERVER['HTTP_CLIENT_IP'];
, H& ]4 R' y7 I% M! B" Z - }else if(!empty($_SERVER['HTTP_X_FORWARDED_FOR'])){
) @! C9 L3 L- B& z% H2 P* I/ v4 F - $myip = $_SERVER['HTTP_X_FORWARDED_FOR'];9 O$ C7 w* D, ]& s" f
- }else{7 \9 R* K F9 U" C
- $myip= $_SERVER['REMOTE_ADDR'];
3 ?- V" Q6 y7 w' ^. A - }9 o8 K+ M$ B9 V, b; g! K' }6 F9 D& W4 r
- echo $myip;6 g) S7 @+ Z/ h" d
- ?>
複製代碼
5 p% @, C4 Y% E: V& B& i+ s8 v% j
這是一個很基本的寫法、很正確的想法,如果 HTTP Header 中包含「Client-IP」,就先以他當作真實 IP。若包含「X-Forwarded-For」,則取他當作真實 IP。若兩者都沒有,則取「REMOTE_ADDR」變數作為真實 IP。因為當使用者連線時透過代理伺服器時,REMOTE_ADDR 會顯示為代理伺服器 Proxy 的 IP。部分代理伺服器會將使用者的原始真實 IP 放在 Client-IP 或 X-Forwarded-For header 中傳遞,如果在變數中呼叫則可以取得真實 IP。' {& f" D2 U2 x2 u m
但是你知道嗎?網路上 80% 的教學寫法全部都是「錯誤」的。3 v9 r+ X" }7 ~7 B* r P. I
- ^) j( _- p: X# g# ^& t6 M/ V
為什麼這樣說呢?請大家記得一件事情:「任何從客戶端取得的資料都是不可信任的!」
, y6 ^3 U- v+ j. Q; A A" r8 K3 |2 z8 ~( \2 n/ S9 d
竄改 HTTP Header「X-Forwarded-For」這個變數雖然「有機會」取得使用者的真實 IP,但是由於這個值是從客戶端傳送過來的,所以「有可能」被使用者竄改。1 h9 T( y' U1 M' K- t* J
舉例來說,我寫了一個小程式,偵測這些常見的 HTTP Header 判斷 IP。並且使用 Burp Suite 這個工具來修改 HTTP Request。5 g" D9 W9 J: @
0 @8 ]/ H1 {* a& u0 s
0 m- L0 r& P& L頁面上顯示目前我目前的 IP「49.50.68.17」,並且其他的 header 是空的。但如果我今天使用 Burp Suite 之類的 Proxy 工具自行竄改封包,加上 X-Forwarded-For 或是 Client-IP header:
# q O. E: s2 {' y0 m
. Z8 X+ J8 d& \& U+ ~% a修改完畢之後,再到原本的顯示 IP 介面,會發現網頁錯將我竄改的 header 當作正確的資料填入。! H" W( W2 K$ s. s
- b8 w7 M3 v- Z4 b& c$ O8 G3 t8 E$ h
- V$ S5 I( u$ G& Q5 a5 i! `使用代理伺服器 Proxy 的情況使用代理伺服器的情況下,HTTP Header 會有不同的行為。例如 Elite Proxy 如何隱藏客戶端的真實 IP。以下簡單介紹幾種常見的狀況給各位參考。
$ A, @( A# f N I直接連線 (沒有使用 Proxy), u, v0 F9 s+ }
& T7 N1 b! _ k3 Y - REMOTE_ADDR: 客戶端真實 IP
- HTTP_VIA: 無
- HTTP_X_FORWARDED_FOR: 無- U P9 a( a# n0 i+ N( Y
Transparent Proxy
# B9 a, r$ y5 ^5 D7 O) V
' S1 r) C$ `. N* z' p1 \# J5 i - REMOTE_ADDR: 最後一個代理伺服器 IP
- HTTP_VIA: 代理伺服器 IP
- HTTP_X_FORWARDED_FOR: 客戶端真實 IP,後以逗點串接多個經過的代理伺服器 IP& W b* `; M( \/ P. D! @+ e4 \
Anonymous Proxy( t- A, e v$ D& A
8 A* }, X b# H/ v) v& Z; J - REMOTE_ADDR: 最後一個代理伺服器 IP
- HTTP_VIA: 代理伺服器 IP
- HTTP_X_FORWARDED_FOR: 代理伺服器 IP,後以逗點串接多個經過的代理伺服器 IP. E# z5 _- `' T& l- x8 Z, D
High Anonymity Proxy (Elite Proxy)) ~( P0 ?. R' \% |
% w, _3 G" X; k* x' j) f/ l5 X% T/ v
- REMOTE_ADDR: 代理伺服器 IP
- HTTP_VIA: 無
- HTTP_X_FORWARDED_FOR: 無 (或以逗點串接多個經過的代理伺服器 IP)* D5 x' s" e" R9 I
實際情況在我們測試的過程中,通常我們都會讓瀏覽器自帶 X-Forwarded-For,並且自行填入 IP。常常會發現有一些網站出現如下的警告…( N2 @6 W6 z" ^! a

C: L/ t) S. N" i7 D u有沒有搞錯?「上次登入位置 127.0.0.1」?沒錯,這個是知名論壇套件「Discuz!」的功能,抓取 IP 的功能也是不安全的寫法。也有這樣的經驗,之前開著 X-Forwarded-For 的 header 到一些網站,竟然直接出現管理者後台!' K+ [ i2 l6 p% @3 a$ S
你覺得只有一般人撰寫的程式會有這樣的問題嗎?其實大型網站也可能會有類似的問題:
5 C+ i9 p) H4 l% l+ f8 s
1 [ y- p) F# L" E4 A. Z先不論為什麼 127.0.0.1 會在美國,這樣的寫法可能會讓管理者永遠抓不到犯罪者的真實 IP,甚至攻擊者可以竄改 header 插入特殊字元,對網站進行 SQL Injection 或者 Cross-Site Scripting 攻擊。, c6 w$ ] D, t& v3 ? W- g
4 `6 K/ ~4 x( R6 r$ G
正確又安全的方式「任何從客戶端取得的資料都是不可信任的!」( y/ }8 M) h q+ L+ |' r, e
請各位開發者、管理者記住這個大原則,雖然這些 Request Header 可能含有真實 IP 的資訊,但是因為他的安全性不高,因此我們絕對不能完全信賴這個數值。
+ Q4 t8 k# n2 Q7 ?! _: r那我們該怎麼處理呢?我的建議是記錄所有相關的 header 欄位存入資料庫,包含「REMOTE_ADDR」「X-Forwarded-For」等等,真正有犯罪事件發生時,就可以調出所有完整的 IP 資訊進行人工判斷,找出真正的 IP。當然從 header 存入的數值也可能會遭到攻擊者竄改插入特殊字元嘗試 SQL Injection,因此存入值必須先經過過濾,或者使用 Prepared Statement 進行存放。
" ?6 I8 ^9 \3 \1 }( O可以參考的 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)
2 A, F. W S' {「駭客思維」就是找出網站任何可能竄改的弱點,從網頁上的元素到 HTTP Header 都是嘗試的對象。因此身為防禦者一定要清楚的知道哪些數值是不能信賴的,不要再參考網路上錯誤的教學了!; `0 x4 A% T! X2 e3 i. q3 ~
, H0 N- f* \. i
*原文參考 CEO Allen Own 大作 http://devco.re/blog/2014/06/19/client-ip-detection/- ~( f) M+ a! r# r
|
|