web-dev-qa-db-ja.com

CORS-プリフライトリクエストの導入の動機は何ですか?

Cross-Origin resource sharingは、Webページが別のドメインへのXMLHttpRequestを作成できるようにするメカニズムです( wikipedia から)。

私はこの数日間CORSをいじっていましたが、すべてがどのように機能するかについてかなりよく理解していると思います。

ですから、私の質問は、CORS /プリフライトがどのように機能するかではなく、新しいリクエストタイプとしてプリフライトを思いついた理由です。サーバーAがプリフライト(PR)をサーバーBに送信して、実際のリクエスト(RR)が受け入れられるかどうかを確認する必要がある理由を確認できません-BがRRを受け入れ/拒否することは確かに可能です以前のPR。

かなり検索した後、www.w3.org(7.1.5)で この部分 の情報を見つけました。

この仕様が存在する前に特定のユーザーエージェントから発信できなかったクロスオリジンリクエストからリソースを保護するために、リソースがこの仕様を認識していることを確認するためにプリフライトリクエストが行われます。

これは文を理解するのが最も難しいと思います。私の解釈(「最良の推測」と呼ぶべきです)は、仕様を認識していないサーバーCからの要求からサーバーBを保護することです。

誰かがシナリオを説明してください/ PR + RRがRR単独よりもよく解決する問題を示すことができますか?

309
jan groth

プリフライトリクエストの目的に関して混乱するのにしばらく時間を費やしましたが、私は今それを手に入れたと思います。

重要な洞察は、プリフライトリクエストはセキュリティのものではないということです。むしろ、それらはnot-changing-the-rulesのことです。

プリフライトリクエストはセキュリティとは関係がなく、CORSを認識して、現在開発中のアプリケーションには関係ありません。むしろ、プリフライトメカニズムは、CORSを認識せずに開発されたサーバーにメリットをもたらし、クライアントとサーバーの間でCORSを認識していることの健全性チェックとして機能します。 CORSの開発者は、決して受信しないという仮定に依存している十分なサーバーがあると感じました。双方がオプトインできるようにプリフライトメカニズムを発明したクロスドメインDELETEリクエスト。彼らは、単純にクロスドメインコールを有効にするという代替手段が、既存のアプリケーションをあまりにも多く破壊してしまうと感じていました。

ここには3つのシナリオがあります。

  1. もはや開発中ではなく、CORSよりも前に開発された古いサーバー。これらのサーバーは、決して受信しないと仮定する場合があります。クロスドメインDELETEリクエスト。 このシナリオはプリフライトメカニズムの主な受益者ですはいプリフライトメカニズムは追加の「健全性チェック」を提供するため、Webの基本的なルールが変更されたためにクライアントとサーバーが破損することはありません。

  2. まだ開発中ですが、多くの古いコードを含み、クロスドメインの世界で適切に動作することを確認するためにすべての古いコードを監査することは実行不可能/望ましくないサーバー。このシナリオにより、サーバーはCORSに徐々にオプトインできます。 「この特定のヘッダーを許可します」、「この特定のHTTP動詞を許可します」、「Cookie /認証情報の送信を許可します」などと言います。このシナリオでは、プリフライトメカニズム

  3. CORSを認識して作成された新しいサーバー。標準的なセキュリティ慣行に従って、サーバーはany着信要求に直面してリソースを保護する必要があります。サーバーはクライアントが悪意のあることをしないと信用することはできません。 このシナリオはプリフライトメカニズムの恩恵を受けません:プリフライトメカニズムは、リソースを適切に保護しているサーバーに追加のセキュリティをもたらしません。

285
Michael Iles

CORSの前にクロスドメインリクエストの世界を考えてください。標準形式のPOSTを実行するか、scriptまたはimageタグを使用してGETリクエストを発行できます。 GET/POST以外のリクエストタイプを作成することはできません。また、これらのリクエストでカスタムヘッダーを発行することもできません。

CORSの出現により、仕様の作成者は、Webの既存のセマンティクスを壊さずに新しいクロスドメインメカニズムを導入するという課題に直面しました。彼らは、サーバーに新しいリクエストタイプをオプトインする方法を提供することで、これを行うことを選択しました。このオプトインはプリフライトリクエストです。

したがって、カスタムヘッダーのないGET/POSTリクエストはプリフライトを必要としません。これらのリクエストは、CORS以前にすでに可能であったためです。ただし、カスタムヘッダーを持つリクエスト、またはPUT/DELETEリクエストdoは、プリフライトが必要です。これらはCORS仕様の新機能です。サーバーがCORSについて何も知らない場合、CORS固有のヘッダーなしで応答し、実際の要求は行われません。

プリフライトリクエストがないと、サーバーはブラウザからの予期しないリクエストを認識し始める可能性があります。サーバーがこれらの種類の要求に対応していない場合、これはセキュリティの問題につながる可能性があります。 CORSプリフライトを使用すると、クロスドメインリクエストを安全な方法でWebに導入できます。

50
monsur

CORSでは、以前のクロスオリジン<img src>または<form action>で可能であったよりも多くのヘッダーとメソッドタイプを指定できます。

一部のサーバーは、ブラウザが作成できないという前提で(不十分に)保護されている可能性があります。クロスオリジンDELETEリクエストまたはX-Requested-Withヘッダーを持つクロスオリジンリクエスト。したがって、このようなリクエストは「信頼」されます。

サーバーが実際にCORSを実際にサポートし、偶然のリクエストに応答するだけではないことを確認するために、プリフライトが実行されます。

31
Kornel

コードを使用した別の見方を次に示します。

