web-dev-qa-db-ja.com

CSRF Coo​​kieはHttpOnlyである必要がありますか?

最近、以下を含むセキュリティレポートが渡されました。

HttpOnlyフラグが設定されていないCookie

内部アプリケーションの1つに明らかに見られた脆弱性。

適用された修正は、Djangoの CSRF_COOKIE_HTTPONLY構成パラメーター からTrueへ。

しかし、これが私を混乱させたものです。 Djangoドキュメントは言う:

CSRFはクロスドメイン攻撃から保護するためだけなので、CSRFをHttpOnlyとして指定しても実用的な保護は提供されません。攻撃者がCookieを読み取ることができる場合JavaScriptを使用すると、ブラウザが知る限り、それらはすでに同じドメイン上にあるため、とにかく好きなことを何でも実行できます。 (XSSはCSRFよりもはるかに大きな穴です。)

この設定では実用的なメリットはほとんどありませんが、セキュリティ監査人が必要とする場合があります。

これは、ここに実際の脆弱性はなく、セキュリティ監査ルールに準拠する必要があることを意味しますか?

59
alecxe

ジョーが言う のように、これには実際のセキュリティ上の利点はありません。純正のセキュリティシアターです。私はこれを ドキュメント から強調したいと思います:

これを有効にし、AJAXリクエストでCSRFトークンの値を送信する必要がある場合、JavaScriptはCookieからではなく、ページ上の非表示のCSRFトークンフォーム入力から値をプルする必要があります。

HttpOnlyフラグの目的は、Cookieの値をJavaScriptから利用できないようにすることです。これにより、XSSの脆弱性が存在しても盗まれないようにすることができます。しかし、CSRFトークンはどういうわけか利用可能でなければならないので、二重に提出することができます-それが結局のところそれで全体のポイントです。したがって、Djangoは、非表示のフォームフィールドに値を含めることでこれを解決します。これにより、攻撃者はCookieの代わりにフォームフィールドの値を読み取ることができるため、HttpOnlyの利点全体が無効になります。

67
Anders

それは正しいです。これは誤検出であり、この発見をあなたに提供した人は、残念ながら彼らが何をしているかを理解していません。 mitmおよびcsrf攻撃のリスクを理解している人は、これを決して提供しません。

10
joe

ここでの混乱の主なポイントは、Django docsが特にについて話しているということです)[〜#〜] csrf [〜#〜] Cookieの使用例httpOnlyフラグがCSRFの防止に値を追加しない理由を理解するには、CSRFとCookieのしくみの両方を理解する必要があります。

CSRFとは、サードパーティがユーザーのブラウザーをトリガーしてサーバーにリクエストを送信し、ユーザーのブラウザーがサーバーのCookieをリクエストとともに自動的に送信するときです。サーバーがこのリクエストを実際にユーザーからのリクエストであると解釈しないようにするため、 CSRF mitigation テクニックを使用します。 CSRF軽減策の要点はリクエストが自分のドメイン(つまり、ユーザーがアプリケーションとやり取りしているドメイン)からのものでない場合にそれを検出できることです

簡単に言うと、Cookieの仕組み:ユーザーのブラウザがドメイン/サーバーにリクエストを送信すると、httpOnlyフラグに関係なく、ドメインに関連付けられたすべてのCookieが自動的に送信されます。したがって、Cookieを使用すると、クライアントまたはサーバーがユーザーのブラウザに情報を添付できるようになります。この情報は、後続の要求とと​​もに自動的にサーバーに返されます。 httpOnlyフラグが設定されたCookieは、JavaScriptからアクセスできません。それらはおそらく情報を保存するための安全な場所と考えるべきではありませんが、アドバタイズされた機能を提供します。

Cookieを使用して実装されたCSRFに戻る—この場合httpOnlyフラグは無意味です— CSRFの要点は、彼らがそうしていないことですユーザーのCookieを読み取る必要があります。ユーザーのブラウザに、関連するCookieをサーバーに送信するように要求するだけでなく、強制的に送信したネットワークリクエストもサーバーに送信します。一般にhttpOnlyフラグは、これらのCookieへのクライアントアクセスを防止するという点で価値を提供します。サーバーがCookieを返す場合は、おそらくhttpOnlyにする必要があります。 CSRFにCookieを使用している場合は、それを行うべきではなく、httpOnly Cookieにするのではなく、再考することに時間を費やす必要があります。したがって、一般的には、これは良い経験則のようです。クライアントのJavaScriptからのアクセスを特に意図していない限り、サーバーはhttpOnly以外のCookieを送信しないでください。

5
colllin

二重送信によるCSRF防止が機能する唯一の方法は、Cookieでナンスを送信することです。これをHTTP応答本文で送信すると、クロスドメインリクエストを送信するスクリプトによって解析される場合があります(そのページにCORSを許可している場合)。これは、CSRFに対する保護の目的全体を無効にします。ドメインXのスクリプトはドメインYのCookieの値を取得できないという考えです。これは、Webのセキュリティの主要な柱の1つです。

HTTPOnly Cookieを使用すると、最も一般的な方法、つまり、Cookieを介してナンスとCookieを読み取ることができるページ上のスクリプトを二重送信することを使用して、CSRFから保護することができなくなります。そのテクニックの仕組みを次に示します。

1)セッションのためにサーバーに保存するnonce値を生成します。これは、セッションID自体、またはセッションに関連付けられたデータに格納されているものです。

