簡體   English   中英

在PHP中針對多個瀏覽器選項卡防御CSRF攻擊

[英]Protect against CSRF attack in PHP for multiple browser tabs

我知道,針對CSRF攻擊有兩種主要解決方案。

  • 每個會話一個令牌
  • 所有獨特形式的代幣

我選擇了第二個,但是有一個問題。 如果訪問者在兩個選項卡中打開一個表單,則第二個選項卡上的表單標記將覆蓋之前的標記。 我寫了一個代碼來解決這個問題。 我的問題是:這是一個好的解決方案,還是我必須努力解決? (示例中只有最重要的部分。)

##### CONFIG & FUNCTION.PHP #####
// INITIALIZING - RUN ONLY ONCE
$_SESSION["csrf_tokens"]["postcomment"]     = array ();
$_SESSION["csrf_tokens"]["postcommentedit"] = array ();
// etc, etc.
function makearandomtoken ()
{
   // a simple but secure way
   return bin2hex (openssl_random_pseudo_bytes (32));
}

##### POSTCOMMENT_FORM.PHP #####
// new form for comment under a post, so create a new token
$created_token = makearandomtoken ();
array_push ( $_SESSION["csrf_tokens"]["postcomment"], $created_token );
// the form (only with important parts)
print "<form>\n";
print "<input type=\"hidden\" name=\"token\" value=\"$created_token\">\n";
print "</form>\n";

##### POSTCOMMENT_EXECUTE.PHP #####
// get the token from POST variable
$received_token = filter_input (INPUT_POST, 'token', FILTER_UNSAFE_RAW);
// check it
if ( in_array($received_token, $_SESSION["csrf_tokens"]["postcomment"]) )
{
   // VALID token, disable it
   $token_index = array_search($received_token, $_SESSION["csrf_tokens"]["postcomment"]);
   unset ($_SESSION["csrf_tokens"]["postcomment"][$token_index]);
}
else
{
   // INVALID token -> CSRF attempt
   die (); // or do anything
}

如果您希望每個表單實例都使用新的令牌,則我認為您的實現沒有問題。 這兩個選項卡均由用戶合法打開,因此可以接受兩個令牌。

至於CSRF保護,我認為它是完整的。 第三個站點無法在沒有令牌的情況下冒充用戶,並且擁有兩個或三個有效令牌的用戶不會使攻擊者更輕松地完成任務。

如果您對前端進行編碼,則可以將事件處理程序注冊到文檔的onUnload事件中,並使該處理程序發出POST請求,以告知服務器正在卸載哪個令牌。 這樣后端可以從會話中刪除令牌。 這可能比它值得的麻煩多,因為如果用戶單擊瀏覽器的“后退”按鈕,她將重新加載無效的令牌,並且在提交表單時會因錯誤而感到沮喪。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM