CORS - Misconfigurations & Bypass
CORSとは?
Cross-Origin Resource Sharing(CORS)標準は、サーバーがアクセスできるユーザーと外部ソースから許可されるHTTPリクエストメソッドを定義することを可能にします。
同一オリジンポリシーは、リソースを要求するサーバーとリソースをホストするサーバーが同じプロトコル(例:http://
)、ドメイン名(例:internal-web.com
)、およびポート(例:80)を共有することを義務付けます。このポリシーでは、同じドメインとポートのウェブページのみがリソースにアクセスできます。
http://normal-website.com/example/example.html
のコンテキストで同一オリジンポリシーを適用した場合の例:
アクセスされるURL | アクセスが許可されるか? |
---|---|
| はい:同一のスキーム、ドメイン、およびポート |
| はい:同一のスキーム、ドメイン、およびポート |
| いいえ:異なるスキームとポート |
| いいえ:異なるドメイン |
| いいえ:異なるドメイン |
| いいえ:異なるポート* |
*Internet Explorer は同一オリジンポリシーの適用時にポート番号を無視し、このアクセスを許可します。
Access-Control-Allow-Origin
ヘッダー
Access-Control-Allow-Origin
ヘッダーこのヘッダーは複数のオリジン、null
値、またはワイルドカード *
を許可できます。ただし、どのブラウザも複数のオリジンをサポートしておらず、ワイルドカード *
の使用は制限の対象です(ワイルドカードは単独で使用する必要があり、Access-Control-Allow-Credentials: true
と併用することは許可されていません)。
このヘッダーは、ウェブサイトによって開始されたクロスドメインリソースリクエストに対するサーバーから発行され、ブラウザは自動的に Origin
ヘッダーを追加します。
Access-Control-Allow-Credentials
ヘッダー
Access-Control-Allow-Credentials
ヘッダーデフォルトでは、クロスオリジンリクエストは、クッキーやAuthorizationヘッダーなどの資格情報なしで行われます。ただし、クロスドメインサーバーは、Access-Control-Allow-Credentials
ヘッダーを true
に設定することで、資格情報が送信された場合に応答の読み取りを許可できます。
true
に設定されている場合、ブラウザは資格情報(クッキー、認証ヘッダー、またはTLSクライアント証明書)を送信します。
CSRF プリフライトリクエスト
クロスドメイン通信におけるプリフライトリクエストの理解
特定の条件下でクロスドメインリクエストを開始する際、標準外のHTTPメソッド(HEAD、GET、POST以外のもの)、新しいヘッダーの導入、または特別なContent-Typeヘッダー値の使用などがある場合、プリフライトリクエストが必要となる場合があります。この事前リクエストは、**OPTIONS
**メソッドを利用して、サーバーに将来のクロスオリジンリクエストの意図、使用するHTTPメソッドやヘッダーなどを通知する役割を果たします。
**クロスオリジンリソース共有(CORS)**プロトコルは、このプリフライトチェックを義務付けており、許可されたメソッド、ヘッダー、およびオリジンの信頼性を検証することで、リクエストされたクロスオリジン操作の実行可能性を判断します。プリフライトリクエストが不要となる条件についての詳細は、Mozilla Developer Network (MDN) が提供する包括的なガイドを参照してください。
重要な点として、プリフライトリクエストの不在は、レスポンスが認証ヘッダーを含む必要性を無効にするものではないことに留意する必要があります。これらのヘッダーがないと、ブラウザはクロスオリジンリクエストからのレスポンスを処理する能力を失います。
以下は、PUT
メソッドとカスタムヘッダーSpecial-Request-Header
を使用するプリフライトリクエストの例を示しています:
以下は、サーバーが受け入れるメソッド、許可されるオリジン、およびその他のCORSポリシーの詳細を示すヘッダーを返す可能性があります:
Access-Control-Allow-Headers
: このヘッダーは、実際のリクエスト中に使用できるヘッダーを指定します。サーバーによって設定され、クライアントからのリクエストで許可されたヘッダーを示します。Access-Control-Expose-Headers
: このヘッダーを通じて、サーバーは単純なレスポンスヘッダーに加えてレスポンスの一部として公開できるヘッダーについてクライアントに通知します。Access-Control-Max-Age
: このヘッダーは、プリフライトリクエストの結果をキャッシュできる期間を示します。サーバーは、プリフライトリクエストによって返される情報が再利用される可能性がある最大時間(秒単位)を設定します。Access-Control-Request-Headers
: プリフライトリクエストで使用され、このヘッダーは、クライアントが実際のリクエストで使用したいHTTPヘッダーについてサーバーに通知するために設定されます。Access-Control-Request-Method
: このヘッダーもプリフライトリクエストで使用され、クライアントが実際のリクエストで使用するHTTPメソッドを示すために設定されます。Origin
: このヘッダーはブラウザによって自動的に設定され、クロスオリジンリクエストの起源を示します。サーバーは、CORSポリシーに基づいて受信リクエストを許可するか拒否するかを評価するために使用されます。
通常(コンテンツタイプと設定されたヘッダーに応じて)、GET/POSTリクエストではプリフライトリクエストが送信されません(リクエストは直接送信されます)。ただし、レスポンスのヘッダー/本文にアクセスしたい場合は、それを許可する Access-Control-Allow-Origin ヘッダーを含める必要があります。 したがって、CORSはCSRFに対して保護されていません(ただし、役立つ場合があります)。
ローカルネットワークリクエストのプリフライトリクエスト
Access-Control-Request-Local-Network
: このヘッダーは、クライアントのリクエストに含まれ、問い合わせがローカルネットワークリソースを対象としていることを示します。サーバーにリクエストがローカルネットワーク内から発信されたことを通知するマーカーとして機能します。Access-Control-Allow-Local-Network
: サーバーはこのヘッダーを利用して、要求されたリソースがローカルネットワーク外のエンティティと共有できることを伝えます。異なるネットワーク境界を越えてリソースを共有するための許可を示し、セキュリティプロトコルを維持しながら制御されたアクセスを確保します。
ローカルネットワークリクエストを許可する有効な応答は、応答にも Access-Controls-Allow-Local_network: true
ヘッダーを含める必要があります:
注意:Linuxの 0.0.0.0 IP は、そのIPアドレスが「ローカル」と見なされないため、これらの要件を バイパス してlocalhostにアクセスするために機能します。
また、ローカルネットワークの要件をバイパス することも可能です。これは、ローカルエンドポイントのパブリックIPアドレス(たとえば、ルーターのパブリックIP)を使用する場合に当てはまります。なぜなら、いくつかの場合において、ローカルネットワークからアクセスされている場合、たとえパブリックIPにアクセスされていても、アクセスが許可されるからです。
悪用可能なミス構成
Access-Control-Allow-Credentials
を true
に設定することが、ほとんどの 実際の攻撃 に必要な条件であることが観察されています。この設定により、ブラウザが資格情報を送信し、レスポンスを読み取ることが許可され、攻撃の効果が向上します。これがないと、ブラウザにリクエストを発行させる利点が自分で行うよりも低下し、ユーザーのクッキーを利用することが不可能になります。
例外:ネットワークロケーションの認証を悪用
被害者のネットワークロケーションが認証の形式として機能する例外が存在します。これにより、被害者のブラウザをプロキシとして使用して、IPベースの認証を回避してイントラネットアプリケーションにアクセスすることが可能となります。この方法はDNSリバインディングと同様の影響を持ちますが、より簡単に悪用できます。
Access-Control-Allow-Origin
での Origin
の反映
Access-Control-Allow-Origin
での Origin
の反映Origin
ヘッダーの値が Access-Control-Allow-Origin
に反映される実際のシナリオは、これらのヘッダーを組み合わせる制限があるため、理論的にはあり得ないです。ただし、複数のURLに対してCORSを有効にしたい開発者は、Origin
ヘッダーの値をコピーして Access-Control-Allow-Origin
ヘッダーを動的に生成することがあります。このアプローチは脆弱性を導入する可能性があり、特に攻撃者が正規のように見せかけるために設計されたドメインを使用する場合、検証ロジックを欺くことができます。
null
オリジンの悪用
null
オリジンの悪用null
オリジンは、リダイレクトやローカルHTMLファイルなどの状況を指定するために指定されており、ユニークな位置を占めています。一部のアプリケーションは、ローカル開発を容易にするためにこのオリジンをホワイトリストに登録していますが、それにより、サンドボックス化されたiframeを介して任意のウェブサイトがnull
オリジンを模倣することで、CORS制限をバイパスすることができます。
正規表現バイパステクニック
ドメインのホワイトリストに遭遇した場合、攻撃者のドメインをホワイトリストに追加したり、サブドメインの乗っ取りの脆弱性を悪用したりするなど、バイパスの機会をテストすることが重要です。さらに、ドメインの検証に使用される正規表現は、ドメインの命名規則の微妙な点を見落とす可能性があり、さらなるバイパスの機会を提供します。
高度な正規表現バイパス
通常、正規表現パターンは、英数字、ドット(.)、ハイフン(-)の文字に焦点を当てており、他の可能性を無視しています。たとえば、ブラウザや正規表現パターンによって異なる解釈される文字を含むドメイン名は、セキュリティチェックをバイパスすることができます。Safari、Chrome、Firefoxがサブドメイン内のアンダースコア文字を処理する方法は、このような相違点がドメインの検証ロジックを回避するために悪用される方法を示しています。
このバイパスチェックの詳細情報と設定については: https://www.corben.io/advanced-cors-techniques/ および https://medium.com/bugbountywriteup/think-outside-the-scope-advanced-cors-exploitation-techniques-dad019c68397
サブドメイン内のXSSから
開発者は、情報をリクエストすることが許可されているドメインをホワイトリストに登録することで、CORSの悪用に対抗する防御メカニズムを実装することがよくあります。しかし、これらの予防措置にもかかわらず、システムのセキュリティは万全ではありません。ホワイトリストに含まれる脆弱なサブドメインが存在するだけで、他の脆弱性(例:XSS:クロスサイトスクリプティング)を介してCORSの悪用への道が開かれる可能性があります。
例として、requester.com
というドメインが、別のドメインであるprovider.com
からリソースにアクセスすることが許可されるようにホワイトリストに登録されているシナリオを考えてみましょう。サーバーサイドの構成は、次のようになるかもしれません:
このセットアップでは、requester.com
のすべてのサブドメインがアクセスを許可されています。ただし、sub.requester.com
のようなサブドメインがXSSの脆弱性で危険にさらされると、攻撃者はこの弱点を悪用できます。例えば、sub.requester.com
にアクセス権限を持つ攻撃者は、XSSの脆弱性を悪用して、CORSポリシーをバイパスし、provider.com
のリソースに悪意を持ってアクセスできます。
サーバーサイドキャッシュポイズニング
HTTPヘッダーインジェクションを介してサーバーサイドキャッシュポイズニングを悪用することで、格納されたクロスサイトスクリプティング(XSS)の脆弱性を誘発する可能性があります。このシナリオは、アプリケーションがOrigin
ヘッダーを違法な文字でサニタイズせず、特にInternet ExplorerとEdgeユーザーにとって脆弱性を作成するときに発生します。これらのブラウザは、(0x0d)を正当なHTTPヘッダーターミネーターとして扱い、HTTPヘッダーインジェクションの脆弱性を引き起こします。
次のリクエストを考慮してください。Origin
ヘッダーが操作されています:
Internet ExplorerとEdgeは、レスポンスを次のように解釈します:
直接的にこの脆弱性を悪用するためにウェブブラウザが不正なヘッダを送信することは実現不可能ですが、Burp Suiteなどのツールを使用して手動で生成された作成されたリクエストを使用することで、サーバーサイドのキャッシュが応答を保存し、他のユーザーに提供される可能性があります。 作成されたペイロードは、ページの文字セットをUTF-7に変更することを目的としており、これは特定のコンテキストでスクリプトとして実行できる方法で文字をエンコードする能力を持つため、XSSの脆弱性に関連付けられることが多い文字エンコーディングです。
格納型XSSの脆弱性について詳しくは、PortSwiggerを参照してください。
注意: 特にサーバーサイドキャッシュポイズニングを通じたHTTPヘッダーインジェクションの脆弱性の悪用は、HTTPヘッダーを含むすべてのユーザー提供入力の検証とサニタイズの重要性を強調しています。 このような脆弱性を防ぐために入力検証を含む堅牢なセキュリティモデルを常に採用してください。
クライアントサイドキャッシュポイズニング
このシナリオでは、適切なエンコーディングなしにカスタムHTTPヘッダーの内容を反映するウェブページのインスタンスが観察されます。 具体的には、ウェブページはX-User-id
ヘッダーに含まれる内容を反映し、この内容にはロード時にJavaScriptコードを実行するように設計されたSVGイメージタグが含まれる可能性があります。
Cross-Origin Resource Sharing(CORS)ポリシーにより、カスタムヘッダーの送信が可能になります。 ただし、CORSの制限によりブラウザによって応答が直接レンダリングされない場合、そのようなインジェクションの有用性は限定されているように見えるかもしれません。 重要なポイントは、ブラウザのキャッシュ動作を考慮する際に発生します。 Vary: Origin
ヘッダーが指定されていない場合、悪意のある応答がブラウザによってキャッシュされる可能性があります。 その後、このキャッシュされた応答は、初回リクエスト時の直接レンダリングの必要性をバイパスして、URLに移動する際に直接レンダリングされる可能性があります。 このメカニズムは、クライアントサイドキャッシングを活用することで攻撃の信頼性を高めます。
この攻撃を説明するために、JavaScriptの例が提供されており、JSFiddleなどのウェブページの環境で実行されるように設計されています。 このスクリプトは単純なアクションを実行します:悪意のあるJavaScriptを含むカスタムヘッダーを含むリクエストを指定されたURLに送信します。 リクエストが正常に完了すると、ターゲットURLに移動し、Vary: Origin
ヘッダーの適切な処理が行われずに応答がキャッシュされている場合、注入されたスクリプトの実行をトリガーする可能性があります。
この攻撃を実行するために使用されるJavaScriptの要約を以下に示します:
バイパス
XSSI (Cross-Site Script Inclusion) / JSONP
XSSI、またはCross-Site Script Inclusionとしても知られる脆弱性は、スクリプトタグを使用してリソースを含める際に同一オリジンポリシー(SOP)が適用されないという事実を利用するタイプの脆弱性です。これは、スクリプトが異なるドメインから含められる必要があるためです。この脆弱性により、攻撃者はスクリプトタグを使用して含まれた任意のコンテンツにアクセスして読むことができます。
この脆弱性は、特にダイナミックなJavaScriptやJSONP(Padding付きJSON)に関連する場合に特に重要です。特に、クッキーなどの環境権限情報が認証に使用される場合です。異なるホストからリソースを要求すると、クッキーが含まれ、それにより攻撃者がアクセスできるようになります。
この脆弱性をよりよく理解し、緩和するためには、https://github.com/kapytein/jsonpで利用可能なBurpSuiteプラグインを使用できます。このプラグインは、Webアプリケーション内の潜在的なXSSI脆弱性を特定および対処するのに役立ちます。
異なる種類のXSSIとその悪用方法について詳しく読むにはこちらをクリックしてください。
リクエストに callback
パラメータ を追加してみてください。ページがJSONPとしてデータを送信するように準備されている可能性があります。その場合、ページはContent-Type: application/javascript
でデータを返し、これによりCORSポリシーがバイパスされます。
簡単(無意味?)なバイパス
Access-Control-Allow-Origin
制限をバイパスする1つの方法は、Webアプリケーションに対してリクエストを行い、応答を返すように要求することです。ただし、このシナリオでは、最終的な被害者の資格情報は異なるドメインにリクエストが行われるため送信されません。
CORS-escape: このツールは、リクエストとそのヘッダーを転送するプロキシを提供し、同時にOriginヘッダーをリクエストされたドメインに一致するようにスプーフィングします。これにより、CORSポリシーが効果的にバイパスされます。以下はXMLHttpRequestを使用した例です:
simple-cors-escape: このツールは、リクエストをそのまま渡す代わりに、サーバーが指定されたパラメータで独自のリクエストを行う別のアプローチを提供します。
Iframe + Popup バイパス
e.origin === window.origin
のようなCORSチェックを バイパス するために、iframeを作成し、そこから新しいウィンドウを開くことができます。詳細は以下のページで確認できます:
TTL経由のDNSリバインディング
TTL経由のDNSリバインディングは、DNSレコードを操作して特定のセキュリティ対策をバイパスするための技術です。動作方法は次のとおりです:
攻撃者はWebページを作成し、被害者にアクセスさせます。
攻撃者は自分のドメインのDNS(IP)を被害者のWebページを指すように変更します。
被害者のブラウザはDNS応答をキャッシュし、DNSレコードが有効であるべき期間を示すTTL(Time to Live)値を持つ場合があります。
TTLが切れると、被害者のブラウザは新しいDNSリクエストを行い、攻撃者は被害者のページでJavaScriptコードを実行できます。
被害者のIPを制御することで、攻撃者は被害者からクッキーを送信せずに情報を収集できます。
この技術は、ブラウザによるキャッシュメカニズムがあるため、低いTTL値でもこの技術をすぐに悪用することが防がれる可能性があることに注意することが重要です。
DNSリバインディングは、被害者によって実行される明示的なIPチェックをバイパスするためや、ユーザーやボットが同じページに長時間滞在するシナリオなど、キャッシュが期限切れになるのを待つ場合に有用です。
DNSリバインディングを素早く悪用する必要がある場合は、https://lock.cmpxchg8b.com/rebinder.htmlのようなサービスを利用できます。
独自のDNSリバインディングサーバーを実行するには、DNSrebinder (https://github.com/mogwailabs/DNSrebinder)のようなツールを利用できます。これには、ローカルポート53/udpを公開し、それを指すAレコード(例:ns.example.com)を作成し、以前に作成したAサブドメインを指すNSレコードを作成する必要があります。ns.example.comサブドメインの任意のサブドメインは、あなたのホストによって解決されます。
さらに理解と実験のために、http://rebind.it/singularity.htmlで公開されているサーバーを探索することもできます。
DNSリバインディング経由の DNSキャッシュフラッディング
DNSリバインディング経由のDNSキャッシュフラッディングは、ブラウザのキャッシュメカニズムをバイパスし、2回目のDNSリクエストを強制するための別の技術です。動作方法は次のとおりです:
最初に、被害者がDNSリクエストを行うと、攻撃者のIPアドレスで応答されます。
キャッシュ防御をバイパスするために、攻撃者はサービスワーカーを利用します。サービスワーカーはDNSキャッシュをフラッドし、キャッシュされた攻撃者のサーバー名を効果的に削除します。
被害者のブラウザが2回目のDNSリクエストを行うと、IPアドレス127.0.0.1で応答されるようになります。通常、これはlocalhostを指します。
サービスワーカーを使用してDNSキャッシュをフラッドすることで、攻撃者はDNS解決プロセスを操作し、被害者のブラウザに2回目のリクエストを強制し、今度は攻撃者が望むIPアドレスに解決させることができます。
キャッシュ経由のDNSリバインディング
キャッシュ防御をバイパスする別の方法は、DNSプロバイダーで同じサブドメインに複数のIPアドレスを利用することです。動作方法は次のとおりです:
攻撃者はDNSプロバイダーで同じサブドメインに2つのAレコード(または2つのIPを持つ単一のAレコード)を設定します。
ブラウザがこれらのレコードをチェックすると、両方のIPアドレスが受信されます。
ブラウザが最初に攻撃者のIPアドレスを使用することを決定した場合、攻撃者は同じドメインへのHTTPリクエストを実行するペイロードを提供できます。
ただし、攻撃者が被害者のIPアドレスを取得したら、被害者のブラウザに応答を停止します。
ブラウザは、ドメインが応答しないことを認識すると、2番目に指定されたIPアドレスを使用し始めます。
2番目のIPアドレスにアクセスすることで、ブラウザは同一オリジンポリシー(SOP)をバイパスし、攻撃者はこれを悪用して被害者から情報を収集および外部送信できます。
この技術は、1つのドメインに複数のIPアドレスが提供される場合のブラウザの動作を活用しています。応答を戦略的に制御し、ブラウザがIPアドレスの選択を操作することで、攻撃者はSOPを悪用し、被害者から情報にアクセスできます。
localhostにアクセスするためには、Windowsでは 127.0.0.1、Linuxでは 0.0.0.0 を再バインドする必要があります。 godaddyやcloudflareなどのプロバイダーは、IP 0.0.0.0 を使用することを許可してくれませんでしたが、AWS route53は2つのIPのうちの1つを "0.0.0.0" として作成することを許可してくれました。
詳細については、https://unit42.paloaltonetworks.com/dns-rebinding/を参照してください。
その他の一般的なバイパス
もし内部IPが許可されていない場合、0.0.0.0を禁止するのを忘れている可能性があります(LinuxとMacで機能します)
もし内部IPが許可されていない場合、localhostに対してCNAMEで応答する(LinuxとMacで機能します)
内部IPがDNS応答として許可されていない場合、www.corporate.internalなどの内部サービスに対してCNAMEで応答できます。
DNS Rebindingの武器化
前述のバイパス技術に関する詳細情報や以下のツールの使用方法については、Gerald Doussot - State of DNS Rebinding Attacks & Singularity of Origin - DEF CON 27 Conferenceでの講演を参照してください。
Singularity of Origin
は、DNS rebinding攻撃を実行するためのツールです。攻撃サーバーのDNS名のIPアドレスをターゲットマシンのIPアドレスに再バインドし、ターゲットマシン上の脆弱なソフトウェアを悪用する攻撃ペイロードを提供するために必要なコンポーネントが含まれています。
DNS Rebindingに対する実際の保護
内部サービスでTLSを使用する
データにアクセスするための認証を要求する
Hostヘッダーを検証する
https://wicg.github.io/private-network-access/: パブリックサーバーが内部サーバーにアクセスする際に常にプリフライトリクエストを送信するための提案
ツール
CORSポリシーの構成ミスをファジングする
参考文献
Last updated