2)これをcookieヘッダーなし HTTPOnlyを介してクライアントに送信し、JavaScriptで取得して保存します(例:短期またはsessionStorage内)

3)CSRFから保護するすべてのリクエストでこれを送信します。リクエストでは、cookieにsessionIdが含まれ、リクエストボディまたはURLクエリ文字列にこのナンスが含まれます(GETリクエストの場合など)。ログなどでナンスが巻き上がるのが心配な場合は、代わりに Web Cryptoを使用して、このナンスを使用してHMACで要求ペイロードに署名する

4)サーバーはセッションデータを検索し、ナンスが一致しないかどうかを確認し、エラーをスローし、別のナンスを生成してCookieで送信します。 nonceは必ずcookieでのみ送信してください。

残念ながら、多くの「セキュリティ監査」ツールは、httpOnlyでマークされていないCookieにフラグを付け始め、このフラグを追加することを推奨しています。このフラグは役に立たないよりも悲しいことに、セキュリティシアターです。

私はhttpOnlyフラグについてのみ話しています。実際には同じクラスの攻撃が依然として発生する可能性があるのに、ある種の弾丸をかわしたと思わせるため、役に立たないよりも悪いです。攻撃者はCookieをサーバーに送信するスクリプトを作成する必要があるため、攻撃者もこのスクリプトは、承認されたセッションのコンテキストで実際の要求を実行します。Cookieがある場合と同じように実行されます。彼らは事前に脚本を書いていた。攻撃者が最終的にCookieを送信するスクリプトをアクティブにしたため、実際の攻撃者が午前3時にリクエストを作成することはありません。はるかに可能性が高いのは、そのスクリプトが、実行する必要があることを実行するように事前にプログラムされていることです。また、httpOnly Cookieが存在しない場合、人々はJavascript出力をサニタイズしてXSSを防止することをより重視します。これは、この攻撃を防止する唯一の正しい方法です。

3

CSRFはクロスドメイン攻撃からの保護のみであるため、CSRF Coo​​kieをHttpOnlyとして指定しても、実用的な保護は提供されません。

これは、より一般的な方法で規定することができ、「CSRF cookie」の技術的な側面を削除することで、より簡単な方法で規定することができます。

定義上、CookieをHttpOnlyとして指定すると、document.cookieまたは同等のJSメソッドを介したアクセスのみが保護されます。 JSコードによって引き起こされた可能性のあるHTTP相互作用を妨げるものではありません。 フォームの送信など、ユーザーがHTML要素を介して行うすべての対話は、JSによって開始できます。何かが開始された方法に意味のある区別はありません。実際、ユーザーが現在のWebページのURL、または現在のWebページにリンクしているWebページのURLを入力することをポイントすることで、「ユーザーが開始した」と主張できます。

