tid=12495& 本帖最後由 IT_man 於 2015-7-3 10:47 編輯
! S" U1 ~& \0 T9 f, D1 S9 E& G" G* K1 G, @
很多網站都會有偵測使用者 IP 的功能,不管是判斷使用者來自哪邊,或者是記錄使用者的位置。但是你知道嗎?網路上大多數的教學全部都是「錯誤」的。正確的程式寫法可以確保知道訪客的 IP,但是錯誤的寫法卻可能讓網站管理者永遠不知道犯罪者的來源。 x/ M" b& O" p
' p) T( ]( I; q" M( M
這次我們單就偵測 IP 的議題來探討各種錯誤的寫法。' k7 U! `) A6 v; \
$ v' | ?( U l4 z+ ^ K$ Z5 F
8 c9 X- \8 S! u$ X
你知道網路上的教學是不安全的嗎?
u- u0 Z3 c5 w: {/ r/ j9 ^* U$ i我們先來看一下網路上的教學,讓我們 Google 找一下「PHP 取得 IP」,就可以看到許多人熱心的教學,我們隨意挑一個常見的教學來看看。9 U! B! j1 p/ f# q* k
以 PHP 為例:
) a4 W, Q4 \. f8 ~- <?php
/ J# u: Y1 @$ `: D9 A4 s - if(!empty($_SERVER['HTTP_CLIENT_IP'])){
- C! J: l& t. }$ J - $myip = $_SERVER['HTTP_CLIENT_IP'];9 f6 u% l3 e4 y V% r! {2 z
- }else if(!empty($_SERVER['HTTP_X_FORWARDED_FOR'])){; R# O; G c" F1 I5 H s1 {
- $myip = $_SERVER['HTTP_X_FORWARDED_FOR'];5 K6 P! m( M4 b( n1 c
- }else{* x% {' x5 n' b$ m& T5 J
- $myip= $_SERVER['REMOTE_ADDR'];
+ M, M6 @! f8 b, c - }
$ a/ [) Y1 v( C. @ - echo $myip;
. E5 j5 f: Q9 d, d, V. p5 t - ?>
複製代碼
; c, H9 [) Z* `5 Y
1 O) _1 t6 l/ G9 P% w. 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 h. @7 @# X$ R$ Q) ^但是你知道嗎?網路上 80% 的教學寫法全部都是「錯誤」的。
% Y- g8 v# b7 s
! e, Q4 H4 k; I: E" a* v為什麼這樣說呢?請大家記得一件事情:「任何從客戶端取得的資料都是不可信任的!」" F: ^# E9 ^' S0 b3 v: Z, p( ~+ J
6 |; G/ l' e# R6 x7 Z, s竄改 HTTP Header「X-Forwarded-For」這個變數雖然「有機會」取得使用者的真實 IP,但是由於這個值是從客戶端傳送過來的,所以「有可能」被使用者竄改。9 n8 w! n" ]! n6 V+ w
舉例來說,我寫了一個小程式,偵測這些常見的 HTTP Header 判斷 IP。並且使用 Burp Suite 這個工具來修改 HTTP Request。9 u, z4 q2 j/ X# I( M% |
+ o8 V3 n. {8 c3 X% K( n6 L2 s7 j1 G- K8 H
頁面上顯示目前我目前的 IP「49.50.68.17」,並且其他的 header 是空的。但如果我今天使用 Burp Suite 之類的 Proxy 工具自行竄改封包,加上 X-Forwarded-For 或是 Client-IP header:
, F% u k1 m" f3 E8 ]1 W& @( `' {$ L, L0 T
修改完畢之後,再到原本的顯示 IP 介面,會發現網頁錯將我竄改的 header 當作正確的資料填入。$ c/ W5 Y& |7 ]$ S; w: b; D( G8 k) S
5 t. o3 ^ v1 u
( f* s) E( C: U使用代理伺服器 Proxy 的情況使用代理伺服器的情況下,HTTP Header 會有不同的行為。例如 Elite Proxy 如何隱藏客戶端的真實 IP。以下簡單介紹幾種常見的狀況給各位參考。
9 @4 T4 s/ u% k+ E. c+ h直接連線 (沒有使用 Proxy)! L/ p2 W$ [; f9 F7 C* T
: a2 j& J2 S6 i, d& t7 n, k1 F* S - REMOTE_ADDR: 客戶端真實 IP
- HTTP_VIA: 無
- HTTP_X_FORWARDED_FOR: 無5 A) c6 Q% V& z; o
Transparent Proxy6 c4 A+ H, ?7 W. F
. \3 P1 o' t0 ] - REMOTE_ADDR: 最後一個代理伺服器 IP
- HTTP_VIA: 代理伺服器 IP
- HTTP_X_FORWARDED_FOR: 客戶端真實 IP,後以逗點串接多個經過的代理伺服器 IP+ p: e3 w D7 j( ~. _. Q/ W
Anonymous Proxy! Q- l# z! i- \1 a0 k" M _9 U7 g
/ }5 r6 E! N7 d5 @% F4 @& \( | - REMOTE_ADDR: 最後一個代理伺服器 IP
- HTTP_VIA: 代理伺服器 IP
- HTTP_X_FORWARDED_FOR: 代理伺服器 IP,後以逗點串接多個經過的代理伺服器 IP
* }& h. q# W7 i/ h! Y High Anonymity Proxy (Elite Proxy)
8 l( R- p5 x3 B
& A2 a3 ~: i, L4 _# I - REMOTE_ADDR: 代理伺服器 IP
- HTTP_VIA: 無
- HTTP_X_FORWARDED_FOR: 無 (或以逗點串接多個經過的代理伺服器 IP), A7 F V/ D: W2 ~/ ~
實際情況在我們測試的過程中,通常我們都會讓瀏覽器自帶 X-Forwarded-For,並且自行填入 IP。常常會發現有一些網站出現如下的警告…9 v; j4 L) g O
3 u- B0 D: V$ r. U1 }* e" @有沒有搞錯?「上次登入位置 127.0.0.1」?沒錯,這個是知名論壇套件「Discuz!」的功能,抓取 IP 的功能也是不安全的寫法。也有這樣的經驗,之前開著 X-Forwarded-For 的 header 到一些網站,竟然直接出現管理者後台!
: w2 R6 m; q6 @% r+ C4 {: P4 F" H你覺得只有一般人撰寫的程式會有這樣的問題嗎?其實大型網站也可能會有類似的問題:
3 A. l2 I+ b2 E, W
6 D" z. v6 S* q5 n$ i# z6 ?. ~9 Y# X先不論為什麼 127.0.0.1 會在美國,這樣的寫法可能會讓管理者永遠抓不到犯罪者的真實 IP,甚至攻擊者可以竄改 header 插入特殊字元,對網站進行 SQL Injection 或者 Cross-Site Scripting 攻擊。
' y# ?, Z, Q+ X, }1 D% C+ s5 d- G0 U. x! _* I7 z8 R1 Q
正確又安全的方式「任何從客戶端取得的資料都是不可信任的!」
5 Z5 [* E e2 D0 d2 S請各位開發者、管理者記住這個大原則,雖然這些 Request Header 可能含有真實 IP 的資訊,但是因為他的安全性不高,因此我們絕對不能完全信賴這個數值。
. E/ G" E! h$ ^1 y" A; y; l) X那我們該怎麼處理呢?我的建議是記錄所有相關的 header 欄位存入資料庫,包含「REMOTE_ADDR」「X-Forwarded-For」等等,真正有犯罪事件發生時,就可以調出所有完整的 IP 資訊進行人工判斷,找出真正的 IP。當然從 header 存入的數值也可能會遭到攻擊者竄改插入特殊字元嘗試 SQL Injection,因此存入值必須先經過過濾,或者使用 Prepared Statement 進行存放。1 A+ g3 @& w C2 f6 t; ^
可以參考的 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)
% a( `# I8 u& r6 w0 ^. i1 c' T「駭客思維」就是找出網站任何可能竄改的弱點,從網頁上的元素到 HTTP Header 都是嘗試的對象。因此身為防禦者一定要清楚的知道哪些數值是不能信賴的,不要再參考網路上錯誤的教學了!
/ v9 w4 l+ I. w: N" ]* H- X, ` Y. O
*原文參考 CEO Allen Own 大作 http://devco.re/blog/2014/06/19/client-ip-detection/ W1 ~; h! L- X$ Y7 ? d D- v
|