HTTP_REFERER的用法及偽造


引言

在php中,可以使用$_SERVER[‘HTTP_REFERER’]來獲取HTTP_REFERER信息,關於HTTP_REFERER,php文檔中的描述如下:

“引導用戶代理到當前頁的前一頁的地址(如果存在)。由 user agent 設置決定。並不是所有的用戶代理都會設置該項,有的還提供了修改
HTTP_REFERER 的功能。簡言之,該值並不可信。 ”

在百度百科中,對於該參數的描述如下:

“HTTP
Referer是header的一部分,當瀏覽器向web服務器發送請求的時候,一般會帶上Referer,告訴服務器我是從哪個頁面鏈接過來的,服務器籍此可以獲得一些信息用於處理。”

從上面的論述中我們可以得到如下幾點結論:

   http_referer由瀏覽器生成,並不是所有瀏覽器都會設置該值。
    http_referer可以偽造,並不可信。

HTTP_REFERER的用途

HTTP_REFERER提供了引導用戶代理到當前頁的前一頁的地址信息,常見的一些應用場景有防盜鏈,統計文章有多少次是來自谷歌搜索結果,多少次來自百度搜索結果等。
下面以防盜鏈為例,講講HTTP_REFERER的用法。
如果你經常寫博客,就一定會遇到盜用你辛辛苦苦整理過的文章不跟你打任何招呼甚至連原文鏈接都一並抹除的網站,文字這個層面我們沒法控制,但是圖片這個層面我們是可以控制的。舉個例子,如果你也曾復制過一些類似騰訊等網站的文章,你會發現黏貼下來發表之后經常出現圖片無法顯示,這是如何做到的呢?
場景:a站點的圖片全部存儲在c站點(雲服務器)上,c站點將識別調用方是否來自a站點,否則顯示一張錯誤圖片,b站是盜圖網站。
a站和b站的代碼一致,如下所示:

<img src="http://www.c.com/image.php?fname=jb.png" width="500px" height="500px" />;

重點是c站的代碼,如下所示:

<?php
if(strpos($_SERVER['HTTP_REFERER'], 'www.a.com')  !== false){
    //以下的寫法並不嚴謹,這里只是做測試
    if(file_exists($_GET['fname'])){
        echo file_get_contents($_GET['fname']);
    }
}


這樣當a站訪問時圖片可以正常顯示,而b站訪問時圖片是顯示不出來的。
什么時候獲取不到HTTP_REFERER值

綜上所述,HTTP_REFERER存在需要兩個條件:

    瀏覽器(客戶端)請求(服務器端請求的情況下,是不存在HTTP_REFERER的,但是可以偽造header,這在下一節中將提及);

    存在前導頁;

    以下是網友收集的獲取不到HTTP_REFERER值的情況:

    在瀏覽器內直接敲URL
    windows桌面上的超鏈接圖標
    瀏覽器內書簽
    第三方軟件(如Word,Excel等)內容中的鏈接
    SSL認證網站跳入
    http://example.com/“> meta頁面設置自動跳轉時,在example.com將取不到REFERER URL
    使用JavaScript的Location.href或者是Location.replace()

在以下情況下可以獲取HTTP_REFERER值:

    直接用
    form提交的表單(POST或GET)
    src請求(如js的script標簽及html中img標簽的src屬性)

如何偽造HTTP_REFERER

前面提到HTTP_REFERER是可以偽造的,那么在php中,如何偽造HTTP_REFERER呢?有如下三種方法:
首先是接口代碼:

<?php
$HTTP_REFERER = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '';
exit(json_encode(
    array(
        'status' => 'ok',
        'refer' => $HTTP_REFERER
        )
));

    curl
    代碼示例:

<?php

function curl_post($url){
     $ch = curl_init();
     curl_setopt($ch, CURLOPT_URL, $url);
     curl_setopt($ch, CURLOPT_REFERER, 'http://www.google.com');
     $output = curl_exec($ch);
     curl_close($ch);
     return $output;
}


var_dump(curl_post("http://www.c.com/api.php"));

執行結果如下:

偽造成功。

    file_get_contents

    一直沒怎么用過file_get_contents來發送post請求,其實file_get_contents可以發送任何http請求,后期會針對性的整理一篇文章出來。

代碼示例:

$opts = array(
  'http'=>array(
    'method'=>"GET",
    'header'=>"Referer: http://www.google.com"
  )
);

$context = stream_context_create($opts);

// Open the file using the HTTP headers set above
var_dump(file_get_contents('http://www.c.com/api.php', false, $context));

執行結果:

偽造成功

    socket
    代碼示例:

$fp = fsockopen("www.c.com", 80, $errno, $errstr, 30);
if (!$fp) {
    echo "$errstr ($errno)<br />\n";
} else {
    $out = "GET /api.php HTTP/1.1\r\n";
    $out .= "Host: www.c.com\r\n";
    $out .= "Referer: www.google.com\r\n";
    $out .= "Connection: Close\r\n\r\n";
    fwrite($fp, $out);
    while (!feof($fp)) {
        echo fgets($fp, 128);
    }
    fclose($fp);
}

執行結果:

偽造成功。

在做這次測試的時候,第一次執行報錯:Your browser sent a request that this server could not understand.
后來發現是$out = “GET api.php HTTP/1.1\r\n”;中少了’/’,糾結了老半天,暈死
---------------------

原文:https://blog.csdn.net/u011250882/article/details/49679535


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM