往年のWeb開発者であれば X-Content-Type-Options: nosniff はIE専用のオプションHTTPヘッダーだと理解している方が多いと思います。
この理解は正しかったのですが、現在は正しくありません。nosniffはChromeやFirefoxの動作にも影響与えます。このため、IEをサポートしないサイトであっても X-Content-Type-Options: nosniff は必要なHTTPヘッダーです。
なぜ X-Content-Type-Options: nosniff はIE以外にも必要になったのか?
主な理由はJSONPの動作にあります。
そもそもJSONは最初から標準規格として利用され始めた仕組みではありません。”JavaScriptのコード”として定義されたオブジェクトがデータとして扱えるので、それをデータ交換の為に利用し始めたのが始まりです。
JSONをXHRで読み込んだ場合、同一生成元ポリシー によりJSONデータの読み込みはリクエストしたサイト1に限られます。この仕様の為、JSONデータは他のサイトからXHRで読み込めませんでした。
この制限を克服するために、XHRではなく、<script>タグでJSONデータを読み込むJSONPが利用されるようになります。
当時はRFC 4627はまだなく、メディアタイプに application/javascript が利用されていました。RFC 4627ではJSONに application/json が割り当てられていますが、RFC 4727後も互換性の為に application/javascript でJSONデータが読み込めるようになっていました。
様々なJSON Hijackの手法や脆弱性が考案され、JSONデータをJavascriptとして読み込むことがリスクになっていました。
コールバックをサポートするJSONPの場合、攻撃手法の名前はともかくJSONPインジェクションと呼ばれる攻撃も可能です。
X-Content-Type-Options: nosniff がChrome/Firefoxでサポート
本来、JSONデータはJavaScriptとして解釈されるべきではありません。しかし、JSONデータをJSONとして解釈させると互換性問題が発生します。このため、ChromeとFirefoxは nosniff ヘッダーがある場合にだけ、メディアタイプを厳格に処理するよう仕様が追加されました。
nosniff
Blocks a request if the requested type is“
style
” and the MIME type is not “text/css
“, or
“script
” and the MIME type is not a JavaScript MIME type.
Firefoxがこの仕様を追加したのは2017年の初め頃です。
まとめ
IE用に nosniff を付けてきたサイトも多いと思います。IEを無視すれば、nosniff無しで正しく動作するサイトを作れないこともないです。しかし、ブラウザがメディアタイプと異なる解釈をしてしまうのは良くないです。新しいJSONハイジャック手法が見つかり、ある日突然nosniffがないととても困る状況になる可能性もあります。IEをサポートしなくなっても、nosniffオプションは削除せず、付けたままにしておきましょう。
JSONPは使わないようにする必要があります。CORSを設定し、普通にXHRからアクセスします。
CORSをサポートするブラウザ:
- Chrome 3+
- Firefox 3.5+
- Opera 12+
- Safari 4+
- Internet Explorer 8+
nosniffがあると困るケースもあります。新しいメディアタイプが追加された場合でブラウザのサポートがなく、コンテンツの中身を見てメディアタイプが判別できる時です。こういうモノがあった場合、そのリクエストだけnosniffを付けないようにすると良いです。