tid=12495& 本帖最後由 IT_man 於 2015-7-3 10:47 編輯 - T% C2 f5 p; w f! k5 u, D5 ^
u$ s" z. I& d3 T' [
很多網站都會有偵測使用者 IP 的功能,不管是判斷使用者來自哪邊,或者是記錄使用者的位置。但是你知道嗎?網路上大多數的教學全部都是「錯誤」的。正確的程式寫法可以確保知道訪客的 IP,但是錯誤的寫法卻可能讓網站管理者永遠不知道犯罪者的來源。" g/ s: g2 V$ X7 R" v+ H* S" D
( S5 {5 W2 Y0 {( Y; T# C這次我們單就偵測 IP 的議題來探討各種錯誤的寫法。
/ n" g/ H4 v( U) G1 _" M ^1 V) _8 \& f4 l W$ ]
1 Y1 o, z% D$ B! T% @- f你知道網路上的教學是不安全的嗎?
& Z: i; j7 b' V) P4 F我們先來看一下網路上的教學,讓我們 Google 找一下「PHP 取得 IP」,就可以看到許多人熱心的教學,我們隨意挑一個常見的教學來看看。
' z- z) k8 x& z7 A: P以 PHP 為例:
' G1 w! W0 }, W- <?php
4 u/ D% M5 @1 G( S `) c! a# W - if(!empty($_SERVER['HTTP_CLIENT_IP'])){3 }& Z& k& W9 A5 h$ |) x i
- $myip = $_SERVER['HTTP_CLIENT_IP'];
0 b( D2 G9 v+ u( @* [ - }else if(!empty($_SERVER['HTTP_X_FORWARDED_FOR'])){
5 R6 h u/ F- V+ n3 p - $myip = $_SERVER['HTTP_X_FORWARDED_FOR'];* L' Q2 P- @! } ?; h3 Z4 {
- }else{- D! U" y3 d( m7 n% O7 U4 ]
- $myip= $_SERVER['REMOTE_ADDR'];6 y- s5 i+ u+ I9 r K
- }
6 e* L+ ^# J% J$ o3 c% m# Z - echo $myip;
) t. v7 \: p& }$ v - ?>
複製代碼 1 {2 o& @. ?# L- Q' G- h, P
8 ]5 R2 A/ L3 l
這是一個很基本的寫法、很正確的想法,如果 HTTP Header 中包含「Client-IP」,就先以他當作真實 IP。若包含「X-Forwarded-For」,則取他當作真實 IP。若兩者都沒有,則取「REMOTE_ADDR」變數作為真實 IP。因為當使用者連線時透過代理伺服器時,REMOTE_ADDR 會顯示為代理伺服器 Proxy 的 IP。部分代理伺服器會將使用者的原始真實 IP 放在 Client-IP 或 X-Forwarded-For header 中傳遞,如果在變數中呼叫則可以取得真實 IP。1 J: e. P6 @1 t0 Z
但是你知道嗎?網路上 80% 的教學寫法全部都是「錯誤」的。 W! ]0 T2 `9 a: u8 \
2 K6 t/ y3 B- d+ P& \- H4 p- o為什麼這樣說呢?請大家記得一件事情:「任何從客戶端取得的資料都是不可信任的!」# W9 N2 V$ o2 A: ^- i
# m! @/ d8 r) e2 L S$ d( o
竄改 HTTP Header「X-Forwarded-For」這個變數雖然「有機會」取得使用者的真實 IP,但是由於這個值是從客戶端傳送過來的,所以「有可能」被使用者竄改。4 M1 b" c$ \7 B- B- R
舉例來說,我寫了一個小程式,偵測這些常見的 HTTP Header 判斷 IP。並且使用 Burp Suite 這個工具來修改 HTTP Request。
: l; [+ H8 ]/ H' X% p
8 ~ F! d; g- t, F
& [3 t3 ~' m) I S* n3 F頁面上顯示目前我目前的 IP「49.50.68.17」,並且其他的 header 是空的。但如果我今天使用 Burp Suite 之類的 Proxy 工具自行竄改封包,加上 X-Forwarded-For 或是 Client-IP header:1 v* q( e; C2 i. @! x" z# A

v: F: `+ c/ i- S) v; G修改完畢之後,再到原本的顯示 IP 介面,會發現網頁錯將我竄改的 header 當作正確的資料填入。
4 e) L9 K0 P& u! X5 ` ( @7 M, W; a/ u/ m6 b0 N& r
( t- `6 f8 k) b5 x$ w ?
使用代理伺服器 Proxy 的情況使用代理伺服器的情況下,HTTP Header 會有不同的行為。例如 Elite Proxy 如何隱藏客戶端的真實 IP。以下簡單介紹幾種常見的狀況給各位參考。
% D( _7 H/ U+ F0 E0 _# k. K直接連線 (沒有使用 Proxy)% n3 h" |/ M" z' k7 ]! x @
. ]" c* k N1 q: Z6 R/ Z ]' e
- REMOTE_ADDR: 客戶端真實 IP
- HTTP_VIA: 無
- HTTP_X_FORWARDED_FOR: 無! o) k# T: m" b9 K2 b& \' t
Transparent Proxy! }) C8 w- U2 T' `- R3 Q
5 E& W. D+ Z# U
- REMOTE_ADDR: 最後一個代理伺服器 IP
- HTTP_VIA: 代理伺服器 IP
- HTTP_X_FORWARDED_FOR: 客戶端真實 IP,後以逗點串接多個經過的代理伺服器 IP
7 [; i2 }" B6 L- I" ?: ]' d) k. f A Anonymous Proxy* ?) i3 ~9 i: N# i
" \- w7 R7 O% h {# Q) |* h - REMOTE_ADDR: 最後一個代理伺服器 IP
- HTTP_VIA: 代理伺服器 IP
- HTTP_X_FORWARDED_FOR: 代理伺服器 IP,後以逗點串接多個經過的代理伺服器 IP
1 r/ K7 b `5 ] High Anonymity Proxy (Elite Proxy)' T& X3 ?6 @9 E7 V( \9 q
2 H9 b7 Q3 f4 X) P
- REMOTE_ADDR: 代理伺服器 IP
- HTTP_VIA: 無
- HTTP_X_FORWARDED_FOR: 無 (或以逗點串接多個經過的代理伺服器 IP)/ Q( W, e, J/ S9 E
實際情況在我們測試的過程中,通常我們都會讓瀏覽器自帶 X-Forwarded-For,並且自行填入 IP。常常會發現有一些網站出現如下的警告…
' ~; I0 _" ?, v+ m5 q4 ?& C2 _# n % m! g6 G7 o/ H" j# S
有沒有搞錯?「上次登入位置 127.0.0.1」?沒錯,這個是知名論壇套件「Discuz!」的功能,抓取 IP 的功能也是不安全的寫法。也有這樣的經驗,之前開著 X-Forwarded-For 的 header 到一些網站,竟然直接出現管理者後台!
: _4 D# c- A1 u& V你覺得只有一般人撰寫的程式會有這樣的問題嗎?其實大型網站也可能會有類似的問題:$ d) `/ O2 s$ o5 u; k7 W3 a/ ^
( O( i; F6 d: z5 M) z0 ^
先不論為什麼 127.0.0.1 會在美國,這樣的寫法可能會讓管理者永遠抓不到犯罪者的真實 IP,甚至攻擊者可以竄改 header 插入特殊字元,對網站進行 SQL Injection 或者 Cross-Site Scripting 攻擊。
5 W8 ^$ _( v% T/ e4 J' c* K) H: i% G, ]* ~
正確又安全的方式「任何從客戶端取得的資料都是不可信任的!」. P7 N0 w5 z5 r
請各位開發者、管理者記住這個大原則,雖然這些 Request Header 可能含有真實 IP 的資訊,但是因為他的安全性不高,因此我們絕對不能完全信賴這個數值。
4 H$ q9 ~# Y9 ?( F那我們該怎麼處理呢?我的建議是記錄所有相關的 header 欄位存入資料庫,包含「REMOTE_ADDR」「X-Forwarded-For」等等,真正有犯罪事件發生時,就可以調出所有完整的 IP 資訊進行人工判斷,找出真正的 IP。當然從 header 存入的數值也可能會遭到攻擊者竄改插入特殊字元嘗試 SQL Injection,因此存入值必須先經過過濾,或者使用 Prepared Statement 進行存放。4 w: W, G7 k, T5 [
可以參考的 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% I0 |2 k0 ~7 A A7 Q
「駭客思維」就是找出網站任何可能竄改的弱點,從網頁上的元素到 HTTP Header 都是嘗試的對象。因此身為防禦者一定要清楚的知道哪些數值是不能信賴的,不要再參考網路上錯誤的教學了!0 p- Q z% H7 h/ h) O
0 C3 \& F. m$ C! U( l1 y*原文參考 CEO Allen Own 大作 http://devco.re/blog/2014/06/19/client-ip-detection/, E: R" F& ^$ m2 e
|