カスタムWebサービスで承認された脆弱性分析を実行していて、CSRFの脆弱性を発見しました。
Originヘッダーをチェックしないサービスと結合されたフォームトークンがないため、AJAX「感染した」概念実証ページからのPOSTを介してリクエストを偽造できると信じていました。
Webサーバーが状態を維持する方法により、攻撃を完了するには一連の6つの連続したPOSTが必要です。ここに問題があります:
私の最初のPoCは、6つの単純なhtmlページ(それぞれ1つのフォーム)を作成することで、私の仮定を検証するために、1つずつロードして送信しました。これは正常に機能したため、これらのフォームアクションを順次AJAX POSTに変換しました。この時点で攻撃が機能しなくなりました。コンテンツと注文の両方の実際のHTTPリクエストを比較しました-すべてのアプリケーションレイヤーデータが一致しています。
返されたデータを読み取る必要がないにもかかわらず、何らかの理由で同じOriginポリシーに疑わしくなったため、Chrome --disable-web-securityオプションを使用して(ポリシーを無効にするため))試しました私の攻撃は再び、今回は成功しました。同じOriginポリシーが何らかの形で攻撃を防いでいるようですが、返されたデータを読み取る必要がないため、なぜなのかわかりません。私がやりたいことを達成する方法はありますか?
ブラウザでサードパーティのCookieが有効になっている限り、これが機能しない理由はありません。
HTMLフォームのPOSTを使用できます。フォームがマルチステージプロセスの場合は、攻撃ページがリクエストを制御して順番に発行できるため、XHRリクエストとして実行する方が便利です。やっている。
AJAXリクエストでwithCredentials
を設定していることを確認してください。
JQueryでは、これは次のように行われます
$.ajax({
type: "POST",
url: 'http://www.example.com/Controller/Action',
data: 'foo=bar',
async: true,
xhrFields: {
withCredentials: true
}
});
他の回答は、withCredentials
を使用すると、意図したGETまたはPOSTではなく [〜#〜] cors [〜#〜] プリフライトリクエストがリソースに送信されることを意味します。リクエストが「単純なリクエスト」である限り、これは当てはまりません。エクスプロイトがHTMLフォームで機能した場合、正しいAJAX=同等のものは単純なリクエストになります。そのため、コードがすべて正しいことを確認してください。
クロスオリジンリクエストには2つのフレーバーがあります。
- 簡単なリクエスト
- 「それほど単純ではない要求」(私が作成したばかりの用語)
単純なリクエストとは、次の条件を満たすリクエストです。
HTTPメソッドは次のいずれかに一致します(大文字と小文字が区別されます)。
- HEAD
- GET
- POST
- HTTPヘッダーの一致(大文字と小文字は区別されません):
- 受け入れる
- 受け入れ言語
- コンテンツ言語
- 最終イベントID
- Content-Type。ただし、値が次のいずれかである場合のみ。
- application/x-www-form-urlencoded
- multipart/form-data
- テキスト/プレーン
単純なリクエストは、CORSを使用せずにブラウザからすでに作成できるため、そのような特徴があります。
これは CORS仕様 で実際に言及されており、CORSが実際にセキュリティを追加するのではなく、クライアントとサーバーの両方が仕様にオプトインした場合にのみクロスドメイン通信を有効にすることを示します。両方の当事者がオプトインしない場合(被害者のサイトがこの方法で通信されることを望まないCSRF攻撃など)、ブラウザはpre-CORSと同じように動作します。つまり、Cookieが送信されますが、応答は読み取れません。
この仕様に準拠するリソースは、資格情報を持つ単純なクロスオリジン要求を予期できるように、常に準備する必要があります。このため、単純な要求が取得以外の意味を持つリソースは、明示的に提供される要求のコンテンツに推測できないトークンを含めることを要求することにより、クロスサイトリクエストフォージェリ(CSRF)からリソースを保護する必要があります。
あなたの質問に戻ります:
コンテンツと注文の両方の実際のHTTPリクエストを比較しました-すべてのアプリケーションレイヤーデータが一致しています。
BurpやFiddler2などのインターセプトプロキシを使用してリクエストを確認することをお勧めします。 Chromeで表示されるリクエストは、それらが発行されたページのOriginから解釈され、Originが同一生成元ポリシーによる応答が表示されない場合は、開発ツールでも通知されません。Chromeは “CAUTION: provisional headers are shown”
メッセージ。
たとえば、以下はChrome dev toolsに表示され、その後Burpに表示されるものと同じリクエストです。外部ツールのみがCookieを表示していることに注目してください。
私はChrome 38、Windows 7 x64上のFirefox 32およびInternet Explorer 11)でこの動作をテストしましたが、ブラウザ間で一貫しています(ただし、設定でサードパーティのCookieが有効になっていることを確認してください)。これは、この動作が現在の標準に準拠していることを示しています。
したがって、私のアドバイスは、インターセプトプロキシを使用してコードとリクエストを再確認することです。たぶん、ここに投稿して、別の目でチェックして、ある方法で機能しているかどうかを確認します。要求が同じではないため、どこかに間違いがあるはずです。
また、Same Origin Policy違反のために返されたエラーが原因で、コードが早期に終了しないことを確認してください。
何もせずにエラーをキャッチしてみてください。 SOPエラーは、スクリプトの実行を停止する例外を発生させます。代わりにエラーをキャッチすると、リクエストが発生し、応答がフィルタリングされ、例外がスローされます。キャッチされ、スクリプトは次のリクエストを続行します。
つまり、基本的には次のように機能します。
attackstep1() << script stop here due to a exception, thus only step1 of attack is performed
attackstep2()
attackstep3()
.....
代わりに、次のようなことを試してください:
try {
attackstep1()
}
Catch(e) {}
try {
attackstep2()
}
Catch(e) {}
try {
attackstep3()
}
Catch(e) {}
try {
....
}
Catch(e) {}
SOP権限エラーを無視し、スクリプトの実行を続行します。保護されたリソースが返すリソースにはアクセスできないことに注意してください。
取得したエラーメッセージは、攻撃しようとしているサーバーで Cross-Originリソース共有(CORS) が有効になっていないためです。したがって、すべてのAJAX要求は、Webサービスをホストするサーバーによって受け入れられません。
したがって、ターゲットサーバーでCORSを有効にすると、サーバーはAJAXリクエストを受け入れます。 CORSが有効になっていないとリクエストが拒否されるため、AJAXは使用しないでください。 curlは、Webサービスを呼び出すことができるNiceコマンドラインツールを使用できます。