2つの異なるアプリケーションから、クロスオリジンリクエストを送信できました。ブラウザが「クロスオリジン」エラーを返しますが、サーバーはまだリクエストを受信して実行しています。たとえば、リモートサイトからクロスドメインリクエストを呼び出すには、
$.ajax({
xhrFields: {
withCredentials: true
},
data:{ my: 'a' },
url: 'http://MyApp/Page',
type: 'POST'
})
ブラウザがスクリプトへの応答を返さないことはわかっていますが、サーバーページは引き続き実行されます。
罪のないユーザーがサイトhttp://example.com
にログインしているとしましょう。このアプリケーションは、POSTレコードを挿入する要求を受け入れます。無実のユーザーがhttp://HackerSite.com
にアクセスすると、http://HackerSite.com
はPOST AJAX経由でhttp://example.com
にリクエストします。これを防ぐにはどうすればよいですか?
資格証明付きのクロスドメインAJAXリクエストを介してだけでなく、例のPOSTは、AJAXなしの標準フォームを使用して送信することもできます。
<form method="post" action="http://MyApp/Page" name="hiddenFormInIframe">
<input type="hidden" name="my" value="a" />
</form>
<script type="text/javascript">
document.hiddenFormInIframe.submit();
</script>
これには、リクエストにCookieも含まれます。
あなたが話している脆弱性は Cross Site Request Forgery と呼ばれます。
POSTリクエストでヘッダーを送信し、ヘッダーサーバー側を確認することにより、別のドメインから送信されるAJAXから保護できます。使用する一般的なヘッダーは X-Requested-With
。このヘッダーはセーフリストにないため、AJAXを介してクロスドメインに送信できません( [〜#〜] cors [〜#〜])がないため サーバーで有効になっています。HTMLフォームもこのヘッダーを送信できません。
AJAXを介したクロスドメインで許可されるヘッダーは次のとおりです。
- 受け入れる
- 受け入れ言語
- コンテンツ言語
- 最終イベントID
- コンテンツタイプ
X-Requested-With
JQueryを使用するとヘッダーが自動的に設定され、ASP.NETコードでこれを確認できます。
ただし、過去にはプラグインを介したエクスプロイトがいくつかありました Flashはヘッダーでは設定できませんでしたが、ブラウザーでは不可能でした (例:Referer
)このため、これを防ぐことをお勧めします シンクロナイザトークンパターン を使用するには、非表示フィールドまたはヘッダーにトークンを設定する必要があります。このトークンは、副作用のあるすべてのリクエストの認証Cookieと同様に検証されます。つまり、変更、送信、または削除するリクエスト(通常はPOST)です。
CORSの詳細については、こちらを参照してください: http://www.html5rocks.com/en/tutorials/cors/
クロスドメインポリシは、特定の状況で CORSヘッダー を使用して明示的に許可しない他のドメインからドメインが情報を読み取るのを防ぎます。しかし、それはクロスオリジンリクエストが出ることを禁止していません。あなたの例のリクエストは "pre-flight" OPTIONS
request にヒットする必要があります:「実際の」リクエストが成功するかどうかを確認するためのプローブリクエスト。
解決策の一部は、プロセスの早い段階でOPTIONS
リクエストを終了することです。プローブドメインがアクセスを許可されているかどうかを判断できるとすぐに。
より完全なソリューションでは、APIアクセストークンが必要になる場合があります。ページが読み込まれるたびに、アクセストークンを生成して埋め込みます。そのトークンをすべてのAPI/AJAXリクエストに含めます。トークンを含まないリクエストはすべて早期に終了する必要があります。
ここでの最良のアイデアは、他の記述のとおり、CSRFトークンを使用することです。最も簡単な形式は、ユーザーのIPアドレスを識別子としてデータベースに追加し、このIPにランダムな値を追加することです。ランダムな値が正しいトークンです。
たとえば、誰かがあなたのページにアクセスしてフォームを取得するときに、ユーザーのIPを取得します。たとえば、12.12.12.12とします。
ランダムな値とともにキー値データベースに追加します:12.12.12.12 = ljghsdlghdlghdlshsdflgd(注、「ljghsdlghdlghdlshsdflgd」の例を使用しないでください。代わりに、十分な長さの疑似ランダム値を生成してください)
この疑似ランダム値を隠しフィールドとして追加します。
送信時に、ユーザーのIPを使用して提案された返信を検索します。実際の応答が提案された応答と一致する場合、要求は受け入れられます。送信の試行が成功したかどうかに関係なく、存在する場合は、データベース内のレコードを削除します。これは、CSRFの試行がターゲットユーザーの実際のトークンを無効にし、各トークンが1回限りの使用になることを意味します。データベースのタイプに応じて、キーを ""に設定するだけの単純なものか、単に削除します。
例:12.12.12.12 = ""。
セキュリティを確保するためだけでなく、データベース内の不要なデータを取り除くためにも、これらの値を期限までに期限切れにすることをお勧めします。フォーラムかどうかによっては、有効時間として数時間持つのが賢明ですが、単純なフォームで言うと、パスワードを変更する場合は、有効時間として約5分で十分です。
もう1つのアイデアはcaptchaです。これは、ウイルス感染や自動リモートコントロールトロイの木馬などの自動クライアント側攻撃も防ぎます。 Webアプリケーションの感度によっては、CaptchaとCSRFトークンを同時に使用することをお勧めします。セッション全体で同じトークンを使用するというアドバイスに従わないでください。ユーザーがだまされてトークンを攻撃者に送信し、サイトに送信する可能性が少しあるため、セキュリティ面での悪い考えです。使い捨てトークンは攻撃者にとって無害ですが、使い捨てトークンは、CSRFが保護するように設計されているセッションと同じくらい危険な場合があります。
したがって、使い捨てトークンを使用します。これは、使い捨てトークンに比べて最高のセキュリティです。また、使い捨てトークンは、他の返信のCSRFの記事にあるように、転送中に保護する必要はありません。
すべてが正しく設定されている場合、サーバーページは実行されません。リクエストが拒否されるのは、それが最終段階に到達するチャンスがある前です。
アプリケーション/サーバーがAccess-Control-Allow-Origin
に設定 *
。これを実行できる場所はいくつかありますが、asp.netアプリケーションの一般的な場所はweb.configです。例:
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
</customHeaders>
</httpProtocol>
これをアプリのどこかに設定しているかどうかを確認します。 asp.netは複数のweb.configファイルを持つことができ、最も近いファイルの設定を使用することに注意してください。たとえば、次のディレクトリ構造があるとします。
/MyProject/ajax/stuff
MyProject
ディレクトリにweb.configがあり、stuff
ディレクトリにweb.configがある場合、stuff
のファイルはstuff
可能な限り。
わかりにくい場合はお知らせください。
また、これもIIS)で設定できると思います。そこでヘッダーも確認してください。