web-dev-qa-db-ja.com

Javascript CSRFの脆弱性を回避するために、HTTPGETでMVC3のAntiForgeryTokenを使用する

このHaackedブログに関して 以来、提案されたアンチJSONGETハイジャックソリューションの実装を躊躇しています

  1. JSONハイジャックを軽減するための推奨されるソリューションには、データを取得するための非RESTフルJSONPOSTが含まれます

  2. 別の解決策(オブジェクトの折り返し)は、ソースコードにアクセスできないサードパーティのコントロールで問題を引き起こします。

  3. セキュリティトークンを作成する方法、またはWebページ内で安全に配信する方法について、代替ソリューション(以下にリスト)を実装するコミュニティで精査された実装が見つかりません。また、自分の実装を実行するのに十分な専門家であるとは主張しません。

  4. リファラーヘッダーは信頼できません

背景

このブログ JSONハイジャックに関するCSRFの問題について説明し、JSONPOSTを使用してデータを取得することをお勧めします。 HTTP POSTを使用してデータを取得するのはRESTでいっぱいではないので、セッションごとにRESTアクションを有効にする、よりRESTfullのソリューションを探しています。またはページごと。

もう1つの緩和手法は、JSONデータをオブジェクトにラップすることです ここで説明 。別のテクニックが見つかるまで、これで問題が遅れる可能性があるのではないかと思います。

代替実装

私には、JSONのjQuery HTTP GETで使用を拡張するのは自然なことのようです ASP.NET MVCのAntiForgeryToken

たとえば、上記のHaackedリンクによると、機密データを取得した場合、次のコードは脆弱です。

$.getJSON('[url]', { [parameters] }, function(json) {
    // callback function code
});

推奨されるPOST回避策を使用してデータを取得することはRESTfullではないことに同意します。私の考えはURLで検証トークンを送信することです。そうすれば、CSRFスタイルの攻撃者は完全なURL。キャッシュされているか、キャッシュされていない場合、データを取得できません。

以下は、JSONGETクエリを実行する方法の2つの例です。どの実装が最も効果的かはわかりませんが、最初の実装はこのデータをキャッシュする誤ったプロキシから安全であると推測されるため、攻撃者に対して脆弱になります。

http:// localhost:54607/Home/AdminBalances/ENCODEDTOKEN-TOKEN-HERE

または

http:// localhost:54607/Home/AdminBalances?ENCODEDTOKEN-TOKEN-HERE

...これはMVC3のAntiForgeryToken、またはそのバリアント( swtを参照 )である可能性もあります。このトークンは、上記で選択したURL形式のインライン値として設定されます。

私が自分の解決策を展開するのを妨げるサンプルの質問

  1. JSON GET(スラッシュ、疑問符など)を検証するためにどのURL形式(上記)を使用しますか?プロキシは http:// localhost:54607/Home/AdminBalances with http :// localhost:54607/Home/AdminBalances?ENCODEDTOKEN-TOKEN-HERE データ?

  2. そのエンコードされたトークンをWebページにどのように配信しますか?インライン、またはページ変数として?

  3. トークンをどのように構成しますか? AntiforgeryTokenが組み込まれていますか、それとも他の方法で?

  4. AntiForgeryTokenはCookieを使用します。この場合、バッキングCookieが使用/必要になりますか? HTTPのみ? HTTPのみと組み合わせたSSLはどうですか?

  5. キャッシュヘッダーをどのように設定しますか? Google Web Acceleratorにとって特別なもの(例)

  6. JSONリクエストをSSLにするだけの意味は何ですか?

  7. 安全のために、返されたJSON配列をオブジェクトにラップする必要がありますか?

  8. このソリューションは、Microsoftが提案する テンプレートとデータバインディング 機能とどのように相互運用しますか

上記の質問は、私が前に進んでこれを自分でやらない理由です。言うまでもなく、私が考えもしなかった質問がもっとある可能性がありますが、それでもリスクがあります。

20

Asp.net MVC AntiForgeryTokenは、HTTP POST( " Double Submit Cookies "テクニックを使用)に依存するCookieに依存しているため、HTTPGETでは機能しません。 OWASP XSRF Prevention Cheat Sheet で説明されています。 httponly として設定することで、クライアントに送信されるCookieをさらに保護することもできるため、スクリプトを介してCookieをスプーフィングすることはできません。

このドキュメント では、XSRFを防ぐために使用できるさまざまな手法を見つけることができます。あなたが説明したのはアプローチ1に該当するようです。しかし、Cookieがリクエストとともに送信されないため、Ajax HTTPGETリクエストを使用するときにサーバーでセッションを取得する方法に問題があります。したがって、アクションのURLにセッション識別子を追加する必要もあります(別名、ハイジャックしやすいCookieなしのセッション)。したがって、攻撃を実行するために、攻撃者はGET要求を実行するための正しいURLを知っている必要があるだけです。

おそらく良い解決策は、ユーザーのSSL証明書(たとえば、証明書の拇印)からのキーを使用してセッションデータを保存することです。このようにして、SSL証明書の所有者のみが自分のセッションにアクセスできます。このように、Cookieを使用する必要はなく、クエリ文字列パラメーターを介してセッション識別子を送信する必要もありません。

とにかく、Asp.netMVCでHTTP POST)を使用したくない場合は、独自のXSRF保護を展開する必要があります。

16
m0sa

私はこの問題に遭遇し、解決策はそれほど簡単ではありませんでしたが、これを開始するための素晴らしいブログがあり、これはgetおよびpostajaxで使用できます。

http://johan.driessen.se/posts/Updated-Anti-XSRF-Validation-for-ASP.NET-MVC-4-RC

以下をグローバル名前空間に配置すると、すべての投稿/取得で偽造防止トークンを利用できるため、ajax呼び出しを変更する必要がありません。共通ページに入力要素を作成します。

<form id="__AjaxAntiForgeryForm" action="#" method="post">@Html.AntiForgeryToken()</form>

次のJavaScriptは、偽造防止トークンを読み取り、それをリクエストヘッダーに追加します。

// Wire up the global jQuery ajaxSend event handler.
$(document).ajaxSend(namespace.ajax.globalSendHandler);

// <summary>
// Global handler for all ajax send events.
// </summary>
namespace.ajax.globalSendHandler = function (event, xhr, ajaxOptions) {
    // Add the anti forgery token
    xhr.setRequestHeader('__RequestVerificationToken', $("#__AjaxAntiForgeryForm input[name=__RequestVerificationToken]").val());
};
4
Marko