3

サイトとユーザーをクロス サイト フォージェリ (CSRF) 攻撃から保護したい場合は、フォームのあるすべてのページ$token = md5( time() * rand );で一意のトークンを生成できます。トークンは非表示の入力フィールドに送信され、同時にセッション変数に保存されます。echo '<input type="hidden" name="token" value="'.$token.'">';$_SESSION['token'] = $token;

提出されたフォームに記載されているかどうかを確認し、if($_POST['token'] == $_SESSION['token'])それに応じて処理を進めます。

ただし、一部のユーザーはマルチタスクを行う場合があります。これは、これを投稿している間、私が実際に行っていることです。

投稿を作成している間、さまざまなウィンドウ/タブを開いて、情報を調査したり、スタック オーバーフローに関する他の質問を調べたりします。スタック オーバーフローにより、問題なくフォームを送信できます。

しかし、自分のサイトでこれを行うと、投稿/フォームを作成しながら他のページを閲覧することを意味$tokenし、自分のウェブサイトから別のページをプルアップするたびに再生成されます. input私が取り組んでいるフォームで非表示のトークンを作成し、別のページにアクセスしたときに再生成された変数と一致しなくなるため、最終的に間違った を送信したい...$_SESSION['token']

この問題を防ぐ方法、または CSRF を最初に停止するためのより良い解決策はありますか?

ユーザーにマルチタスクを許可し、CSRF から保護したい...

4

2 に答える 2

4

単一のCSRFのためにあなたが述べたことと同じ問題があり、最新のページを送信しない限り置き換えられますが、セッション付きの配列を使用すると問題が解決するはずです。また、キャプチャを含めることもできます。Google の Recaptcha をお勧めします。

session_start();
function createToken(){
    $token = sha1(uniqid(mt_rand(), true));
    $_SESSION['Tokens']['Token'][] = $token;
    $_SESSION['Tokens']['Time'][] = time() + (10 * 60); #10 min limit
    #you can omit/change this if you want to not limit or extend time limit
    return $token;
}

function checkToken($token){
    clearTokens();
    foreach($_SESSION['Tokens']['Token'] as $key => $value){
        if($value === $token){
            return true;
        }
    }
    return false;
}

function clearTokens(){
    foreach($_SESSION['Tokens']['Time'] as $key => $value){
        if($value <= time()){
            unset($_SESSION['Tokens']['Token'][$key], $_SESSION['Tokens']['Time'][$key]);
            #remove last parameter if you aren't using token time limit
        }
    }
}

あなたのHTML:

<input type="hidden" name="token" value="<?php createToken(); ?>">

PHP トークン チェッカー

if(isset($_POST['token']) && checkToken($_POST['token'])){
    #valid token
}else{
    #create error message saying that they tried to repost data or session token expired
}
于 2013-08-14T18:04:47.423 に答える