tid=12495& 本帖最後由 IT_man 於 2015-7-3 10:47 編輯
+ _$ J1 ^) \0 E" w8 I+ v( F1 k3 j1 r
很多網站都會有偵測使用者 IP 的功能,不管是判斷使用者來自哪邊,或者是記錄使用者的位置。但是你知道嗎?網路上大多數的教學全部都是「錯誤」的。正確的程式寫法可以確保知道訪客的 IP,但是錯誤的寫法卻可能讓網站管理者永遠不知道犯罪者的來源。
* c9 i9 t7 d# ~6 v. ^
# l& B5 K& @2 ~這次我們單就偵測 IP 的議題來探討各種錯誤的寫法。
7 x. g- V, G' R: u+ x5 i, f7 H: L: O6 p3 g' A* B
" `: U0 Y2 N( q3 C! V; c
你知道網路上的教學是不安全的嗎?4 z u. F; p) H; ]; [
我們先來看一下網路上的教學,讓我們 Google 找一下「PHP 取得 IP」,就可以看到許多人熱心的教學,我們隨意挑一個常見的教學來看看。7 I; w7 z4 m/ Y- R; Z# {7 v/ Z1 y
以 PHP 為例:
; ~1 A; d/ B9 T9 L( [. P$ s( R- <?php) R+ b- O6 g1 T" F6 |
- if(!empty($_SERVER['HTTP_CLIENT_IP'])){
: m& c, {5 E0 T& |' \ - $myip = $_SERVER['HTTP_CLIENT_IP'];! L; p5 [# c. `
- }else if(!empty($_SERVER['HTTP_X_FORWARDED_FOR'])){+ ^' ]8 M4 _' f5 w2 J
- $myip = $_SERVER['HTTP_X_FORWARDED_FOR'];
1 v6 h3 B' @( b7 m - }else{
$ q/ o& q" J/ O( \9 ] - $myip= $_SERVER['REMOTE_ADDR'];
. |0 u9 [5 H% l1 ?% O) T - }$ c& ?7 x0 M6 Z9 t# t4 \
- echo $myip;, E$ }) y( Z# o2 L9 t. [
- ?>
複製代碼
& Y! n6 n2 p0 B
7 `* V) A& v Q1 s# X這是一個很基本的寫法、很正確的想法,如果 HTTP Header 中包含「Client-IP」,就先以他當作真實 IP。若包含「X-Forwarded-For」,則取他當作真實 IP。若兩者都沒有,則取「REMOTE_ADDR」變數作為真實 IP。因為當使用者連線時透過代理伺服器時,REMOTE_ADDR 會顯示為代理伺服器 Proxy 的 IP。部分代理伺服器會將使用者的原始真實 IP 放在 Client-IP 或 X-Forwarded-For header 中傳遞,如果在變數中呼叫則可以取得真實 IP。) d! z) v1 _# n3 |/ K& |
但是你知道嗎?網路上 80% 的教學寫法全部都是「錯誤」的。
' y9 C# Q; u( [9 E) e; W/ }/ D" K: B& X8 u, b& E
為什麼這樣說呢?請大家記得一件事情:「任何從客戶端取得的資料都是不可信任的!」, U; K( A5 v6 Z7 ]
/ t0 }( f0 a" D. ?6 b0 ` @竄改 HTTP Header「X-Forwarded-For」這個變數雖然「有機會」取得使用者的真實 IP,但是由於這個值是從客戶端傳送過來的,所以「有可能」被使用者竄改。! r5 t0 p0 ?+ |( x, I' v% I1 f
舉例來說,我寫了一個小程式,偵測這些常見的 HTTP Header 判斷 IP。並且使用 Burp Suite 這個工具來修改 HTTP Request。
& q" h; N# b! E/ Z
- Y0 `5 s& X+ X7 \$ e/ w4 ~% Q) T% S- v; t6 b, A9 _# b* Z
頁面上顯示目前我目前的 IP「49.50.68.17」,並且其他的 header 是空的。但如果我今天使用 Burp Suite 之類的 Proxy 工具自行竄改封包,加上 X-Forwarded-For 或是 Client-IP header:( ^$ p3 Z5 N' w: `4 q2 p

8 f4 H# d$ V2 d# c& _修改完畢之後,再到原本的顯示 IP 介面,會發現網頁錯將我竄改的 header 當作正確的資料填入。
l+ i* z- k! l5 j, p; I , m& b* S2 A o1 _- C" T7 A
6 Z( e W: O" V; \7 D( a7 R; A使用代理伺服器 Proxy 的情況使用代理伺服器的情況下,HTTP Header 會有不同的行為。例如 Elite Proxy 如何隱藏客戶端的真實 IP。以下簡單介紹幾種常見的狀況給各位參考。! [/ A3 r& K7 x- w$ D5 Y" p$ A. @
直接連線 (沒有使用 Proxy)# }: C% a5 Y9 |1 l& L3 s
5 n2 }5 n( T( ~& T
- REMOTE_ADDR: 客戶端真實 IP
- HTTP_VIA: 無
- HTTP_X_FORWARDED_FOR: 無 @( q# s* X' @7 a
Transparent Proxy$ [7 b2 o. K+ {1 G
& | ] l9 ?2 o: p- j0 k3 s! Z. ]9 K
- REMOTE_ADDR: 最後一個代理伺服器 IP
- HTTP_VIA: 代理伺服器 IP
- HTTP_X_FORWARDED_FOR: 客戶端真實 IP,後以逗點串接多個經過的代理伺服器 IP
6 g1 f$ j8 d* d) @$ g7 n5 G Anonymous Proxy
, w0 i9 m0 v5 o: m* L' K. I0 W& `7 z7 l4 u; e
- REMOTE_ADDR: 最後一個代理伺服器 IP
- HTTP_VIA: 代理伺服器 IP
- HTTP_X_FORWARDED_FOR: 代理伺服器 IP,後以逗點串接多個經過的代理伺服器 IP2 K5 t1 L9 a% H
High Anonymity Proxy (Elite Proxy)3 T' N( u# D' V# ~* |8 h" C
" P( W6 I2 U: v& k6 }& y F
- REMOTE_ADDR: 代理伺服器 IP
- HTTP_VIA: 無
- HTTP_X_FORWARDED_FOR: 無 (或以逗點串接多個經過的代理伺服器 IP)
% H2 j# Z2 Y2 W8 z' c9 V0 V 實際情況在我們測試的過程中,通常我們都會讓瀏覽器自帶 X-Forwarded-For,並且自行填入 IP。常常會發現有一些網站出現如下的警告…5 @# Q/ q0 T( Y- I

- S4 n" N: n, C有沒有搞錯?「上次登入位置 127.0.0.1」?沒錯,這個是知名論壇套件「Discuz!」的功能,抓取 IP 的功能也是不安全的寫法。也有這樣的經驗,之前開著 X-Forwarded-For 的 header 到一些網站,竟然直接出現管理者後台!
, Y+ Q. j( Z, V0 f) p: r4 H" l你覺得只有一般人撰寫的程式會有這樣的問題嗎?其實大型網站也可能會有類似的問題:
" P1 q$ }5 o0 z
3 K$ o$ l) c. |, _先不論為什麼 127.0.0.1 會在美國,這樣的寫法可能會讓管理者永遠抓不到犯罪者的真實 IP,甚至攻擊者可以竄改 header 插入特殊字元,對網站進行 SQL Injection 或者 Cross-Site Scripting 攻擊。: M; x1 p4 m' Z
, V2 v* C6 n! e$ ?
正確又安全的方式「任何從客戶端取得的資料都是不可信任的!」4 v% A' Z/ a d8 |5 v: E
請各位開發者、管理者記住這個大原則,雖然這些 Request Header 可能含有真實 IP 的資訊,但是因為他的安全性不高,因此我們絕對不能完全信賴這個數值。
) R& K7 P4 c* p ?3 S+ j; G( f那我們該怎麼處理呢?我的建議是記錄所有相關的 header 欄位存入資料庫,包含「REMOTE_ADDR」「X-Forwarded-For」等等,真正有犯罪事件發生時,就可以調出所有完整的 IP 資訊進行人工判斷,找出真正的 IP。當然從 header 存入的數值也可能會遭到攻擊者竄改插入特殊字元嘗試 SQL Injection,因此存入值必須先經過過濾,或者使用 Prepared Statement 進行存放。
, P0 s8 ?4 z8 ^可以參考的 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 J; d2 K2 o: h# g; B「駭客思維」就是找出網站任何可能竄改的弱點,從網頁上的元素到 HTTP Header 都是嘗試的對象。因此身為防禦者一定要清楚的知道哪些數值是不能信賴的,不要再參考網路上錯誤的教學了!5 T9 d" N* f, L2 {
5 c% Q6 d+ N6 ?+ g$ z h
*原文參考 CEO Allen Own 大作 http://devco.re/blog/2014/06/19/client-ip-detection/* d4 k) I( ^! q1 Y
|