<!-- hypothetical exploit on evil.com -->
<!-- Targeting banking-website.example.com, which authenticates with a cookie -->
<script>
jQuery.ajax({
  method: "POST",
  url: "https://banking-website.example.com",
  data: JSON.stringify({
    sendMoneyTo: "Dr Evil",
    amount: 1000000
  }),
  contentType: "application/json",
  dataType: "json"
});
</script>

CORS以前では、上記の悪用の試みは、同一生成元ポリシーに違反しているため失敗します。この方法で設計されたAPIは、ブラウザーのネイティブセキュリティモデルによって保護されていたため、XSRF保護を必要としませんでした。 CORS以前のブラウザでクロスオリジンJSON POSTを生成することは不可能でした。

現在、CORSが登場しています。プリフライトを介してCORSにオプトインする必要がない場合、このサイトは、独自の過失がないため、突然、大きな脆弱性を抱えることになります。

一部のリクエストがプリフライトをスキップできる理由を説明するには、 これは仕様によって回答されます:

単純なクロスオリジンリクエストは、この仕様に準拠していない現在展開されているユーザーエージェントによって生成される可能性のあるものと一致するものとして定義されています。

それを解くために、GETは7.1.5で定義されている「単純なメソッド」であるため、プリフライトされません。 (プリフライトを回避するために、ヘッダーも「単純」でなければなりません)。これを正当化する理由は、「単純な」クロスオリジンGETリクエストが、例えば<script src="">(これがJSONPの仕組みです)。 src属性を持つ要素は、プリフライトなしでクロスオリジンGETをトリガーできるため、「単純な」XHRでプリファイトを要求してもセキュリティ上の利点はありません。

14
Dylan Tack

他の答えは、戦闘前がセキュリティを強化する理由に焦点を合わせていないと感じています。

シナリオ:

1)プリフライトあり。ユーザーがsafe-bank.comに対して認証されている間に、攻撃者がサイトdummy-forums.comからのリクエストを偽造します。
サーバーがオリジンをチェックせず、何らかの形で欠陥がある場合、browserはプリフライトリクエストOPTIONを発行します方法。サーバーは、ブラウザーが応答として予期しているCORSを認識しないため、browserは続行されません(まったく害はありません)

2)プリフライトなし。攻撃者は上記と同じシナリオでリクエストを偽造します。ブラウザはすぐにPOSTまたはPUTリクエストを発行し、サーバーはそれを受け入れて処理する可能性があり、これにより潜在的に何らかの損害が発生します。

攻撃者が、任意のランダムなホストからリクエストを直接送信する場合は、任意のホストからno認証のリクエストについて考えている可能性が高いです。これは偽造されたリクエストですが、xsrfのリクエストではありません。そのため、サーバーは資格情報を確認して失敗します。 CORSは、リクエストを発行する資格情報を持つ攻撃者を阻止しようとはしませんが、ホワイトリストはこの攻撃のベクトルを減らすのに役立ちます。

プリフライトメカニズムは、クライアントとサーバー間の安全性と一貫性を追加します。キャッシュがほとんど使用できないので、これがすべてのリクエストで余分なハンドシェイクの価値があるかどうかはわかりませんが、それはそれがどのように機能するかです。

12
Hirako

さらに、ユーザーデータに副作用を引き起こす可能性のあるHTTP要求メソッド(特に、GET以外のHTTPメソッド、またはPOST特定のMIMEタイプでの使用)、仕様ではブラウザがリクエストを「プリフライト」することを義務付けています

ソース

3

パフォーマンスに関するプリフライトされたリクエストではありませんか?プリフライトリクエストを使用すると、クライアントは、PUTメソッドを使用したJSONなどの大量のデータを送信する前に、操作が許可されているかどうかをすばやく知ることができます。または、認証ヘッダーの機密データをネットワーク経由で送信する前。

PUT、DELETE、およびカスタムヘッダー以外のその他のメソッドの事実は、デフォルトでは許可されていません(「Access-Control-Request-Methods」および「Access-Control-Request-Headers」で明示的な許可が必要です)ダブルチェックのように。これらの操作は、GET要求ではなく、ユーザーデータにより多くの影響を与える可能性があるためです。だから、それは次のように聞こえます:

http://foo.example からのクロスサイトリクエストを許可していることがわかりましたが、DELETEリクエストを許可することは確かですか?影響を考慮しましたか?これらのリクエストがユーザーデータで発生する可能性があるということですか?」

私は、プリフライトされたリクエストと古いサーバーの利点との間の引用された相関関係を理解し​​ていませんでした。 CORSの前に、またはCORSの認識なしで実装されたWebサービスは、最初にその応答に「Access-Control-Allow-Origin」ヘッダーがないため、クロスサイト要求を受け取ることはありません。

1
Nipo

CORSをサポートするブラウザーでは、読み取りリクエスト(GETなど)は、同一の発信元ポリシーによってすでに保護されています:認証されたクロスドメインリクエストを実行しようとする悪意のあるWebサイト銀行またはルーターがAccess-Control-Allow-Originヘッダーを設定していないため、返されたデータを読み取ることができません。

ただし、writingリクエスト(POSTなど)を使用すると、リクエストがウェブサーバーに到着したときに損傷が発生します。*ウェブサーバーはOriginヘッダーをチェックしてリクエストが合法かどうかを判断できますが、このチェックはそうではありませんこれは、WebサーバーがCORSを必要としないか、WebサーバーがCORSよりも古いため、クロスドメインPOSTが同一生成元ポリシーによって完全に禁止されていると想定しているために実装されています。

そのため、ウェブサーバーにはクロスドメイン書き込みリクエストの受信にオプトインの機会が与えられます。

*基本的にAJAXバージョンのCSRF。

1
AndreKR