tid=12495& 本帖最後由 IT_man 於 2015-7-3 10:47 編輯
* b# J& Z0 X* C. ^) ~& P
% @( Q/ I3 [6 G$ ^很多網站都會有偵測使用者 IP 的功能,不管是判斷使用者來自哪邊,或者是記錄使用者的位置。但是你知道嗎?網路上大多數的教學全部都是「錯誤」的。正確的程式寫法可以確保知道訪客的 IP,但是錯誤的寫法卻可能讓網站管理者永遠不知道犯罪者的來源。 i0 q& p7 x5 @( V) M
# ]& r7 T( @0 F: Z% s. t, d; I這次我們單就偵測 IP 的議題來探討各種錯誤的寫法。( L" T& I; S9 f4 F5 n0 J7 {
( B( D }& M: W) u
u2 F8 O+ P$ r; c' Q2 I6 R. Y你知道網路上的教學是不安全的嗎?! ? P; l# o! v" h- E9 ~
我們先來看一下網路上的教學,讓我們 Google 找一下「PHP 取得 IP」,就可以看到許多人熱心的教學,我們隨意挑一個常見的教學來看看。, A# h2 X' I7 G9 k" [& m0 |: {
以 PHP 為例:# Z* Y7 {9 W% m5 E& E- c0 \
- <?php6 X, L+ ?0 B, f8 q# Q6 x
- if(!empty($_SERVER['HTTP_CLIENT_IP'])){. o2 e4 d+ }3 A9 H( {+ y
- $myip = $_SERVER['HTTP_CLIENT_IP'];
* l3 _& j l1 _5 E2 ^+ x6 ?( W - }else if(!empty($_SERVER['HTTP_X_FORWARDED_FOR'])){
1 ]8 _' y( X" F# \& ? - $myip = $_SERVER['HTTP_X_FORWARDED_FOR'];
; u% r; D j5 c% n) l8 Z6 V5 ] - }else{! f* D2 y1 v, j5 N/ _" H0 K# M
- $myip= $_SERVER['REMOTE_ADDR'];
B, H; Z+ w1 J; B* R+ {7 i% i - }
2 }3 U' v4 C0 @( e8 @+ T0 ` - echo $myip;! Y5 V2 Y5 w: n
- ?>
複製代碼 X# y; T5 |7 r) M
+ Q* X& J# ^3 p$ a) V5 I這是一個很基本的寫法、很正確的想法,如果 HTTP Header 中包含「Client-IP」,就先以他當作真實 IP。若包含「X-Forwarded-For」,則取他當作真實 IP。若兩者都沒有,則取「REMOTE_ADDR」變數作為真實 IP。因為當使用者連線時透過代理伺服器時,REMOTE_ADDR 會顯示為代理伺服器 Proxy 的 IP。部分代理伺服器會將使用者的原始真實 IP 放在 Client-IP 或 X-Forwarded-For header 中傳遞,如果在變數中呼叫則可以取得真實 IP。7 e! o6 c, A2 g% o& l
但是你知道嗎?網路上 80% 的教學寫法全部都是「錯誤」的。
" ?$ \" v, A" }
: F$ O. } O: P; P' T7 E為什麼這樣說呢?請大家記得一件事情:「任何從客戶端取得的資料都是不可信任的!」
, S: X p$ C, d1 m) P$ T4 t% E$ a- l( Z5 d& [* `* u
竄改 HTTP Header「X-Forwarded-For」這個變數雖然「有機會」取得使用者的真實 IP,但是由於這個值是從客戶端傳送過來的,所以「有可能」被使用者竄改。% O* T# D1 I, W/ z z* h
舉例來說,我寫了一個小程式,偵測這些常見的 HTTP Header 判斷 IP。並且使用 Burp Suite 這個工具來修改 HTTP Request。- J8 T8 N( V. @
9 h+ Q; V0 y% T5 c4 Y0 P: T3 S. P! E
頁面上顯示目前我目前的 IP「49.50.68.17」,並且其他的 header 是空的。但如果我今天使用 Burp Suite 之類的 Proxy 工具自行竄改封包,加上 X-Forwarded-For 或是 Client-IP header:
+ U# Q Y: s8 q9 z8 V
9 L* I( X+ m" p8 \5 U- e. g) k修改完畢之後,再到原本的顯示 IP 介面,會發現網頁錯將我竄改的 header 當作正確的資料填入。
& d& n7 f/ j. h. r$ y
$ L4 ^6 c9 S6 e+ S7 B* y2 J6 y3 {! d8 F% ^% B5 F% s4 V& C
使用代理伺服器 Proxy 的情況使用代理伺服器的情況下,HTTP Header 會有不同的行為。例如 Elite Proxy 如何隱藏客戶端的真實 IP。以下簡單介紹幾種常見的狀況給各位參考。1 g* B: ^% x8 a. L
直接連線 (沒有使用 Proxy)
: V3 S* W' k* Q1 z3 q: I7 k. W
5 ~ X k2 T; x/ l - REMOTE_ADDR: 客戶端真實 IP
- HTTP_VIA: 無
- HTTP_X_FORWARDED_FOR: 無3 ]; M0 f$ ?. Q( H9 v
Transparent Proxy {& ?8 l# G& a
. c" t& x% m, m; p6 g3 o+ H
- REMOTE_ADDR: 最後一個代理伺服器 IP
- HTTP_VIA: 代理伺服器 IP
- HTTP_X_FORWARDED_FOR: 客戶端真實 IP,後以逗點串接多個經過的代理伺服器 IP
2 M+ {4 p* G* d Anonymous Proxy" K( m* ]7 K/ e, b% i; B4 o
! _0 i# j0 M- r# D( i/ H9 m - REMOTE_ADDR: 最後一個代理伺服器 IP
- HTTP_VIA: 代理伺服器 IP
- HTTP_X_FORWARDED_FOR: 代理伺服器 IP,後以逗點串接多個經過的代理伺服器 IP
" O) C0 a( T; _9 ?( M High Anonymity Proxy (Elite Proxy)
* v, w2 h" R1 e" ~: l& D( N( X8 g' n) i# v: R0 d
- REMOTE_ADDR: 代理伺服器 IP
- HTTP_VIA: 無
- HTTP_X_FORWARDED_FOR: 無 (或以逗點串接多個經過的代理伺服器 IP)
* X x7 r h ]6 V4 X6 X5 @5 w 實際情況在我們測試的過程中,通常我們都會讓瀏覽器自帶 X-Forwarded-For,並且自行填入 IP。常常會發現有一些網站出現如下的警告…
, e" W" L5 m. @
F$ p- z6 L1 l7 v5 `" ?2 K有沒有搞錯?「上次登入位置 127.0.0.1」?沒錯,這個是知名論壇套件「Discuz!」的功能,抓取 IP 的功能也是不安全的寫法。也有這樣的經驗,之前開著 X-Forwarded-For 的 header 到一些網站,竟然直接出現管理者後台!
' m! i M& h! z你覺得只有一般人撰寫的程式會有這樣的問題嗎?其實大型網站也可能會有類似的問題:( L6 |0 k; Z) n" R
% W9 I* g# T8 f" m- Y先不論為什麼 127.0.0.1 會在美國,這樣的寫法可能會讓管理者永遠抓不到犯罪者的真實 IP,甚至攻擊者可以竄改 header 插入特殊字元,對網站進行 SQL Injection 或者 Cross-Site Scripting 攻擊。" `" V9 t: L" k
( H- x4 Y ~3 b8 F
正確又安全的方式「任何從客戶端取得的資料都是不可信任的!」% O& p k! q% s! q! p
請各位開發者、管理者記住這個大原則,雖然這些 Request Header 可能含有真實 IP 的資訊,但是因為他的安全性不高,因此我們絕對不能完全信賴這個數值。
/ v g& K' ]4 _" y7 n0 S6 u那我們該怎麼處理呢?我的建議是記錄所有相關的 header 欄位存入資料庫,包含「REMOTE_ADDR」「X-Forwarded-For」等等,真正有犯罪事件發生時,就可以調出所有完整的 IP 資訊進行人工判斷,找出真正的 IP。當然從 header 存入的數值也可能會遭到攻擊者竄改插入特殊字元嘗試 SQL Injection,因此存入值必須先經過過濾,或者使用 Prepared Statement 進行存放。
: ]+ H# g8 P0 {% F9 v, c1 }& 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)
+ x! ~; I- g' c+ a) \7 S6 k' n7 i: ~「駭客思維」就是找出網站任何可能竄改的弱點,從網頁上的元素到 HTTP Header 都是嘗試的對象。因此身為防禦者一定要清楚的知道哪些數值是不能信賴的,不要再參考網路上錯誤的教學了!
+ c1 o) v& \) K( b$ Z9 h7 a' n, @* }4 \3 x9 c
*原文參考 CEO Allen Own 大作 http://devco.re/blog/2014/06/19/client-ip-detection/9 i: w5 D5 c' r# H/ J c/ ^% d% E
|