tid=12495& 本帖最後由 IT_man 於 2015-7-3 10:47 編輯
+ v+ v2 k4 [- i( Q+ P5 P
) Q9 S& X& I8 c& F. P很多網站都會有偵測使用者 IP 的功能,不管是判斷使用者來自哪邊,或者是記錄使用者的位置。但是你知道嗎?網路上大多數的教學全部都是「錯誤」的。正確的程式寫法可以確保知道訪客的 IP,但是錯誤的寫法卻可能讓網站管理者永遠不知道犯罪者的來源。
' Y: Z! ]' F8 J1 {7 T9 K( f' N: b' j0 A& d
這次我們單就偵測 IP 的議題來探討各種錯誤的寫法。: M8 H. c$ I; l: ~" S
; ~7 J; e: f7 ^
4 l* F% S) T0 D! C, z
你知道網路上的教學是不安全的嗎?2 i, I$ M6 A8 ?/ x3 ?
我們先來看一下網路上的教學,讓我們 Google 找一下「PHP 取得 IP」,就可以看到許多人熱心的教學,我們隨意挑一個常見的教學來看看。
) k1 Z! \! I8 R& K9 X以 PHP 為例:
4 h' n" p# s+ ^& u/ q3 O- <?php% E; Z' [& m' n$ S% J9 g
- if(!empty($_SERVER['HTTP_CLIENT_IP'])){
9 M8 B/ F( p8 K; w9 Y' U - $myip = $_SERVER['HTTP_CLIENT_IP'];
R! I& g5 i/ w2 p4 y - }else if(!empty($_SERVER['HTTP_X_FORWARDED_FOR'])){
~$ P9 G% w2 S* j! T, x Q - $myip = $_SERVER['HTTP_X_FORWARDED_FOR'];7 N! ?" O4 V* ?% j8 J: i, C
- }else{
! z5 J& ?6 @% G1 ?, S4 S! { - $myip= $_SERVER['REMOTE_ADDR'];3 G2 K* P, v6 B( ]* g0 n8 X, ]6 q
- }
( v" ?2 Q" ?4 G2 V - echo $myip;
7 I7 c9 R( k* @0 K3 A1 t" l! C - ?>
複製代碼 % N4 }8 P, ~ d) e6 K
% K) Y; \; {' @! `$ ^0 l; h) G這是一個很基本的寫法、很正確的想法,如果 HTTP Header 中包含「Client-IP」,就先以他當作真實 IP。若包含「X-Forwarded-For」,則取他當作真實 IP。若兩者都沒有,則取「REMOTE_ADDR」變數作為真實 IP。因為當使用者連線時透過代理伺服器時,REMOTE_ADDR 會顯示為代理伺服器 Proxy 的 IP。部分代理伺服器會將使用者的原始真實 IP 放在 Client-IP 或 X-Forwarded-For header 中傳遞,如果在變數中呼叫則可以取得真實 IP。* {3 j6 l% V( B3 V; S1 Z4 V' |
但是你知道嗎?網路上 80% 的教學寫法全部都是「錯誤」的。4 N5 m$ W) j3 b9 R" B! Y7 K3 L- w2 k
5 |/ ?% H* y2 e7 i% x q* n+ I為什麼這樣說呢?請大家記得一件事情:「任何從客戶端取得的資料都是不可信任的!」
; ]% N$ G$ X4 G+ x. w5 J# r$ c( v8 O6 n- m
竄改 HTTP Header「X-Forwarded-For」這個變數雖然「有機會」取得使用者的真實 IP,但是由於這個值是從客戶端傳送過來的,所以「有可能」被使用者竄改。
" a% g; T& Q4 a舉例來說,我寫了一個小程式,偵測這些常見的 HTTP Header 判斷 IP。並且使用 Burp Suite 這個工具來修改 HTTP Request。$ X& B( L) Z; c9 D9 K# _
* H' u: T5 L' S# _
& X( L# q4 v! n9 j8 ~9 B* c頁面上顯示目前我目前的 IP「49.50.68.17」,並且其他的 header 是空的。但如果我今天使用 Burp Suite 之類的 Proxy 工具自行竄改封包,加上 X-Forwarded-For 或是 Client-IP header:7 p# ?7 f+ D1 X) a5 q& I: U+ p8 |
7 w: w8 A. z4 m3 x修改完畢之後,再到原本的顯示 IP 介面,會發現網頁錯將我竄改的 header 當作正確的資料填入。( W) J5 m* Y( G
, L; T4 X: D; e3 @( C" _
7 m: G {9 A7 h6 K, f
使用代理伺服器 Proxy 的情況使用代理伺服器的情況下,HTTP Header 會有不同的行為。例如 Elite Proxy 如何隱藏客戶端的真實 IP。以下簡單介紹幾種常見的狀況給各位參考。& Q' y! ?1 D7 g$ F6 i3 Y7 |
直接連線 (沒有使用 Proxy)" {0 U; ]: v* B& R4 l9 I8 R2 Q# H/ {
) s# B; H, O4 V9 @+ ` - REMOTE_ADDR: 客戶端真實 IP
- HTTP_VIA: 無
- HTTP_X_FORWARDED_FOR: 無7 S8 b9 c2 ~- o
Transparent Proxy w: I. K; Y ~2 H& l# q' y9 P% X; d
+ D, V# {) W& E! Q# ^( z4 Y' g _
- REMOTE_ADDR: 最後一個代理伺服器 IP
- HTTP_VIA: 代理伺服器 IP
- HTTP_X_FORWARDED_FOR: 客戶端真實 IP,後以逗點串接多個經過的代理伺服器 IP
" O$ ^% i) A: a& f Anonymous Proxy. p$ ?9 k: R* L
* ^1 u5 b8 k# n! @& b6 K, x0 h
- REMOTE_ADDR: 最後一個代理伺服器 IP
- HTTP_VIA: 代理伺服器 IP
- HTTP_X_FORWARDED_FOR: 代理伺服器 IP,後以逗點串接多個經過的代理伺服器 IP
" N: P( Q+ Q5 B High Anonymity Proxy (Elite Proxy)
/ G* l0 M' t+ M/ n
: Y" w5 T( ]4 J - REMOTE_ADDR: 代理伺服器 IP
- HTTP_VIA: 無
- HTTP_X_FORWARDED_FOR: 無 (或以逗點串接多個經過的代理伺服器 IP)
v$ T+ T! L9 _* X+ F- I 實際情況在我們測試的過程中,通常我們都會讓瀏覽器自帶 X-Forwarded-For,並且自行填入 IP。常常會發現有一些網站出現如下的警告…5 \' Q5 z# A$ Y1 {
- G4 T$ N0 Z) k( m' I P* L3 Q
有沒有搞錯?「上次登入位置 127.0.0.1」?沒錯,這個是知名論壇套件「Discuz!」的功能,抓取 IP 的功能也是不安全的寫法。也有這樣的經驗,之前開著 X-Forwarded-For 的 header 到一些網站,竟然直接出現管理者後台!6 X7 k& d* ]' P- J7 O' P
你覺得只有一般人撰寫的程式會有這樣的問題嗎?其實大型網站也可能會有類似的問題:. i$ W0 J9 ]! E3 x$ F; S; W
3 \/ {. Q" O q$ x, H
先不論為什麼 127.0.0.1 會在美國,這樣的寫法可能會讓管理者永遠抓不到犯罪者的真實 IP,甚至攻擊者可以竄改 header 插入特殊字元,對網站進行 SQL Injection 或者 Cross-Site Scripting 攻擊。: z' {/ r* x2 e
8 H( i. x" G# O% R# P3 A正確又安全的方式「任何從客戶端取得的資料都是不可信任的!」. g: V) P* x9 L# }1 ^+ ?
請各位開發者、管理者記住這個大原則,雖然這些 Request Header 可能含有真實 IP 的資訊,但是因為他的安全性不高,因此我們絕對不能完全信賴這個數值。
+ K+ g, L6 h0 t) B那我們該怎麼處理呢?我的建議是記錄所有相關的 header 欄位存入資料庫,包含「REMOTE_ADDR」「X-Forwarded-For」等等,真正有犯罪事件發生時,就可以調出所有完整的 IP 資訊進行人工判斷,找出真正的 IP。當然從 header 存入的數值也可能會遭到攻擊者竄改插入特殊字元嘗試 SQL Injection,因此存入值必須先經過過濾,或者使用 Prepared Statement 進行存放。
2 V4 I: P* t0 u' q可以參考的 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)
5 ], E3 j) i; I5 R% ^「駭客思維」就是找出網站任何可能竄改的弱點,從網頁上的元素到 HTTP Header 都是嘗試的對象。因此身為防禦者一定要清楚的知道哪些數值是不能信賴的,不要再參考網路上錯誤的教學了!
( Z" u2 [& q% s5 `2 I7 L( x( N1 k- P- X3 M6 _- I, m# k. W8 q
*原文參考 CEO Allen Own 大作 http://devco.re/blog/2014/06/19/client-ip-detection/
+ o" p4 d& H0 n1 i0 a |