Status Code

Error Events

October 1, 2020
Abuse Error Events, Status Code, nosniff, Content-Type
Category Attack
Defenses Fetch Metadata, SameSite Cookies

Webページがサーバにリクエストを発行すると(例:フェッチ、HTMLタグ)、サーバはこのリクエストを受信して処理します。 受信した際にサーバは与えられた条件に基づいて、リクエストが成功(例:200)すべきか失敗(例:404)すべきかを決定します。 レスポンスがエラーステータスを持つ場合、ページを処理するためにブラウザによってerror eventが発行されます。 これらのエラーは、例えばHTMLコンテンツを画像として埋め込もうとした時のようなパーサーの処理が失敗するケースにも対応しています。 たとえば、攻撃者は認証されたユーザだけが利用できるリソースにユーザがアクセスできるかどうかを確認することで、ユーザがサービスにログインしているかどうかを検出できます1。 このXS-Leakの影響はアプリケーションによって異なりますが、ユーザを非匿名化する高度な攻撃につながる可能性があります2。 エラーイベントは様々な HTMLタグからスローされる可能性があり、ブラウザによって動作が異なるものもあります 3。 例えば、読み込まれたリソースやHTMLタグ、特定のヘッダ(例えば nosniff や Content-Type )の存在、あるいはブラウザのデフォルトの保護機能の適用などによって動作が変わることがあります。 エラーイベントで情報をリークさせる原理は、さまざまなXS-Leakに抽象化して適用できます。 たとえば、Cache Probingの1つの手法では、特定の画像がブラウザによってキャッシュされたかどうかの検出にエラーイベントを使用しています。 コード # 以下のコードは、<script> タグを使用してエラーイベントを検出する方法を示しています。 function probeError(url) { let script = document.createElement('script'); script.src = url; script.onload = () => console.log('Onload event triggered'); script.onerror = () => console.log('Error event triggered'); document.head.appendChild(script); } // google.com/404 が HTTP 404 を返すため、スクリプトはエラーイベントを発生する probeError('https://google.com/404'); // google.com は HTTP 200 を返すので、スクリプトは onloadイベントをトリガーする probeError('https://google.com/'); 対策 # このXS-Leakの緩和策は、アプリケーションが特定のリソースをどのように処理するかによって異なる可能性があります。 一般的なアプローチとしては、可能な限り一貫した挙動を採用することです。 特定のシナリオでは、アプリケーションはSubresource Protectionsを使用して、攻撃者がURLを予測して攻撃を進行させることを防ぐことができます。 最後に、一般的なWebプラットフォームのセキュリティ機能を導入することで、アプリケーションの実装に大きな変更を加えることなく、このXS-Leakをより大幅に緩和することができます。 ...

Content-Type

October 1, 2020
Abuse typeMustMatch, iframes, Content-Type, Status Code
Category Historical
Defenses Deprecation

リクエストのContent-Typeをリークすることで、攻撃者は2つのリクエストを区別できるようになります。 typeMustMatch # typeMustMatchはobject要素のtypeMustMatch属性を反映したブール値です。これは、オブジェクトを読み込む際に、リソースのContent-Typeがオブジェクトで提供されるものと同じかどうかを検証することで、特定の MIME タイプを強制しなければならないことを保証します。残念ながら、この強制は攻撃者がウェブサイトから返されるContent-Typeとステータスコードを漏らすことも可能にします 1。 根本的な原因 # 以下のスニペットを考えると、https://target/api で返された Content-Type が type のものと一致しない場合や、サーバが 200 以外のステータスを返した場合には、 not_loaded がレンダリングされるでしょう。 <object type="application/json" data="https://example.org" typemustmatch> not_loaded </object> 問題 # 攻撃者は、すべての条件が満たされたときに起こるオブジェクトのレンダリングを検出することによって、ウェブサイトのContent-Typeとステータスコードをリークできます。攻撃者は、(ステータスコード200で)オブジェクトがレンダリングされるとき、0ではないであろうclientHeightとclientWidthの値をチェックできます。typeMustMatchはリソースを読み込む際に、サーバーがステータス200を返すことを要求するので、Error Events XS-Leaksと同様にエラーページを検出することが可能でしょう。 以下の例では、iframe内にオブジェクトを埋め込み、iframeがonloadイベントをトリガーしたときにclientHeightとclientWidthの値をチェックすることでこの動作を検出する方法を示しています。 // 配送先のWebサイトのURLを設定する var url = 'https://example.org'; // チェックしたいコンテンツタイプ var mime = 'application/json'; var ifr = document.createElement('iframe'); // オブジェクトがonloadイベントを発生させないので、iframe内にオブジェクトをロードする。 ifr.srcdoc = ` <object id="obj" type="${mime}" data="${url}" typemustmatch> error </object>`; document.body.appendChild(ifr); // iframeが読み込まれたら、オブジェクトの高さを読み取ります。 // もしそれが一行のテキストの高さであれば、リソースのContent Typeは`application/json`ではなかったということです。 // もしそうでなければ、それは`application/json`だったということです。 ifr.onload = () => { console. ...