本帖最後由 IT_man 於 2015-7-3 10:47 編輯
, u. w7 p4 |8 ?4 e& p
& v9 c. Q+ I% w很多網站都會有偵測使用者 IP 的功能,不管是判斷使用者來自哪邊,或者是記錄使用者的位置。但是你知道嗎?網路上大多數的教學全部都是「錯誤」的。正確的程式寫法可以確保知道訪客的 IP,但是錯誤的寫法卻可能讓網站管理者永遠不知道犯罪者的來源。
, a7 d1 P7 e6 _% Y# O( r/ g/ H& ]& @/ q; b
這次我們單就偵測 IP 的議題來探討各種錯誤的寫法。
. `$ b" d* \6 }
1 u* A) c2 _! g) s( U2 w7 Z1 G. u2 }0 L# w
你知道網路上的教學是不安全的嗎?
5 I; K& ~2 ^4 R. W' }' V4 w+ f我們先來看一下網路上的教學,讓我們 Google 找一下「PHP 取得 IP」,就可以看到許多人熱心的教學,我們隨意挑一個常見的教學來看看。
2 Y. N5 y2 ~4 M R4 E3 N* k以 PHP 為例:6 d7 z8 \8 w+ I
- <?php1 t' k/ [8 d- ~( ]7 R+ U$ E
- if(!empty($_SERVER['HTTP_CLIENT_IP'])){
' v9 A! `- K- @' `7 Q Z9 l - $myip = $_SERVER['HTTP_CLIENT_IP'];8 I" l, j5 s8 D8 o
- }else if(!empty($_SERVER['HTTP_X_FORWARDED_FOR'])){
( r n4 S; A5 R6 w2 ~" f- ^& s, U2 P - $myip = $_SERVER['HTTP_X_FORWARDED_FOR'];6 M3 u, o' I _; o8 L* p
- }else{
5 G( a! J# V+ y# S3 w8 ` - $myip= $_SERVER['REMOTE_ADDR'];5 ?6 b6 a1 W) n! ]5 d1 z% @, s
- }" G$ y7 ^8 T" {, P
- echo $myip;: |8 @ A) v" @% Q! Q3 N( H
- ?>
複製代碼 + ~* W% D) ]6 k. Y: i$ I0 `
, X6 q9 u' `! t) J8 Z, ?( c1 P& K這是一個很基本的寫法、很正確的想法,如果 HTTP Header 中包含「Client-IP」,就先以他當作真實 IP。若包含「X-Forwarded-For」,則取他當作真實 IP。若兩者都沒有,則取「REMOTE_ADDR」變數作為真實 IP。因為當使用者連線時透過代理伺服器時,REMOTE_ADDR 會顯示為代理伺服器 Proxy 的 IP。部分代理伺服器會將使用者的原始真實 IP 放在 Client-IP 或 X-Forwarded-For header 中傳遞,如果在變數中呼叫則可以取得真實 IP。
" ^. i# |. b9 g$ l* \4 I但是你知道嗎?網路上 80% 的教學寫法全部都是「錯誤」的。
% w* z+ f! h8 N" k! i# w
, ?1 U: J' o/ Y0 k. C% T0 s為什麼這樣說呢?請大家記得一件事情:「任何從客戶端取得的資料都是不可信任的!」7 s2 ~( Z$ x3 p) r0 H
8 O0 B7 `. y! L- B
竄改 HTTP Header「X-Forwarded-For」這個變數雖然「有機會」取得使用者的真實 IP,但是由於這個值是從客戶端傳送過來的,所以「有可能」被使用者竄改。
+ o& b7 A+ P6 }0 |: c; k0 Q( ?7 q* l舉例來說,我寫了一個小程式,偵測這些常見的 HTTP Header 判斷 IP。並且使用 Burp Suite 這個工具來修改 HTTP Request。
* X8 T6 D' i1 p( _1 d/ P0 H
1 s/ r1 ^( }: t8 N& k; N4 Q4 e+ o5 }3 p( W, Z; k O
頁面上顯示目前我目前的 IP「49.50.68.17」,並且其他的 header 是空的。但如果我今天使用 Burp Suite 之類的 Proxy 工具自行竄改封包,加上 X-Forwarded-For 或是 Client-IP header:1 T1 `+ i7 Z- V7 C" e# f; Y% v
$ ~: w0 P% w% W& j6 E
修改完畢之後,再到原本的顯示 IP 介面,會發現網頁錯將我竄改的 header 當作正確的資料填入。* ?, a! W0 ^) f1 Q! P
1 M2 P1 t! v3 C9 s
9 f# h$ l' s8 P% c8 @( E
使用代理伺服器 Proxy 的情況使用代理伺服器的情況下,HTTP Header 會有不同的行為。例如 Elite Proxy 如何隱藏客戶端的真實 IP。以下簡單介紹幾種常見的狀況給各位參考。
3 j9 O! C7 K% n7 m直接連線 (沒有使用 Proxy)
. s. c y/ L: `2 T) h" d3 f6 Y$ `
1 v! f/ ^; ?' ]6 w6 V - REMOTE_ADDR: 客戶端真實 IP
- HTTP_VIA: 無
- HTTP_X_FORWARDED_FOR: 無) C8 \7 V& z3 F
Transparent Proxy
9 m. {4 I! Q3 w5 I- q# h- p4 f( r) }3 P
- REMOTE_ADDR: 最後一個代理伺服器 IP
- HTTP_VIA: 代理伺服器 IP
- HTTP_X_FORWARDED_FOR: 客戶端真實 IP,後以逗點串接多個經過的代理伺服器 IP7 o0 y, y. d& r
Anonymous Proxy- t' W( I# [" P! f( }
7 i5 h+ ?) r0 v
- REMOTE_ADDR: 最後一個代理伺服器 IP
- HTTP_VIA: 代理伺服器 IP
- HTTP_X_FORWARDED_FOR: 代理伺服器 IP,後以逗點串接多個經過的代理伺服器 IP
: ]7 I3 }% ?$ x7 |* i. x4 P! C High Anonymity Proxy (Elite Proxy)
( }0 W5 ~* V& B1 ?: V
2 E% M$ q9 C" t$ `' [* d - REMOTE_ADDR: 代理伺服器 IP
- HTTP_VIA: 無
- HTTP_X_FORWARDED_FOR: 無 (或以逗點串接多個經過的代理伺服器 IP)) v3 q: a+ m3 `; H' N: @
實際情況在我們測試的過程中,通常我們都會讓瀏覽器自帶 X-Forwarded-For,並且自行填入 IP。常常會發現有一些網站出現如下的警告…
9 A7 \+ o) D6 @# I6 k" Z; D# ]% _7 g& R$ d9 r R; f8 P
有沒有搞錯?「上次登入位置 127.0.0.1」?沒錯,這個是知名論壇套件「Discuz!」的功能,抓取 IP 的功能也是不安全的寫法。也有這樣的經驗,之前開著 X-Forwarded-For 的 header 到一些網站,竟然直接出現管理者後台! m# d5 T9 N% o8 |2 V* {7 c
你覺得只有一般人撰寫的程式會有這樣的問題嗎?其實大型網站也可能會有類似的問題:
! M. @, S, C9 o7 j" |% a9 g$ k* n1 J+ a, L2 V# F
先不論為什麼 127.0.0.1 會在美國,這樣的寫法可能會讓管理者永遠抓不到犯罪者的真實 IP,甚至攻擊者可以竄改 header 插入特殊字元,對網站進行 SQL Injection 或者 Cross-Site Scripting 攻擊。- f2 D- x3 R8 g
m4 f$ U6 H+ ~
正確又安全的方式「任何從客戶端取得的資料都是不可信任的!」
) u' q, G, [" X* y7 L; b f. h: b請各位開發者、管理者記住這個大原則,雖然這些 Request Header 可能含有真實 IP 的資訊,但是因為他的安全性不高,因此我們絕對不能完全信賴這個數值。& M5 p$ y$ ]& @8 _2 r$ v
那我們該怎麼處理呢?我的建議是記錄所有相關的 header 欄位存入資料庫,包含「REMOTE_ADDR」「X-Forwarded-For」等等,真正有犯罪事件發生時,就可以調出所有完整的 IP 資訊進行人工判斷,找出真正的 IP。當然從 header 存入的數值也可能會遭到攻擊者竄改插入特殊字元嘗試 SQL Injection,因此存入值必須先經過過濾,或者使用 Prepared Statement 進行存放。
/ |8 f' P0 R9 e0 Z可以參考的 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)% n" C Y( ~) ^5 z; T( {3 m. T) a
「駭客思維」就是找出網站任何可能竄改的弱點,從網頁上的元素到 HTTP Header 都是嘗試的對象。因此身為防禦者一定要清楚的知道哪些數值是不能信賴的,不要再參考網路上錯誤的教學了!
% I# `5 u4 s2 |! ^& m# j5 Q$ k7 L6 ^$ s% q
*原文參考 CEO Allen Own 大作 http://devco.re/blog/2014/06/19/client-ip-detection/$ \5 z2 G, N3 m. t3 B. @
|
|