私はアプリケーション(Django、そういうことが起こります)を書いていて、実際に「CSRFトークン」が何であるか、それがどのようにデータを保護するのかを知りたいだけです。CSRFトークンを使用しない場合、投稿データは安全ではありませんか?
私はアプリケーション(Django、そういうことが起こります)を書いていて、実際に「CSRFトークン」が何であるか、それがどのようにデータを保護するのかを知りたいだけです。CSRFトークンを使用しない場合、投稿データは安全ではありませんか?
回答:
www.mybank.com
mybank.com
結果、フォームが(概念的に)要求されると想定しますhttp://www.mybank.com/transfer?to=<SomeAccountnumber>;amount=<SomeAmount>
。(ログインによって暗示されるため、アカウント番号は必要ありません。)www.cute-cat-pictures.org
ない、それは悪質なサイトであることを知って、。mybank.com
(ある程度の運が必要です!)、次のようなリクエストをページに含めることができますhttp://www.mybank.com/transfer?to=123456;amount=10000
(123456
ケイマン諸島のアカウントの数はそして10000
、あなたが以前あなたが所有して嬉しかったと思っていた金額です)www.cute-cat-pictures.org
ページを、ので、あなたのブラウザはその要求を行います。www.mybank.com
Cookie とともにリクエストを送信し、完全に正当に見えます。あなたのお金があります!これは、CSRFトークンのない世界です。
今より良い1用と CSRFトークン:
http://www.mybank.com/transfer?to=123456;amount=10000;token=31415926535897932384626433832795028841971
。mybank.com
彼らがあなたにそれを提供するとき、彼ら自身のウェブページに含まれるであろう巨大な、推測することができない乱数です。それは異なる、彼らは誰にも任意のページを提供するたびに。www.mybank.com
ます。結果:10000
通貨単位を維持します。その一部をウィキペディアに寄付することをお勧めします。
(あなたのマイレージは異なる場合があります。)
読む価値のあるコメントから編集:
HTTPアクセス制御のため、www.cute-cat-pictures.org
通常のスクリプトは、アンチCSRFトークンにアクセスできないことに注意してくださいwww.mybank.com
。このメモはAccess-Control-Allow-Origin: *
、別のWebサイトからAPIを使用できないという理由だけで、それが何であるかわからないまま、すべてのWebサイト応答のヘッダーを不当に送信する一部の人々にとって重要です。
www.cute-cat-pictures.org
通常のスクリプトは、アンチCSRFトークンにアクセスできないことに注意してくださいwww.mybank.com
。このメモはAccess-Control-Allow-Origin: *
、別のWebサイトからAPIを使用できないという理由だけで、それが何であるかわからないまま、すべてのWebサイト応答のヘッダーを不当に送信する一部の人々にとって重要です。
はい、投稿データは安全です。しかし、そのデータの起源はそうではありません。このようにして、攻撃者のWebページを閲覧しているときに、誰かがJSを持つユーザーをだましてサイトにログインさせることができます。
それを防ぐために、djangoはcookieとフォームデータの両方でランダムなキーを送信します。次に、ユーザーがPOSTを実行すると、2つのキーが同一であるかどうかが確認されます。ユーザーがだまされた場合、サードパーティのWebサイトがサイトのCookieを取得できないため、認証エラーが発生します。
サイトは、フォームページを作成するときに一意のトークンを生成します。このトークンは、サーバーにデータをポスト/取得するために必要です。
トークンはサイトによって生成され、フォームを含むページが生成されたときにのみ提供されるため、他の一部のサイトはフォームを模倣できません。トークンを持たないため、サイトに投稿できません。
Cloud Underブログでは、CSRFトークンについて説明しています。
a.comでホストされている、簡略化されたTwitterのようなWebサイトがあるとします。サインインしているユーザーは、POSTリクエストとしてサーバーに送信され、送信ボタンを押すと公開されるフォームにテキスト(ツイート)を入力できます。サーバー上では、ユーザーは一意のセッションIDを含むCookieによって識別されるため、サーバーはツイートを投稿したユーザーを認識します。
フォームは次のように単純にすることができます。
<form action="http://a.com/tweet" method="POST"> <input type="text" name="tweet"> <input type="submit"> </form>
想像してみてください。悪者がこのフォームをコピーして悪意のあるWebサイトに貼り付けたとします(b.comなど)。フォームは引き続き機能します。ユーザーがTwitterにサインインしている限り(つまり、ユーザーがa.comの有効なセッションCookieを持っている場合)、
http://a.com/tweet
ユーザーが送信ボタンをクリックすると、POSTリクエストが送信 され、通常どおり処理されます。これまでのところ、ユーザーがフォームの正確な機能を認識している限り、これは大きな問題ではありませんが、悪者が次のようにフォームを微調整するとどうなるでしょうか。
<form action="https://example.com/tweet" method="POST"> <input type="hidden" name="tweet" value="Buy great products at http://b.com/#iambad"> <input type="submit" value="Click to win!"> </form>
さて、ユーザーの1人が悪者のWebサイトに行き、「クリックして勝つ!」ボタンをクリックすると、フォームがWebサイトに送信され、ユーザーはCookieのセッションIDによって正しく識別され、非表示のツイートが公開されます。
私たちの悪者がさらに悪い場合は、JavaScriptを使用してWebページを開くとすぐに、罪のないユーザーがこのフォームを送信するようにします。これは基本的にクロスサイトリクエストフォージェリです。
フォームはどこからでもどこでも簡単に送信できます。通常、これは一般的な機能ですが、フォームが属するドメインからのみフォームの送信を許可することが重要である場合がさらに多くあります。
WebアプリケーションがPOST要求とGET要求を区別しない場合(たとえば、PHPで$ _POSTではなく$ _REQUESTを使用する場合)は、事態はさらに悪化します。やめろ!データ変更リクエストは簡単に送信できます
<img src="http://a.com/tweet?tweet=This+is+really+bad">
、悪意のあるWebサイトやメールに埋め込まれて、送信できます。自分のWebサイトからのみフォームを送信できるようにするにはどうすればよいですか?これがCSRFトークンの出所です。CSRFトークンは、ランダムで推測が難しい文字列です。保護したいフォームのあるページで、サーバーはランダムな文字列、CSRFトークンを生成し、それを非表示フィールドとしてフォームに追加し、セッションに保存するかCookieを設定することによって、何らかの形で記憶します値を含みます。フォームは次のようになります。
<form action="https://example.com/tweet" method="POST"> <input type="hidden" name="csrf-token" value="nc98P987bcpncYhoadjoiydc9ajDlcn"> <input type="text" name="tweet"> <input type="submit"> </form>
ユーザーがフォームを送信すると、サーバーは投稿されたフィールドcsrf-token(名前は関係ありません)の値をサーバーが記憶しているCSRFトークンと比較するだけです。両方の文字列が等しい場合、サーバーはフォームの処理を続行します。それ以外の場合、サーバーはフォームの処理を直ちに停止し、エラーで応答する必要があります。
なぜこれが機能するのですか?上記の例の悪者がCSRFトークンを取得できない理由はいくつかあります。
非表示フィールドの値はユーザーごとに異なるため、静的ソースコードをページから別のWebサイトにコピーしても意味がありません。悪意のあるユーザーのWebサイトが現在のユーザーのCSRFトークンを知らなければ、サーバーは常にPOST要求を拒否します。
悪意のあるユーザーの悪意のあるページは、ユーザーのブラウザーによって別のドメイン(a.comではなくb.com)から読み込まれるため、JavaScriptをコーディングすることはできません。これにより、コンテンツが読み込まれ、ユーザーの現在のCSRFトークンがあなたのウェブサイト。これは、ウェブブラウザがデフォルトでクロスドメインAJAXリクエストを許可していないためです。
ドメインが一致しないため、悪意のあるユーザーはサーバーによって設定されたCookieにもアクセスできません。
クロスサイトリクエストフォージェリから保護する必要があるのはいつですか?上記のようにGET、POST、およびその他のリクエストメソッドを混同しないようにできる場合は、デフォルトですべてのPOSTリクエストを保護することから始めます。
上記で説明したように、標準のHTMLフォームは、これらのメソッドを使用するブラウザから送信できないため、PUTおよびDELETEリクエストを保護する必要はありません。
一方、JavaScriptは実際に、jQueryの$ .ajax()関数を使用するなど、他のタイプの要求を行うことができますが、AJAX要求が機能するためには、ドメインが一致する必要があります(他の方法で明示的にWebサーバーを構成しない限り) 。
これは、POSTリクエストであっても、CSRFトークンをAJAXリクエストに追加する必要がない場合が多いことを意味しますが、実際のPOSTリクエストが実際のリクエストである場合は、WebアプリケーションのCSRFチェックのみをバイパスする必要があります。 AJAXリクエスト。これは、AJAXリクエストに通常含まれているX-Requested-Withのようなヘッダーの存在を探すことで実行できます。別のカスタムヘッダーを設定して、サーバー側でその存在を確認することもできます。ブラウザは通常のHTMLフォームの送信(上記を参照)にカスタムヘッダーを追加しないため、安全です。BadGuy氏がこの動作をフォームでシミュレートする機会はありません。
AJAXリクエストに疑問がある場合は、何らかの理由でX-Requested-Withのようなヘッダーを確認できないため、生成されたCSRFトークンをJavaScriptに渡して、AJAXリクエストにトークンを追加します。これにはいくつかの方法があります。通常のHTMLフォームと同じようにペイロードに追加するか、AJAXリクエストにカスタムヘッダーを追加します。サーバーが着信要求でそれを探す場所を認識し、それをセッションまたはcookieから記憶した元の値と比較できる限り、ソートされます。
すべての根幹は、リクエストがサイトの実際のユーザーからのものであることを確認することです。csrfトークンはフォーム用に生成され、ユーザーのセッションに関連付ける必要があります。これは、トークンを検証するサーバーにリクエストを送信するために使用されます。これはcsrfから保護する1つの方法です。別の方法はリファラーヘッダーをチェックすることです。