2011-02-01 72 views
25

我正在製作一個CakePHP系統,因爲我們正在處理金錢,客戶帳戶等問題,所以我們需要保持體面安全。到目前爲止,所有事情都非常好,直到我必須與支付平臺集成我需要重定向到他們的網站,他們重定向回我的。什麼是PHP的session.referer_check保護我免受?

這可以在我的開發機器(調試= 2)中正常工作,但在生產中,當客戶被重定向回來時,他獲得登錄提示而不是登陸回他的「登錄區域」。經過多次挖掘,我發現這是因爲CakePHP設置了session.referer_check,如果HTTP_REFERER來自另一臺主機而不是我的主機,則它會使會話無效。

現在,通常情況下,我會禁用這個沒有第二個想法,但在這個系統中,我比平常更關心安全性。

我的問題是什麼session.referer_check應該保護我?
如果我關閉它,可以對我的網站執行哪種攻擊/利用/壞事?

我在猜測爲什麼存在這個問題應該有一些原因,但我無法想象它會保護我。

你能給我任何想法嗎?
是否安全禁用了此操作?

謝謝
丹尼爾

+0

你是100%它是檢查引用,而不是在先前的請求,以防止CSRF與表格發送令牌? – Pablo 2011-02-01 15:50:14

+0

100%肯定。 CakePHP沒有檢查引用鏈接,它只是打開referer_check(一個檢查引用鏈接本身的PHP功能:http://www.php.net/manual/en/session.configuration.php#ini.session.referer-check ) - 另外,我看到的結果是將人員關閉。當CakePHP不喜歡它獲得的CSRF令牌時(或者它沒有得到它時)做的是「blackholing」(空白頁,基本上) – 2011-02-01 15:57:00

+0

類似的:http://stackoverflow.com/questions/22079477/cakephp -session-is-lost-after-an-oauth-redirect – trante 2014-02-27 21:16:33

回答

22

這是爲Session Fixation和CSRF/XSRF提供有限的保護。檢查引用者是a valid method of stopping xsrf。一種更好的停止會話固定的方法是Session.use_only_cookies,因爲黑客無法爲受控瀏覽器設置他尚未控制的域的cookie。但是,Session.referer_check很容易繞過。它只是在引用域中尋找一個子字符串。如果子字符串一起丟失,如果原始URL爲https://則會發生這種情況,那麼會話ID將無效。但是,由於它的子串而不是一個完整的字符串,那麼你可以通過參考www.somedomain.com.some_hacker.com來繞過www.somedomain.com。所以總之,我覺得這是完全沒用

3

這種方式檢測,可幫助防止Cross-site request forgery引用者。

理想情況下,你會希望有一種方法讓引用者檢查匹配你自己的域名或支付平臺的域名,但因爲它是一個簡單的子字符檢查而不是模式匹配,我不認爲這會是可能。

如果您禁用了此功能,則應採取其他措施以防止此類攻擊。

4

記住,基本上所有的referer_check正在做的是一樣的東西:

$pattern = "/^http:\/\/www\.myurl\.com(\/.*)*$/"; 

if(!empty($_SERVER['HTTP_REFERER']) && !preg_match($pattern, $_SERVER['HTTP_REFERER'])) { 
    session_destroy(); 
} 

這是煩人,建於referer_check PHP的將不接受URL的數組,但你總是可以讓你自己一個人那樣做。因此,對於CakePHP的

,你可以這樣做以下:

// ADD THIS TO /app/config/config.php 
$config['CustomSecurity'] = array(
    'accept_referers' => array(
     'http://www.my_site.com', 
     'https://www.other_allowed_referer.com', 
    ) 
); 

// ADD THIS TO /app/app_controller.php 

private function referer_check(){ 
    if(!empty($_SERVER['HTTP_REFERER'])) { 
     $accept_referers = Configure::read('CustomSecurity.accept_referers'); 
     $referer_accepted = false; 
     foreach($accept_referers as $referer) { 
     $pattern = '/^'.preg_replace('/(\.|\/)/','\\\$1',$referer).'(\/.*)*$/'; 
     if(preg_match($pattern, $_SERVER['HTTP_REFERER'])) 
      $referer_accepted = true; 
     } 
     if(!$referer_accepted) { 
     $this->Session->destroy(); 
     exit; 
     } 
    }   
} 

,並在您app_controller::before_filter功能,來電:

$this->referer_check(); 

...或者類似的東西反正...對不起關於代碼格式化,textarea是一個tard :)