tid=12495& 本帖最後由 IT_man 於 2015-7-3 10:47 編輯 4 L$ ^+ v N/ v
_: l/ M3 u$ U; Z+ Q; E9 p4 ?, n很多網站都會有偵測使用者 IP 的功能,不管是判斷使用者來自哪邊,或者是記錄使用者的位置。但是你知道嗎?網路上大多數的教學全部都是「錯誤」的。正確的程式寫法可以確保知道訪客的 IP,但是錯誤的寫法卻可能讓網站管理者永遠不知道犯罪者的來源。
( ~( E1 H. `8 ?) Q! Z7 U0 W3 `
( m- E+ ~! H' `0 H, H這次我們單就偵測 IP 的議題來探討各種錯誤的寫法。
9 M G0 X8 ^5 J& N$ S( F' g8 R, i+ M8 Q7 |2 B2 D* ~ g8 h
" D) Q4 h* P( h你知道網路上的教學是不安全的嗎?( h6 M1 E: b: k r# l, e0 l. s
我們先來看一下網路上的教學,讓我們 Google 找一下「PHP 取得 IP」,就可以看到許多人熱心的教學,我們隨意挑一個常見的教學來看看。! D, y! t) c# N; l, s
以 PHP 為例:
. V! A! N8 g2 _6 \6 F& q- <?php
6 i K5 _0 e, {) q1 ]9 x0 i k - if(!empty($_SERVER['HTTP_CLIENT_IP'])){
: a9 n% V$ A) m5 D - $myip = $_SERVER['HTTP_CLIENT_IP'];
2 Z# v! ?, C8 c9 T- K - }else if(!empty($_SERVER['HTTP_X_FORWARDED_FOR'])){
. ]+ f* U6 I6 R3 a; ~. N; E( [1 @ - $myip = $_SERVER['HTTP_X_FORWARDED_FOR'];
5 c! Y, R+ {& K. [/ { - }else{/ { `0 e6 V2 L$ c2 R1 |
- $myip= $_SERVER['REMOTE_ADDR'];
3 [- j1 o1 K# D2 i% Z! z3 p - }
, e/ X2 C: d/ ]6 _3 X6 @0 F - echo $myip;
3 O( \/ T2 I8 ^ - ?>
複製代碼
( T# |7 m7 U1 H/ `+ o' z7 C# V/ }0 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。6 C( z, f" m2 ]" I- y6 ?
但是你知道嗎?網路上 80% 的教學寫法全部都是「錯誤」的。
+ C% w5 j1 \" E, t+ r0 w! B
; G2 c+ \0 A# e' s( Y7 @為什麼這樣說呢?請大家記得一件事情:「任何從客戶端取得的資料都是不可信任的!」
! J: M) t5 B6 n
* \6 {0 C5 U# t, x" @竄改 HTTP Header「X-Forwarded-For」這個變數雖然「有機會」取得使用者的真實 IP,但是由於這個值是從客戶端傳送過來的,所以「有可能」被使用者竄改。
# I5 R6 ^) G2 @* s% p舉例來說,我寫了一個小程式,偵測這些常見的 HTTP Header 判斷 IP。並且使用 Burp Suite 這個工具來修改 HTTP Request。
7 y; d9 D8 C: C: e1 W
( t! t/ O h, E% b
) N Y) Q; H4 r5 H
頁面上顯示目前我目前的 IP「49.50.68.17」,並且其他的 header 是空的。但如果我今天使用 Burp Suite 之類的 Proxy 工具自行竄改封包,加上 X-Forwarded-For 或是 Client-IP header:
6 R) m1 n7 M4 y 9 [0 s8 z E+ I
修改完畢之後,再到原本的顯示 IP 介面,會發現網頁錯將我竄改的 header 當作正確的資料填入。; @; ?% ~' m- n ?5 t- k

0 B- } |3 R- k6 G2 }+ M% a, o$ d) F. B! @
使用代理伺服器 Proxy 的情況使用代理伺服器的情況下,HTTP Header 會有不同的行為。例如 Elite Proxy 如何隱藏客戶端的真實 IP。以下簡單介紹幾種常見的狀況給各位參考。
5 G" A3 e* g2 ^4 E: x% k直接連線 (沒有使用 Proxy). Z& N& J) t& \: m" Y# u* B, l
! U4 D9 a0 ^! ]
- REMOTE_ADDR: 客戶端真實 IP
- HTTP_VIA: 無
- HTTP_X_FORWARDED_FOR: 無
' W9 w- k! Y9 {! j& e Transparent Proxy
: G, {; y; E& l4 p% J9 O' Z
% n' { G5 f. L9 I7 r t! x2 T - REMOTE_ADDR: 最後一個代理伺服器 IP
- HTTP_VIA: 代理伺服器 IP
- HTTP_X_FORWARDED_FOR: 客戶端真實 IP,後以逗點串接多個經過的代理伺服器 IP
5 w+ p' f" D2 G( j7 n" \ Anonymous Proxy
8 e Y% ^/ @' }/ B% }! f5 W/ N5 P* c, @8 i% k8 S# z" R
- REMOTE_ADDR: 最後一個代理伺服器 IP
- HTTP_VIA: 代理伺服器 IP
- HTTP_X_FORWARDED_FOR: 代理伺服器 IP,後以逗點串接多個經過的代理伺服器 IP* c2 h% `3 Q7 y8 K# S" y3 z
High Anonymity Proxy (Elite Proxy)0 `8 z# t7 f8 z* z
; p/ ]' A" ^2 M; x. F3 g Y2 x
- REMOTE_ADDR: 代理伺服器 IP
- HTTP_VIA: 無
- HTTP_X_FORWARDED_FOR: 無 (或以逗點串接多個經過的代理伺服器 IP)1 m0 d4 B/ E! G& d
實際情況在我們測試的過程中,通常我們都會讓瀏覽器自帶 X-Forwarded-For,並且自行填入 IP。常常會發現有一些網站出現如下的警告…3 I2 T2 I3 x9 \
, G0 f8 x, N: D7 s3 M
有沒有搞錯?「上次登入位置 127.0.0.1」?沒錯,這個是知名論壇套件「Discuz!」的功能,抓取 IP 的功能也是不安全的寫法。也有這樣的經驗,之前開著 X-Forwarded-For 的 header 到一些網站,竟然直接出現管理者後台!% ~& q* i2 e# K: d- F; |* U
你覺得只有一般人撰寫的程式會有這樣的問題嗎?其實大型網站也可能會有類似的問題:
! j" z1 Y% }# J
! _' u' ~9 }3 i- u9 ?* S先不論為什麼 127.0.0.1 會在美國,這樣的寫法可能會讓管理者永遠抓不到犯罪者的真實 IP,甚至攻擊者可以竄改 header 插入特殊字元,對網站進行 SQL Injection 或者 Cross-Site Scripting 攻擊。
7 s) z6 @: a/ M u: F8 n0 ~5 `( [( e4 g' ~
正確又安全的方式「任何從客戶端取得的資料都是不可信任的!」
+ v0 K+ A" t+ f1 ^+ K3 d請各位開發者、管理者記住這個大原則,雖然這些 Request Header 可能含有真實 IP 的資訊,但是因為他的安全性不高,因此我們絕對不能完全信賴這個數值。
% ~4 m: t( D8 N6 t5 }+ o) y n那我們該怎麼處理呢?我的建議是記錄所有相關的 header 欄位存入資料庫,包含「REMOTE_ADDR」「X-Forwarded-For」等等,真正有犯罪事件發生時,就可以調出所有完整的 IP 資訊進行人工判斷,找出真正的 IP。當然從 header 存入的數值也可能會遭到攻擊者竄改插入特殊字元嘗試 SQL Injection,因此存入值必須先經過過濾,或者使用 Prepared Statement 進行存放。
* c5 c) ?- G- I, M- i可以參考的 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)
( E7 b7 U# G. C$ c「駭客思維」就是找出網站任何可能竄改的弱點,從網頁上的元素到 HTTP Header 都是嘗試的對象。因此身為防禦者一定要清楚的知道哪些數值是不能信賴的,不要再參考網路上錯誤的教學了!. R: z6 P, l9 g
" u' d8 X5 ]7 [' p2 C*原文參考 CEO Allen Own 大作 http://devco.re/blog/2014/06/19/client-ip-detection/; e8 t; F2 \" v S% { [
|