2013年4月8日 星期一

PHP 使用 curl 偽造 client 端 IP 與來源網址

[client 端 IP]
一般要獲取用戶端 IP 時,常會判斷以下這些值。
  1. $_SERVER["HTTP_CLIENT_IP"]
  2. $_SERVER["HTTP_X_FORWARDED_FOR"]
  3. $_SERVER["HTTP_X_FORWARDED"]
  4. $_SERVER["HTTP_X_CLUSTER_CLIENT_IP"]
  5. $_SERVER["HTTP_FORWARDED_FOR"]
  6. $_SERVER["HTTP_FORWARDED"]
  7. $_SERVER["REMOTE_ADDR"]
但 1~6 這幾個的值都可以由使用者模擬出假資料,唯獨 REMOTE_ADDR 無法偽造。

[來源網址]
一般要得知用戶端來源網址時,常會獲取 $_SERVER['HTTP_REFERER'] 的值。
但 HTTP_REFERER 也是可以偽造的。

[範例]
  1. http://demo.cinc.biz/changeip/1.php
    是一支偽造用戶端 IP 和來源網址的範例。
    這支程式向 http://demo.cinc.biz/changeip/2.php 訪問,
    並輸出 2.php 回應的訊息。
  2. http://demo.cinc.biz/changeip/2.php
    則是單純的輸出用戶端 1~7 項 IP 資訊,與 $_SERVER['HTTP_REFERER'] 的值。
  3. 程式如下
    [1.php]
    $ch = curl_init();
    curl_setopt($ch,CURLOPT_URL,"http://demo.cinc.biz/changeip/2.php");
    curl_setopt($ch,CURLOPT_HTTPHEADER,array(
        'CLIENT-IP:8.8.8.8',
        'X-FORWARDED-FOR:8.8.8.9',
        'X-FORWARDED:8.8.8.10',
        'X-CLUSTER-CLIENT_IP:8.8.8.11',
        'FORWARDED-FOR:8.8.8.12',
        'FORWARDED:8.8.8.13',
        'REMOTE-ADDR:8.8.8.14' //REMOTE-ADDR 無法偽造
        ));
    //偽造連結過來網頁網頁
    curl_setopt($ch,CURLOPT_REFERER,"http://example.com/");
    curl_setopt($ch,CURLOPT_HEADER,0);//是否輸出header
    $out = curl_exec($ch);
    curl_close($ch);

    [2.php]
    <pre>
    <?php
    echo '$_SERVER["HTTP_CLIENT_IP"]:' . $_SERVER['HTTP_CLIENT_IP'] . "\n";
    echo '$_SERVER["HTTP_X_FORWARDED_FOR"]:' . $_SERVER['HTTP_X_FORWARDED_FOR'] . "\n";
    echo '$_SERVER["HTTP_X_FORWARDED"]:' . $_SERVER['HTTP_X_FORWARDED'] . "\n";
    echo '$_SERVER["HTTP_X_CLUSTER_CLIENT_IP"]:' . $_SERVER['HTTP_X_CLUSTER_CLIENT_IP'] . "\n";
    echo '$_SERVER["HTTP_FORWARDED_FOR"]:' . $_SERVER['HTTP_FORWARDED_FOR'] . "\n";
    echo '$_SERVER["HTTP_FORWARDED"]:' . $_SERVER['HTTP_FORWARDED'] . "\n";
    echo '<strong>$_SERVER["REMOTE_ADDR"]:' . $_SERVER['REMOTE_ADDR'] . "</strong>\n";
    echo '$_SERVER["HTTP_REFERER"]:' . $_SERVER['HTTP_REFERER'] . "\n";
    ?>
    </pre>
  4. 測試結果:http://demo.cinc.biz/changeip/1.php
[結論]
所以有時判斷很多因素,取得的 IP 也有可能是偽造的。
但用 REMOTE-ADDR 取使用者 IP,若使用者有用 proxy,就只能取到 proxy 的 IP。
因此用哪一種方式,就要取決於視實際情況較偏重什麼了。

沒有留言:

張貼留言