現在、JavaScript/HTMLフロントエンドを備えた単一ページのアプリケーションを構築しています。フロントエンドは、.NETで記述されたWEB APIを呼び出します。現在、ユーザーが自分の資格情報を入力してログインをクリックするHTMLページがあります。 AJAXリクエストは、ユーザーを認証し、Json Webトークンを含むHTTP専用Cookieを返すWEB APIに送信されます。ブラウザは、後続の各リクエストでこのCookieを送信し、コントローラはそれを検証します。
上記はうまく機能していますが、CSRF保護が欠如しています。私はこれを実装する最良の方法を理解しようとしています。私の調査から、いくつかのオプションがあるようです。
https://www.jamesward.com/2013/05/13/securing-single-page-apps-and-rest-services の記事では、Cookieからトークンを抽出して送信することを提案していますリクエストヘッダーとして。これを行うには、JavaScriptがCookieにアクセスできるように、HTTPのみのフラグをドロップする必要があります。 XSSの脆弱性が見つかった場合にセッション情報が公開される可能性があるため、これは最良の解決策ではないと思います。何か足りないものはありますか?
別の場所で、CSRFトークンを含む別のCookieを送信し、JavaScriptを使用して値をプルする方法について読みました。その後、後続のAJAX=リクエストでカスタムヘッダーとしてその値を送信し、そのヘッダーに基づいてWEB APIを検証させます。このための簡単な概念実証アプリケーションを作成し、ブラウザーが引き続き送信することを発見しましたCSRFトークンが将来の要求で配信されたCookieこれは問題を引き起こしますか?CSRF攻撃のあるページが何らかの形でこれを悪用する可能性はありますか?
上記と同様ですが、CSRFトークンをCookie経由で配信するのではなく、カスタムヘッダー経由で配信し、JavaScriptにそこから読み取らせます。これは最も簡単なようですが、このアプローチには欠点がありますか?
また、ユーザーのセッション全体で単一のCSRFトークンを使い続けることは安全ですか、それともすべてのリクエストで更新する必要がありますか?
従来のCSRFトークン戦略を使用できますが、AJAXベースのアプリケーションで使用するには厄介な作業が必要になる可能性があり、AJAX固有のエンドポイントではより簡単なオプションを使用できます。
「X-Requested-With:XMLHttpRequest」や「X-Is-Local-XHR:true」のように、サーバーへのリクエストに追加のヘッダーを追加し、サーバーが認証済みリクエストでヘッダーを要求するようにします。古いバージョンのFlashを使用しているユーザーは脆弱である可能性があります(古いバージョンのFlashの脆弱性も非常に悪かったため、これが重要かどうかの選択)。 https://stackoverflow.com/questions/17478731/whats-the-point-of-the-x-requested-with-header を参照してください
OriginヘッダーまたはRefererヘッダーが設定され、Hostヘッダーのドメインと一致することを確認します。 Originヘッダーは、すべてのPOSTリクエストに対してChromeおよびFirefoxによって送信されますが、古いブラウザーには含まれていない可能性があります。Refererヘッダーはプライバシー上の理由により一部のユーザーによって無効にされています。有効な値のいずれかが存在することで、リクエストを確認できます。
これは古いトピックであり、議論が散らばっています(Security.SEを含む)。ただし、CookieおよびポストバックベースのCSRF保護スキームをエミュレートするという一般的な提案の代わりに、Cookieを完全に廃止することをお勧めします。
1ページのアプリを実際のアプリのように扱い、標準の方法を使用してWeb APIに対して認証します。たとえば、OAuthトークンとセッションレスリクエストを使用できます。OAuthの設定が難しすぎる場合は、カスタムトークンスキームを使用できます。)
これにより、CORSの問題も解決されます。