2

このコードが PHP フォームに対する CSRF 攻撃を防ぐのに十分な強度があるかどうかを知りたいですか?

<?php
session_start();
session_regenerate_id(true);

if (isset($_POST['submit'])) {
if (isset($_SESSION['token']) && ($_POST['token'] == $_SESSION['token'])) {
}
}
$token = hash('sha256', uniqid(mt_rand(), true));
$_SESSION['token'] = $token;
?>

//FORM

<form method="POST" action="page.php">
<input type="hidden" name="token" value="<?php echo $token; ?>">
<input type="submit" name="submit">
</form>

ありがとう。

4

3 に答える 3

2

被害者があなたのサイトのフォームをまったく表示していない場合、被害者のセッションにはまだトークンが保存されていません。

攻撃者がトークン フィールドのないフォームを被害者に提示した場合、$_POST['token']$_SESSION['token']が両方とも null になるため、被害者が行った POST リクエストは CSRF チェックに合格します。(または、PHP が不明な変数を初期化する方法に応じて、両方とも空の文字列になります。)

また、トークンがセッションに存在することを確認してから等価性をチェックし、これらのテストのいずれかが失敗した場合は中止する必要があります。

サイトによっては、ユーザーがフォームを見ていない可能性が非常に高い場合や、極端なケースである場合があります。最初にトークンの存在を確認することで、Web サイトにいくつのフォームがあっても、CSRF 攻撃の可能性はありません。

その小さな問題を除けば、CSRF の脆弱性は見当たりません。そのコードは仕事をするように見えます。

于 2013-05-12T00:05:22.770 に答える
1

目的としては十分だと思います。

によって返される値は、uniqid(mt_rand(), true)最大 33 バイトである必要があります。

  • から最大 10 バイトのプレフィックスmt_rand
  • 8 バイトのシステム時間 (秒単位)
  • 5 バイトの現在のマイクロ秒
  • 内部線形合同ジェネレーターからの 10 バイトphp_combined_lcg

ただし、これらの 33 バイトは 264 ビットのエントロピーを提供しませんが、はるかに少ないです。

  • log 2 (2 31mt_rand -1) ≈プレフィックスの 31 ビット
  • システム時刻がわかっている (例: Date応答ヘッダー フィールド)
  • マイクロ秒は 10 6値の 1 つしか持てないため、log 2 (10 6 ) ≈ 20 ビット
  • LCG 値は log 2 (10 9 ) ≒ 30

これは合計すると、約 81 の未知のビットになります。これを強引に実行するには、平均して 2 81 /2 ≈ 1.2・10 24回の推測が必要であり、ハッシュされたときに特定のトークンが得られます。処理するデータは、約 8·10 13 TB になります。現在のコンピューターでは、これを約 5.215・10 17秒で実行できるはずです。

これは、攻撃を実行不可能にするのに十分なはずです。

于 2013-05-12T11:37:04.697 に答える