私は、CSRF攻撃に対する2つの主要な解決策があることを知っています。セッションあたりの複数のブラウザタブでPHPの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
}
アプリが2つのタブを開く必要がある場合は、ログインごとに1つのCSRFトークンを行います。そうでない場合は、複数のタブを開いてはいけません。また、トークンを設定するのは、フォームをこのように表示すると、非フォームベースのページに対して複数のタブを持つことができます。 –
いいですね。欠落しているのは、未使用の古いトークンをパージする戦略、および/またはユーザーあたりの有効なトークンの量の制限です。 – jh1711
トークンの量を制限する必要があります。そうしないと、攻撃者はトークンを使用してセッションを完了できません。また、セッションのサイズはPHPスクリプトのメモリ制限によって制限されるため、複数のアカウントでサーバーをDoSする可能性があります。 – Jarzon