web-dev-qa-db-ja.com

DjangoでCSRFを防ぐためにリファラーチェックが必要なのはなぜですか?

今日、私はDjangoのCSRF保護が非表示のフォームフィールドをCookieに対してチェックすることに加えて、refer(r)erヘッダーチェックを使用することを学びました。以下のドキュメントと問題から判断すると、重要なようです。

ただし、これはHTTPSでのみチェックされます。他のウェブサイトがリファラーをチェックしていないことにも気づきました。

だから私は2つの質問があります:

  1. このチェックなしで可能な攻撃はどのように機能しますか?中間者攻撃に対してhttps protect を行わないのですか?
  2. 他のウェブサイトはどのようにそれを防ぎますか?また、Djangoはhttpに投影されませんか?

私が見つけた情報:

https://docs.djangoproject.com/en/1.8/ref/csrf/#how-it-works

さらに、HTTPSリクエストの場合、厳密なリファラーチェックはCsrfViewMiddlewareによって行われます。これは、HTTPのSet-Cookieヘッダーが(残念ながら)クライアントと通信しているクライアントによって受け入れられるため、セッションに依存しないnonceを使用している場合にHTTPSで可能な中間者攻撃に対処するために必要です。 HTTPSの下のサイト。 (Refererヘッダーの存在はHTTPで十分に信頼できないため、HTTPリクエストの場合は、Refererチェックは行われません。)

https://code.djangoproject.com/ticket/1687

残念ながら、このチェックはDjangoのCSRF保護のセキュリティのために絶対に必要です。これがないと、SSLサイトへの中間者攻撃を防ぐことができません。私たちは、プライバシーを向上させない方法でヘッダーをブロックする少数のユーザーにとっては、サイトを壊すよりもMITMを防ぐ方が価値のあるトレードオフであると決定しました。

14
Mark

まず、興味深い質問に感謝します。 CSRFの詳細については以前は知りませんでした。自分で質問の答えを自分で調べなければなりませんでしたが、今ではDjangoの動作の正しい説明を知っていると思います。

Django=開発者はHTTPとHTTPSの扱いが異なります。これは、ユーザーが安全でないWebサービスとは異なるものを期待しているためです。より具体的には、Webページがトランスポート層セキュリティを使用している場合、ユーザーは中間者攻撃。つまり、誰かがリモートサーバーとリモートサーバーの間に直接座り、すべてのメッセージを傍受したとしても、その情報を利用することはできないという原則を信頼します。これは予期されていないことに注意してください。プレーンHTTP接続の。

Django開発者の投稿 here から引用した次のシナリオを考えてみましょう:

  • ユーザーが閲覧する http://example.com/
  • mITMは、返されるページを変更します。つまり、POST対象のフォーム https://example.com/detonate-bomb/ になります。MITMはCSRFトークンを含めることはできますが、CSRFトークンを発明し、一致するCSRF Coo​​kieを送信できるため、問題はありません。
  • POSTフォームは、ユーザーのブラウザからJavaScriptによって送信され、それにはCSRF Coo​​kie、一致するCSRFトークン、およびユーザーのセッションCookieが含まれるため、受け入れられます。

私はこの攻撃をすぐに理解できなかったので、詳細を説明しようと思います。最初に、プレーン接続を介してフォームを表示するが、SSL/TLSを介してデータを送信するページを見ていることに注意してください。私が理解しているように、問題の一部は、Cookieと隠しフォームの値(別名「CSRFトークン」)が互いに比較されるだけで、サーバー側に保存されている値とは比較されないことです。これにより、攻撃者はサーバーに受け入れられるcookie-token-combinationを被害者に簡単に提供できます-フォームを表示するページは保護されていないため、Set-Cookieヘッダーとフォームのコンテンツそれ自体が偽装される可能性があります。操作されたフォームが(たとえば、挿入されたJSを介して)送信されると、サーバーは完全に有効な要求を確認します。

厳密なRefererチェックを追加することが、この正確な問題への答えです。これらのヘッダーをチェックすると、https://example.comから送信されたリクエストのみがhttps://example.comの別のエンドポイントで受け入れられます。同じドメインの安全でないページは、完全に信頼されていないものとして扱われます。

ここで、プレーンなHTTPリクエストが異なる方法で処理される理由に戻るために、暗号化をまったく使用しないサイトを想像する必要があります。その場合、真ん中の男が実際のフォームデータと共に送信されたRefererヘッダーを偽装する可能性があるため、これらのヘッダーをチェックしてもセキュリティは向上しません。言い換えると、中間者によるCSRF攻撃に対する保護はありません。しかし、前述したように、ユーザーはプレーンなHTTPサイトからこの種のセキュリティを期待していません。

他のWebフレームワークがこの攻撃ベクトルをどのように処理するかについてのあなたの質問に関して、正直に言って私は知らないと言わなければなりません。

12
zinfandel

この質問をして以来、私が見つけたものを簡単に要約します。

Webサイトへのユーザーの最初のリクエストは、(サーバー側から)httpsであるとは限りません。攻撃者はこのリクエストを使用して、特定のCSRF Coo​​kieを設定する可能性があります。次に、これを使用して、ユーザーの代わりに、コントロール外のhttpドメインからクロスサイトリクエストを実行できます。これは、参照元チェックが妨げるものです。

頭に浮かぶかもしれない解決策は、認証されたセッションを開始するときにCSRFトークンをリセットすることです。その後、攻撃者は匿名サービスへの偽の要求のみを行うことができますが、これはほとんどメリットがありません(自分で直接行うことはできますが、結局は匿名です)。

これに伴う問題は、パスワードを必要とするにもかかわらず、ログインフォーム自体もCSRFに対して脆弱であることです。攻撃者は その場合 の場合、ユーザーのセッションを引き継ぐのではなく、ユーザーを攻撃者のセッションにログインさせます。その後、攻撃者はユーザーが行ったまたは入力した内容を見ることができる可能性があります。

HSTSがオンになっていて、ログイン時にCSRFトークンを変更すると想定して、オフにできると思われるまれなケース:

  • 次のいずれかを行うログインプロセスがあります。

    • CSRFトークンを最初のページの後に変更して、自動化できないように2つのページを巻き込みます(X-Frame-Optionsも設定)。例えば。 2要素認証、または手動の[OK]ボタンのある2番目のページのみが必要でした。
    • ログインページには、偽のリクエストから保護するCAPTCHAがあります。
    • ユーザーが私たちの特定のサービスに間違ったアカウントを使用するようにだまされることはありません(たとえば、ユーザーには明らかな方法で高度にパーソナライズされていますが、攻撃者は検出できません)。
  • 最初のリクエストはhttpsを介して行われます。このページは、通常のブラウザではなく、アプリまたはソフトウェアからのみアクセスすることを想定しています。

  • ブラウザは、Cookieがhttps専用であるか、https接続で設定されたかを確認する方法を実装しています(攻撃者はhttp経由で使用可能なCookieを設定できませんでした)。しかし、それは現時点では不可能であり、私たちの管理外です。

(CSRFトークンを秘密の方法でセッション依存にし、サーバー側に保存しても、これは修正されません。攻撃者はCSRFトークンを上書きまたは生成することはできませんが、CSRFトークンを開くことでサーバーに要求することができます。彼が選択したセッションを使用してフォーム)。

1
Mark