8

私は 1 つの PHP Web アプリケーションを開発しています。誰も簡単に機能を壊すことができないように、アプリケーションのセキュリティを強化したいと考えています。

私の問題についての簡単な説明: あるモジュールには、リクエストのソースをチェックしている段階が 1 つあります (このリクエストの送信元)。

現在、HTTP_REFERRER変数を使用しています(phpで利用可能)。この変数の値を 1 つの特定の URL (例: http://www.example.com/test.php ) でチェックしています。完全一致が存在する場合は、私だけがさらなるアクションを呼び出しています。

上記のアプローチと少し混乱しています.HTTP_REFERRERを使用するか、IPアドレスで確認する必要がありますか(特定のIPアドレスからのものである場合は有効なリクエスト)?

また、セキュリティを提供するためのより良いアプローチも知りたいです。

誰かがアイデアを持っているので、共有してください。

前もって感謝します

4

3 に答える 3

7

Web セキュリティの教訓 #1: ユーザーの入力を決して信用しないでください。そして、私が決して言うとき、私は決して意味しません。;) PHP に HTTP_REFER 変数を含めると、http ヘッダーで簡単に侵害されます (ソース: http://www.mustap.com/phpzone_post_62_how-to-bypass-the-referer-se )

ソースを確認する際に考えられる解決策は、フォーム トークン (csrf 保護) を使用することです。いずれかであり、独自のソースでのみ可能です。

シンプルな CSRF (クロスサイト リクエスト フォージェリ) 保護の例: (したがって、シンプルです。より安全で堅牢なソリューションについては、The Rook の回答を参照してください)

1) フォーム ページで、ある種のトークンを作成し、セッションと非表示のフォーム フィールドに配置します。

<?php
    session_start();
    $csrfToken = md5(uniqid(mt_rand(),true)); // Token generation updated, as suggested by The Rook. Thanks!

    $_SESSION['csrfToken'] = $token;
?>
<form action="formHandler.php">
   <input type="hidden" name="csrfKey" value="<?php echo $csrfToken ?>" />
</form>

2) フォーム ハンドラーで、トークンが有効かどうかを確認します。

<?php
   session_start();
   if($_POST['csrfKey'] != $_SESSION['csrfKey']) {
      die("Unauthorized source!");
   }
?>
于 2010-06-28T13:17:18.417 に答える
3

CSRF をチェックするHTTP_REFERRERことは、保護の有効な形式です。自分のブラウザでこの HTTP ヘッダーをスプーフィングするのは簡単ですが、 CSRFを使用して別の人のブラウザでスプーフィングすることはルールに違反するため不可能です

国土安全保障省によると、私はこれまでに発見された中で最も危険な CSRF 脆弱性を発見し、史上最も危険な脆弱性トップ 1,000 に入っています。Motorola は、リファラー チェックを使用してこの欠陥にパッチを当てました。メモリが不足しているため、組み込みネットワーク ハードウェアでこの保護方法がよく見られます。

より一般的で安全な方法は、Cryptographic nonceを変数内に格納し、$_SESSION機密性の高い要求ごとにこれをチェックすることです。簡単な方法はPOST、すべての機密要求 (パスワードの変更など) に使用し、この暗号ナンスが php ヘッダー ファイル内のすべての投稿に対して有効であることを確認することですunset($_POST);。この方法が機能するのは、攻撃者がブラウザに強制的に GET/POST リクエストを送信させることはできますが、RESPONSE を表示できず、リクエストを偽造するために必要なこのトークンを読み取ることができないためです。このトークンは XSS で取得できるため、必ずxss についてサイトをテストしてください

csrf トークンを生成するための適切な方法は、md5(uniqid(mt_rand(),true)); CSRF を停止するのに十分なエントロピーである必要があります。md5() は、salt の生成方法をあいまいにするために使用されます。現在の時刻は秘密ではないことに注意してください。攻撃者は、CSRF リクエストが生成された時刻を正確に知っており、セッションが作成された時刻を絞り込むことができます。攻撃者は多くの推測を行うことができると想定する必要があります。実際には、これはページに一連の iframe を書き込むことで簡単に達成できます。

于 2010-06-28T17:56:03.137 に答える
2

Treur は正しく理解しましたが、いくつかのことを明確にし、参照資料のソースを提供したいと思います。Treur が言ったように、ブラウザーによって送信されたすべてのヘッダーを含むユーザー入力データを決して信頼しないでください。

あなたが説明しているのは、典型的なクロスサイト リクエスト フォージェリ攻撃です。RFC2616 ( Hyper Text Transfer Protocol 1.1 ) によると、リファラー ヘッダーはオプションであり、ブラウザーによっていつでも省略される可能性があるため、リファラーヘッダーのチェックは CSRF 攻撃に対する有効な保護ではありません。SSL を使用している場合、リファラー ヘッダーは常にブラウザーによって省略されます。第二に、これはユーザー定義の値であるため、信頼すべきではありません。

CSRF 攻撃に対する推奨される保護は、同期されたトークン パターンを使用することです。これは、非表示フィールドとしてフォームに埋め込まれたシークレット トークンを作成する必要があることを意味します。フォームが投稿されたら、シークレット トークンが存在し、有効であることを確認します。セキュリティ トークンを作成する方法は複数あります。トークンを作成する 1 つの方法について説明します。

アプリケーションのアクションごとに、一意のアクション名を作成します。たとえば、「delete_user」、「add_user」、「save_user_profile」などです。あなたが記述したフォームに「foobar」というアクション名があるとしましょう。アクション名をユーザーのセッション ID およびシークレット値と連結します。

$stringValue = "foobar" . "secret value" . session_id();

セキュリティ トークンを作成するには、連結された文字列のハッシュを作成します。sha1 を使用してハッシュを作成できます。ブルート フォース攻撃のリスクを軽減するには、ハッシュでより大きなキー (sha 512 など) を使用します。

$secretToken = hash("sha5125", $stringValue);

このトークンをフォームの非表示フィールドに設定します。フォームが送信されたら、トークンを再作成し、フォームで送信されたものと一致することを確認します。このトークンは、1 つのユーザー セッションに対して有効です。リクエストごとにトークンが再生成されるわけではないため、攻撃者がトークンを再利用できる機会があると主張する人もいるかもしれません。ただし、適切なセッション管理戦略があれば、これはあまり問題になりません。

私が言ったように、適切なセッション管理が必要です。これは、セッションを長時間存続させてはならないことを意味します。特にセッション固定の脆弱性は、攻撃者がユーザー セッションを制御し、秘密トークンを「予測」できるため、CSRF 保護手段を無効にします。

以下に、一読することをお勧めするリンクをいくつか示します。

于 2010-07-09T07:39:59.587 に答える