これが、「ビデオの自動再生」の概念が十分に定義されておらず、確実に防止できない理由でもあります。ビデオを開始するための自発的なユーザーアクションの構成要素は、DOM(ドキュメントオブジェクトモデル)ではなく、ユーザーインターフェイスの概念です。概念。ユーザーが移動する前にビデオが開始する(「下にスクロールするスペース」など)までビデオが開始しない限り、ブラウザーはユーザーからの自動再生がビデオを再生するジェスチャーを行ったことを認識しません。 (いくつかのケースでは、「もぐらくする」自動再生を試みることができます。たとえば、迷惑なWeb広告を「ぶつかる」(検出、ブラックリスト)、またはサードパーティのドメインと情報を共有することができますが、カバレッジは保証されません。 。)

ドメインでJSが完全に無効にされていない限り、Webサイトによって制御されるフレーム内のユーザーアクションは、Webサイトのスクリプトによって実行可能であると単純に見なされます。ほとんどのドメインでJSを完全にオフにしている最近のWebの1つですか?ほとんど誰もいない。

したがって、一般化された観測は次のとおりです。

CookieをHttpOnlyとして指定しても、ユーザーがWebサイトのインターフェイスを介して実行する可能性のあるアクションを実行する攻撃に対する実際的な保護は提供されません。

すべてのCookie(HttpOnlyとマークされたものを含む)の読み取りは、Webサイトのインターフェースでは行われず、ブラウザーのインスペクターツールまたはHTTP経由で送信されるCookieのHTTPプロキシーでのみ実行できることに注意してください。

3
curiousguy

httpOnly属性は、DjangoのCSRF防止Cookieから省略できます。これは、他の多くの回答、さらには質問が強調表示されているため、JavaScriptのコードが、不正なブラウザをロードした被害者のブラウザで実行されているためです。同一オリジンポリシーにより、オリジンは、属性の有無にかかわらず、許可されたオリジンから認証済み応答を読み取ることができません。

(セッションCookieの要件とアンチCSRF Coo​​kieの要件を混在させないでください)。

Djangoは、開発者がHTMLフォームにXSRF-TOKEN Cookieに関連する(または同じ)アンチCSRFトークンを入力することを期待しています。

https://github.com/Django/django/blob/f283ffaa84ef0a558eb466b8fc3fae7e6fbb547c/Django/middleware/csrf.py#L136

Django作成者は、Secure属性(セッションCookieと反CSRFの両方に適用されます)の必要性を規定するように十分に注意しています。 Strict-Transport-Securityレスポンスヘッダーを追加して、ブラウザにhttp://リンクを挿入させ、暗号化されていないトラフィックを書き換えて、Cookieの挿入やインタラクション全体の盗聴を回避する必要があります。

フレームワークの作成者はhttpOnly属性について厳密ではありません。これは、同じオリジンポリシーのおかげで、許可されていないオリジンがブラウザ用に生成するJavaScriptコードを介してCookieを読み取ることができないためです。承認されたOriginからフォームの詳細と応答ヘッダーを取得しようとするサーバー側スクリプトは、認証されていない応答のみを受け取ります。

シングルページアプリケーションの唯一のソースとして使用する場合、XSRF-TOKEN Cookieに対してhttpOnlyを許可しないという厳しい要件に遭遇しました。 XSRF-TOKEN応答Cookieに依存するSPAは引き続き安全です。許可されていないオリジンも、同じオリジンポリシーのため、適切なXSRF-TOKENレスポンスCookieを読み取ることができません。また、許可されていないサーバー側スクリプトは、適切なXSRF-TOKEN応答Cookieをプリフェッチできません(これも、スクリプトが許可されたサーバーとの認証を欠いているためです)。

https://github.com/expressjs/csurf#single-page-application-spa

2
eel ghEEz

CSRFトークンは、CSRFで保護されたフォームのあるページではシークレットではありませんが(XSSを使用して盗まれる可能性があります)、フォームのないページにXSSの脆弱性がある可能性があります。そこでは、Cookieからのみトークンを取得できますが、非表示フィールドからは取得できません。この場合、HttpOnly Cookieを使用することでセキュリティが向上します。

JavaScriptを介してフォームを含むページをリクエストしてトークンを取得する方法はまだあります。これを防ぐ方法はありますが、ほとんどのサイトではこの攻撃が可能です。

1
allo