17

ここ数日で CSRF 攻撃を防ぐ方法について読みました。ページロードごとにトークンを更新し、トークンをセッションに保存し、フォームを送信するときにチェックを行います。

しかし、ユーザーが自分の Web サイトで 3 つのタブを開いて、セッションの最後のトークンを保存したとしたらどうなるでしょうか? これにより、トークンが別のトークンで上書きされ、一部の事後アクションが失敗します。

セッションにすべてのトークンを保存する必要がありますか、それともこれを機能させるためのより良い解決策はありますか?

4

2 に答える 2

30

はい、格納されたトークンのアプローチでは、生成されたすべてのトークンを、いつでも戻ってきた場合に備えて保持する必要があります。複数のブラウザー タブ/ウィンドウだけでなく、前後のナビゲーションでも、1 つの格納されたトークンが失敗します。一般に、古いトークンを期限切れにすることで、潜在的なストレージの爆発を管理する必要があります (それ以降に発行されたトークンの年齢および/または数によって)。

トークンの保存を完全に回避する別のアプローチは、サーバー側のシークレットを使用して生成された署名付きトークンを発行することです。その後、トークンが戻ってきたら、署名を確認できます。一致する場合は、署名したことがわかります。例えば:

// Only the server knows this string. Make it up randomly and keep it in deployment-specific
// settings, in an include file safely outside the webroot
//
$secret= 'qw9pDr$wEyq%^ynrUi2cNi3';

...

// Issue a signed token
//
$token= dechex(mt_rand());
$hash= hash_hmac('sha1', $token, $secret);
$signed= $token.'-'.$hash;

<input type="hidden" name="formkey" value="<?php echo htmlspecialchars($signed); ?>">

...

// Check a token was signed by us, on the way back in
//
$isok= FALSE;
$parts= explode('-', $_POST['formkey']);
if (count($parts)===2) {
    list($token, $hash)= $parts;
    if ($hash===hash_hmac('sha1', $token, $secret))
        $isok= TRUE;
}

これにより、署名が一致するトークンを取得した場合、それを生成したことがわかります。それ自体はあまり役に立ちませんが、ユーザーIDなど、ランダム性以外の追加のものをトークンに入れることができます。

$token= dechex($user->id).'.'.dechex(mt_rand())

...

    if ($hash===hash_hmac('sha1', $token, $secret)) {
        $userid= hexdec(explode('.', $token)[0]);
        if ($userid===$user->id)
            $isok= TRUE

現在、各フォームの送信は、フォームを取得した同じユーザーによって承認される必要があり、CSRF をほぼ無効にします。

トークンに入れることをお勧めするもう 1 つのことは、有効期限です。これにより、一時的なクライアントの侵害や MitM 攻撃によって、そのユーザーに対して永久に機能するトークンと、パスワードのリセット時に変更される値がリークされなくなります。パスワードを変更すると既存のトークンが無効になるようにします。

于 2010-04-22T23:45:42.000 に答える
1

現在のセッションまたはユーザーに対しても永続的であり (ユーザーのパスワードのハッシュのハッシュなど)、第三者によって決定できないトークンを単純に使用できます (たとえば、ユーザーの IP のハッシュを使用するのは良くありません)。 .

そうすれば、おそらく大量の生成されたトークンを保存する必要がなくなり、セッションの有効期限が切れない限り (おそらくユーザーは再度ログインする必要があります)、ユーザーは好きなだけタブを使用できます。

于 2011-01-30T10:30:57.667 に答える