tid=12495& 本帖最後由 IT_man 於 2015-7-3 10:47 編輯 R% }& s. _6 O+ h* v
+ ?: x& m+ D* {: U
很多網站都會有偵測使用者 IP 的功能,不管是判斷使用者來自哪邊,或者是記錄使用者的位置。但是你知道嗎?網路上大多數的教學全部都是「錯誤」的。正確的程式寫法可以確保知道訪客的 IP,但是錯誤的寫法卻可能讓網站管理者永遠不知道犯罪者的來源。
- M: w- o0 q+ q1 c
: J8 W4 A" O9 l9 G這次我們單就偵測 IP 的議題來探討各種錯誤的寫法。
& A' n) s3 |5 t i" a7 X( X' r( I) }- p2 W' e) n5 r- A
- q! z) r7 o9 \/ ~你知道網路上的教學是不安全的嗎?
' O4 @$ C4 N. C- B( P' E我們先來看一下網路上的教學,讓我們 Google 找一下「PHP 取得 IP」,就可以看到許多人熱心的教學,我們隨意挑一個常見的教學來看看。
. W3 r" ]. j4 {3 [8 g! A9 e以 PHP 為例:% O" l' {4 g% Z: x9 e, g
- <?php# i" Z R0 P2 P6 Z1 l
- if(!empty($_SERVER['HTTP_CLIENT_IP'])){1 H& |/ {' x7 k: D. s
- $myip = $_SERVER['HTTP_CLIENT_IP'];" {( r; y* r/ Z1 x2 l, d
- }else if(!empty($_SERVER['HTTP_X_FORWARDED_FOR'])){ I5 y6 Z2 y% K r
- $myip = $_SERVER['HTTP_X_FORWARDED_FOR'];
5 h4 }8 p8 ~* R9 Q, t. M - }else{9 r$ G' b# m& S6 D* m2 M4 W
- $myip= $_SERVER['REMOTE_ADDR']; x' ^( @4 U) e& d5 h+ r
- }% o, P+ n2 b. e) d$ L
- echo $myip;: w! J% N- y- @' o. U
- ?>
複製代碼 4 n' Y$ w% m: y+ [, @
/ D: B2 c/ T- C& C
這是一個很基本的寫法、很正確的想法,如果 HTTP Header 中包含「Client-IP」,就先以他當作真實 IP。若包含「X-Forwarded-For」,則取他當作真實 IP。若兩者都沒有,則取「REMOTE_ADDR」變數作為真實 IP。因為當使用者連線時透過代理伺服器時,REMOTE_ADDR 會顯示為代理伺服器 Proxy 的 IP。部分代理伺服器會將使用者的原始真實 IP 放在 Client-IP 或 X-Forwarded-For header 中傳遞,如果在變數中呼叫則可以取得真實 IP。
- \ r G% D$ N. W% }) V `* c但是你知道嗎?網路上 80% 的教學寫法全部都是「錯誤」的。 l! P, c! T) V* b0 \/ ?1 w' b4 K: M
2 _4 w+ M! M0 I0 S: r' G! y& F9 x) n
為什麼這樣說呢?請大家記得一件事情:「任何從客戶端取得的資料都是不可信任的!」) B% `1 q6 ?4 t8 `% _8 n% j, {
3 p: t1 r8 \7 f: D' G* g竄改 HTTP Header「X-Forwarded-For」這個變數雖然「有機會」取得使用者的真實 IP,但是由於這個值是從客戶端傳送過來的,所以「有可能」被使用者竄改。
5 ?6 g" v# g) `3 t舉例來說,我寫了一個小程式,偵測這些常見的 HTTP Header 判斷 IP。並且使用 Burp Suite 這個工具來修改 HTTP Request。
) d& ^$ U3 \3 j+ L2 ^0 f6 Y, z
/ z0 c* p& {- k5 c( M& k, s
2 E8 j" Q9 S2 _) D頁面上顯示目前我目前的 IP「49.50.68.17」,並且其他的 header 是空的。但如果我今天使用 Burp Suite 之類的 Proxy 工具自行竄改封包,加上 X-Forwarded-For 或是 Client-IP header:
3 s2 d% u7 Q/ L2 R5 s4 F! [
! a4 W$ A! Q9 {1 f6 G, K: `修改完畢之後,再到原本的顯示 IP 介面,會發現網頁錯將我竄改的 header 當作正確的資料填入。
2 U6 e' S: ~& v. M& C6 A, q1 r7 g * j$ @: m0 X5 B& ^# s
/ M. J+ R j9 E. X; L! r
使用代理伺服器 Proxy 的情況使用代理伺服器的情況下,HTTP Header 會有不同的行為。例如 Elite Proxy 如何隱藏客戶端的真實 IP。以下簡單介紹幾種常見的狀況給各位參考。
5 O6 g a. ^( ^+ x! T, B直接連線 (沒有使用 Proxy)
& S5 a9 W- J0 R3 a, |2 n! a6 S0 D' f3 z
- REMOTE_ADDR: 客戶端真實 IP
- HTTP_VIA: 無
- HTTP_X_FORWARDED_FOR: 無6 }1 w, L! C3 W; Y5 ~" M. @7 B
Transparent Proxy; m z6 c% G$ B7 G
! g# s; g1 Q0 V- {3 I2 M
- REMOTE_ADDR: 最後一個代理伺服器 IP
- HTTP_VIA: 代理伺服器 IP
- HTTP_X_FORWARDED_FOR: 客戶端真實 IP,後以逗點串接多個經過的代理伺服器 IP
4 j. b& h# m3 N0 { Anonymous Proxy( k' d7 `6 i! B; b8 u
# F( q. d3 r$ C+ y$ G* K. m3 N - REMOTE_ADDR: 最後一個代理伺服器 IP
- HTTP_VIA: 代理伺服器 IP
- HTTP_X_FORWARDED_FOR: 代理伺服器 IP,後以逗點串接多個經過的代理伺服器 IP
. ]- m5 Z( P% M' `$ a' R High Anonymity Proxy (Elite Proxy)
) U: k& t5 m7 F. t; K& B$ b1 _% C7 X
- REMOTE_ADDR: 代理伺服器 IP
- HTTP_VIA: 無
- HTTP_X_FORWARDED_FOR: 無 (或以逗點串接多個經過的代理伺服器 IP)) C* H" H9 n9 h+ }$ P: h w
實際情況在我們測試的過程中,通常我們都會讓瀏覽器自帶 X-Forwarded-For,並且自行填入 IP。常常會發現有一些網站出現如下的警告…3 }: a; z8 J/ L6 a2 q/ b4 n' _2 g- e' ?
4 ]& _+ `% L2 b5 m; A: L4 |
有沒有搞錯?「上次登入位置 127.0.0.1」?沒錯,這個是知名論壇套件「Discuz!」的功能,抓取 IP 的功能也是不安全的寫法。也有這樣的經驗,之前開著 X-Forwarded-For 的 header 到一些網站,竟然直接出現管理者後台!
- x; ]$ P9 R5 Z3 \( w你覺得只有一般人撰寫的程式會有這樣的問題嗎?其實大型網站也可能會有類似的問題:/ S- l( w+ B, m3 f+ ]# j
; x" B) D) X+ ?8 z/ y9 b
先不論為什麼 127.0.0.1 會在美國,這樣的寫法可能會讓管理者永遠抓不到犯罪者的真實 IP,甚至攻擊者可以竄改 header 插入特殊字元,對網站進行 SQL Injection 或者 Cross-Site Scripting 攻擊。
: V! r0 J+ O2 |
v7 f8 P, [& t- T正確又安全的方式「任何從客戶端取得的資料都是不可信任的!」1 _9 P( I: l7 L$ Z
請各位開發者、管理者記住這個大原則,雖然這些 Request Header 可能含有真實 IP 的資訊,但是因為他的安全性不高,因此我們絕對不能完全信賴這個數值。9 z# q3 j5 S, x% L3 ?
那我們該怎麼處理呢?我的建議是記錄所有相關的 header 欄位存入資料庫,包含「REMOTE_ADDR」「X-Forwarded-For」等等,真正有犯罪事件發生時,就可以調出所有完整的 IP 資訊進行人工判斷,找出真正的 IP。當然從 header 存入的數值也可能會遭到攻擊者竄改插入特殊字元嘗試 SQL Injection,因此存入值必須先經過過濾,或者使用 Prepared Statement 進行存放。/ `; {- v2 Z |( V( W
可以參考的 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)
& ?$ h) L# y( u' d! N1 d1 E「駭客思維」就是找出網站任何可能竄改的弱點,從網頁上的元素到 HTTP Header 都是嘗試的對象。因此身為防禦者一定要清楚的知道哪些數值是不能信賴的,不要再參考網路上錯誤的教學了!; X2 [1 e' f3 }1 x! a0 p! }
: A3 h. H8 X4 L* a, A4 X3 W*原文參考 CEO Allen Own 大作 http://devco.re/blog/2014/06/19/client-ip-detection/
4 B; e! t5 G0 P) {/ f |