tid=12495& 本帖最後由 IT_man 於 2015-7-3 10:47 編輯
, }$ \( G. h! J" j6 N: L: t ^
6 Y6 H8 u. D7 J! l' |9 @( \很多網站都會有偵測使用者 IP 的功能,不管是判斷使用者來自哪邊,或者是記錄使用者的位置。但是你知道嗎?網路上大多數的教學全部都是「錯誤」的。正確的程式寫法可以確保知道訪客的 IP,但是錯誤的寫法卻可能讓網站管理者永遠不知道犯罪者的來源。( i; t7 o$ O. ~1 [! A2 s6 p
' c6 Z) t: D" t; U這次我們單就偵測 IP 的議題來探討各種錯誤的寫法。9 n! T- o" k6 T
" s& k: V E+ ^ H( m, v% c. P5 z, ~8 K) d) J
你知道網路上的教學是不安全的嗎?
) y( Q% \ g( @; u5 M+ k+ V( {我們先來看一下網路上的教學,讓我們 Google 找一下「PHP 取得 IP」,就可以看到許多人熱心的教學,我們隨意挑一個常見的教學來看看。" E& s2 r; {; l5 R9 n
以 PHP 為例:
5 C$ L/ A- G. R. k$ \, `- <?php
3 u/ |1 O9 V; I- s - if(!empty($_SERVER['HTTP_CLIENT_IP'])){
0 o. n& j6 _3 }1 q) p - $myip = $_SERVER['HTTP_CLIENT_IP'];
b- R+ Y/ t& J3 I0 y - }else if(!empty($_SERVER['HTTP_X_FORWARDED_FOR'])){: J0 A( M8 i) F! ~8 f4 P
- $myip = $_SERVER['HTTP_X_FORWARDED_FOR'];- Q# i. k, r3 {6 n. X- Z. W
- }else{5 l) s8 H" S* K; i
- $myip= $_SERVER['REMOTE_ADDR'];, a. ]- i# C9 Q% l' E
- }
; |/ k0 n9 ?' p6 h9 x& @3 R - echo $myip;2 z3 |' z: ~6 _- l( U2 r% `% K
- ?>
複製代碼
9 Q, g) r/ b# H6 v X7 a4 k$ a9 \; ]% P
這是一個很基本的寫法、很正確的想法,如果 HTTP Header 中包含「Client-IP」,就先以他當作真實 IP。若包含「X-Forwarded-For」,則取他當作真實 IP。若兩者都沒有,則取「REMOTE_ADDR」變數作為真實 IP。因為當使用者連線時透過代理伺服器時,REMOTE_ADDR 會顯示為代理伺服器 Proxy 的 IP。部分代理伺服器會將使用者的原始真實 IP 放在 Client-IP 或 X-Forwarded-For header 中傳遞,如果在變數中呼叫則可以取得真實 IP。
" Y7 _# ^. R% p8 ^( K x8 P* W7 U但是你知道嗎?網路上 80% 的教學寫法全部都是「錯誤」的。3 t! @/ [ W. w: @# @
5 a& J/ G7 V6 i/ ~! ^. ^/ s為什麼這樣說呢?請大家記得一件事情:「任何從客戶端取得的資料都是不可信任的!」
% b1 ^7 m9 z3 x4 g; s8 S1 p& d t- \+ s6 D! H0 I
竄改 HTTP Header「X-Forwarded-For」這個變數雖然「有機會」取得使用者的真實 IP,但是由於這個值是從客戶端傳送過來的,所以「有可能」被使用者竄改。0 ?, F( O1 U! S' X$ {
舉例來說,我寫了一個小程式,偵測這些常見的 HTTP Header 判斷 IP。並且使用 Burp Suite 這個工具來修改 HTTP Request。
& Z" |/ I! X) I
6 l: }0 Y7 L+ f! n
( `5 c" N2 [3 Y. V1 e1 ~$ f頁面上顯示目前我目前的 IP「49.50.68.17」,並且其他的 header 是空的。但如果我今天使用 Burp Suite 之類的 Proxy 工具自行竄改封包,加上 X-Forwarded-For 或是 Client-IP header:
$ o# K1 U& s+ y8 ~ 4 o7 @- v2 }* J" o: d
修改完畢之後,再到原本的顯示 IP 介面,會發現網頁錯將我竄改的 header 當作正確的資料填入。
; f0 ]! B8 N3 u- T0 ^
9 V+ Y6 a( I) L4 n% [6 z; U
7 C9 J5 a" y7 r, s使用代理伺服器 Proxy 的情況使用代理伺服器的情況下,HTTP Header 會有不同的行為。例如 Elite Proxy 如何隱藏客戶端的真實 IP。以下簡單介紹幾種常見的狀況給各位參考。2 I* H3 R5 F0 G
直接連線 (沒有使用 Proxy)
3 `# `2 @" p% O4 f) T) O1 z, U, T: \
- REMOTE_ADDR: 客戶端真實 IP
- HTTP_VIA: 無
- HTTP_X_FORWARDED_FOR: 無
$ ?! R. F* E; U7 \ Transparent Proxy7 c' u# a- U2 _4 f* I% O) P
* U3 y0 W- n+ T) m1 [ - REMOTE_ADDR: 最後一個代理伺服器 IP
- HTTP_VIA: 代理伺服器 IP
- HTTP_X_FORWARDED_FOR: 客戶端真實 IP,後以逗點串接多個經過的代理伺服器 IP
: `' {& s& q' f$ k5 j- {- ] Anonymous Proxy
5 a$ E/ I. X* d9 |9 i
4 V$ e+ J8 m( @3 g6 P& _+ X - REMOTE_ADDR: 最後一個代理伺服器 IP
- HTTP_VIA: 代理伺服器 IP
- HTTP_X_FORWARDED_FOR: 代理伺服器 IP,後以逗點串接多個經過的代理伺服器 IP
2 n" J T6 Z7 o' p: i S High Anonymity Proxy (Elite Proxy). r! n. R# |5 _& z
$ t, }3 G- v6 ]! @5 I- X) K0 y
- REMOTE_ADDR: 代理伺服器 IP
- HTTP_VIA: 無
- HTTP_X_FORWARDED_FOR: 無 (或以逗點串接多個經過的代理伺服器 IP)# U# I( H) X) A2 b1 D V0 Q
實際情況在我們測試的過程中,通常我們都會讓瀏覽器自帶 X-Forwarded-For,並且自行填入 IP。常常會發現有一些網站出現如下的警告…3 U5 w3 A( _# m( c$ a3 h- J6 `) K

! }) i o3 p, }8 ~1 R- q! i有沒有搞錯?「上次登入位置 127.0.0.1」?沒錯,這個是知名論壇套件「Discuz!」的功能,抓取 IP 的功能也是不安全的寫法。也有這樣的經驗,之前開著 X-Forwarded-For 的 header 到一些網站,竟然直接出現管理者後台!
" F8 U1 j0 j% S" B! f你覺得只有一般人撰寫的程式會有這樣的問題嗎?其實大型網站也可能會有類似的問題:
0 J- d+ J6 ?/ T9 q0 s
. C M3 M7 C! E& {0 T8 h* A* w先不論為什麼 127.0.0.1 會在美國,這樣的寫法可能會讓管理者永遠抓不到犯罪者的真實 IP,甚至攻擊者可以竄改 header 插入特殊字元,對網站進行 SQL Injection 或者 Cross-Site Scripting 攻擊。
3 I; B7 V$ k& k# `$ ? @& K2 E( z& k* I
正確又安全的方式「任何從客戶端取得的資料都是不可信任的!」
) e( O7 U9 C# d0 k5 x; P \! }請各位開發者、管理者記住這個大原則,雖然這些 Request Header 可能含有真實 IP 的資訊,但是因為他的安全性不高,因此我們絕對不能完全信賴這個數值。
' h9 s4 l/ @' d那我們該怎麼處理呢?我的建議是記錄所有相關的 header 欄位存入資料庫,包含「REMOTE_ADDR」「X-Forwarded-For」等等,真正有犯罪事件發生時,就可以調出所有完整的 IP 資訊進行人工判斷,找出真正的 IP。當然從 header 存入的數值也可能會遭到攻擊者竄改插入特殊字元嘗試 SQL Injection,因此存入值必須先經過過濾,或者使用 Prepared Statement 進行存放。7 S4 f6 b" l7 y' E& A9 H
可以參考的 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)
/ X7 {# ~7 t) F2 B# c% d! H" |「駭客思維」就是找出網站任何可能竄改的弱點,從網頁上的元素到 HTTP Header 都是嘗試的對象。因此身為防禦者一定要清楚的知道哪些數值是不能信賴的,不要再參考網路上錯誤的教學了!5 S. e. g3 a) Z' H# b; z! P
* u, |! M, ?- ]1 ^8 G0 P*原文參考 CEO Allen Own 大作 http://devco.re/blog/2014/06/19/client-ip-detection/
- w+ Y( S( ^9 \6 k( _ |