• 診断項目 No.17/127
  • セキュリティヘッダー
  • 重大度 中(medium)

MIMEスニッフィング対策(X-Content-Type-Options: nosniff)とは?仕組み・診断基準・設定方法

MIMEスニッフィング対策は、全応答にX-Content-Type-Options: nosniffを付けるだけで実施できます。ブラウザの動作、診断基準、Apache・nginx・IIS・Next.jsの設定例と確認方法を解説します。

結論(MIMEスニッフィング対策)

MIMEスニッフィング対策とは、レスポンスヘッダー X-Content-Type-Options: nosniff を返し、ブラウザに「サーバーが宣言したContent-Typeを信用し、中身から型を推測しない」よう指示することです。値は nosniff の1種類だけで、OWASP ASVS 5.0.0 V3.4.4はすべてのHTTP応答への付与を求めています。アップロードファイルがHTMLとして実行されるXSSや、型の違うファイルがスクリプト・CSSとして読み込まれる事故を、ヘッダー1行で防げます。

この記事のポイント

  • 設定は X-Content-Type-Options: nosniff の1行だけで、値は nosniff 以外にありません。
  • nosniffが有効だと、JavaScriptのMIMEタイプでないスクリプトや text/css でないスタイルシートはブロックされます。
  • ブラウザは値をカンマで分割した先頭の値だけを見ます。nosniff; mode=block のような書き方は無効です。
  • 正しいContent-Typeを返すことが前提です。エラーが出たらnosniffを外さず、Content-Typeを直します。
  • セキュリティAIチェッカーは先頭の値がnosniffなら○、ヘッダーなし・不正値なら×(重み2)と判定します。
診断項目名MIMEスニッフィング対策
項目IDheaders.nosniff
分類セキュリティヘッダー
重大度・配点の重み中(medium) 重み 2
関連する標準・ガイドラインOWASP ASVS 5.0.0 V3.4.4(すべてのHTTP応答に X-Content-Type-Options: nosniff を含める。Level 2)、OWASP WSTG-CONF-14(Other HTTP Security Header Misconfigurations)、OWASP Secure Headers Project 推奨値 nosniff、CWE-693(Protection Mechanism Failure。OWASP ZAP アラート 10021 の分類)

MIMEスニッフィング対策(X-Content-Type-Options: nosniff)とは

MIMEスニッフィング対策とは、レスポンスヘッダー X-Content-Type-Options: nosniff を返して、ブラウザに「サーバーが宣言した Content-Type を信用し、中身を見て型を推測(MIMEスニッフィング)しないこと」を指示する対策です。値は nosniff の1種類だけです。

X-Content-Type-Options: nosniff

MIMEスニッフィングとは、ブラウザがファイルの中身を見て「これはHTMLだろう」「これはスクリプトだろう」と型を推測する動作のことです。便利な反面、攻撃者が用意したファイルが本来と違う型として解釈されると、サイトのオリジン権限のままスクリプトが動く原因になります。

セキュリティAIチェッカーのこの項目では、診断対象URL(リダイレクト後の最終URL)の応答に、このヘッダーが有効な形で付いているかを確認します。自治体サイトはPDF・画像・CSV・Office文書などのファイル配布が多く、問い合わせフォームや投稿機能を持つことも多いため、ファイルの型が誤解釈されて HTML やスクリプトとして実行される事故を防ぐ基本対策として重要です。設定は1行で済み、正しい Content-Type を返しているサイトであれば副作用はほとんどありません。

MIMEスニッフィング対策はなぜ必要か(ブラウザの仕組み)

古いブラウザや処理系は「中身」で型を決めていた

古いブラウザや一部の処理系は、text/plain や application/octet-stream で配信されたファイルでも、先頭に <html> や <script> があれば HTML として描画することがありました。攻撃者が画像やテキストを装って HTML/JavaScript を含むファイルをアップロードすると、そのファイルを開いた職員や住民のブラウザで、サイトのオリジン権限のままスクリプトが動きます。nosniff はこの「型の取り違え」を断ち切ります。

Fetch Standard で定められた nosniff の動作

WHATWG Fetch Standard では、ヘッダー値を「get, decode, and split」で分割し、最初の値が ASCII 大文字小文字を区別せず nosniff に一致すれば nosniff が有効になると定義されています。そのうえで、次の場合に応答をブロックします。

リクエストの宛先nosniff 有効時の動作
script 系(script / worker / sharedworker / serviceworker / audioworklet / paintworklet)Content-Type が JavaScript の MIME タイプでなければブロック
style(<link rel="stylesheet"> など)Content-Type が text/css でなければブロック
その他(ページ表示・画像など)MIMEスニッフィングを行わず、宣言された Content-Type をそのまま使う

MDN は、ブラウジングコンテキストで読み込む際に Content-Type が無いか HTML 以外を示していても text/html として扱わなくなる点を挙げ、アップロードされたファイルが HTML として実行される XSS を防げると説明しています。

CORB(Cross-Origin Read Blocking)との関係

OWASP ASVS 5.0.0 V3.4.4 は、nosniff によりブラウザの Cross-Origin Read Blocking(CORB)を活用できることにも触れています。nosniff と正しい Content-Type を組み合わせることで、他オリジンのページから HTML・JSON・XML などを読み取らせない保護が働きやすくなります。

MIMEスニッフィング対策についてよくある誤解

  • 「HTMLページにだけ付ければよい」:ASVS V3.4.4 はすべての HTTP 応答を対象にしています。実際に効果が大きいのは、アップロードファイル、JSON、JS、CSS など HTML 以外の応答です。
  • 「nosniff を付ければ Content-Type は適当でよい」:逆です。nosniff を付けると、誤った Content-Type の JS/CSS は読み込まれなくなります。正しい Content-Type を返すことが前提です。Content-Type の明示そのものは「Content-Typeが明示されている」で確認します。
  • 「nosniff; mode=block のように書ける」:値は nosniff のみです。
  • 「ヘッダーが2回出ても問題ない」:Fetch Standard 上は最初の値が nosniff なら有効ですが、Apache とアプリの両方で付与している構成は、どこで管理しているかが分かりにくくなります。付与箇所は1か所に集約するのが望ましいです。

MIMEスニッフィング対策の診断基準(セキュリティAIチェッカー)

取得方法

  • 入力URLへ GET を1回送信し、リダイレクトを最大4回まで追跡します(タイムアウト15秒、本文上限2MB)。
  • 評価に使うのは最終応答のレスポンスヘッダーです。同名ヘッダーが複数ある場合は、カンマ区切りで連結された値として扱います。
  • この項目は追加のリクエストを送りません。下層ページやエラー応答への適用状況は、別項目の「nosniffを全応答へ適用」と「エラー応答のヘッダー整合性」で確認します。

判定条件

ヘッダー値をカンマで分割し、先頭の値の前後空白を除いて小文字化したものを評価します(Fetch Standard の解釈と同じ)。

判定条件得点への影響
○ 問題なし(pass)先頭の値が nosniff(大文字小文字は区別しない)重み2を満点で加算
× 要改善(fail)ヘッダーがない、または先頭の値が nosniff 以外(空文字、no-sniff、nosniff; mode=block など)重み2が0点
△ 要確認(warn)/対象外(na)この項目では使いません―
  • 根拠欄(evidence)には、取得したヘッダー値、またはヘッダーがない旨(「X-Content-Type-Optionsがありません。」)を表示します。
  • スコアは pass=1.00、warn=0.45、fail=0 の係数で重み付けし、対象外を除いた適用項目の範囲で計算します。この項目が × の場合、適用項目の重み合計に対して2点分を失います。

自治体サイトでの判定例

応答ヘッダー判定説明
X-Content-Type-Options: nosniff○標準的な正しい設定
X-Content-Type-Options: NOSNIFF○大文字小文字は区別されない
X-Content-Type-Options: nosniff, nosniff(Webサーバーと CMS の二重付与)○先頭の値が nosniff なのでブラウザ上は有効。ただし付与箇所の整理を推奨
X-Content-Type-Options: nosniff; mode=block×値の書式が誤っており、ブラウザは nosniff と解釈しない
ヘッダーなし(CMS 既定のまま)×未設定

MIMEスニッフィング対策がないとどんなリスクがあるか

攻撃シナリオ

  1. アップロードファイル経由の XSS:住民向けの投稿フォームや職員用 CMS の添付機能で、画像や文書に見せかけた HTML/JS 入りのファイルがアップロードされる。サーバーが不正確な Content-Type(または Content-Type なし)で配信すると、ブラウザが内容を見て HTML と判定し、サイトのオリジンでスクリプトが実行される。Cookie の窃取や、ページの書き換え、偽の手続き画面への誘導につながります。
  2. スクリプト/スタイルとしての流用:攻撃者が、サイト上の JSON やテキスト応答を <script src> や <link rel=stylesheet> で読み込ませ、型チェックが働かないことを利用して情報を引き出したり、意図しない動作を起こさせたりする。nosniff があれば、JS/CSS 以外の MIME タイプの応答はブロックされます。
  3. クロスオリジンの読み取り:nosniff と正しい Content-Type を組み合わせると、ブラウザの CORB が HTML・JSON・XML などを他オリジンの <img> や <script> 経由で読み取らせないよう保護しやすくなります。Spectre 型のサイドチャネル対策の前提にもなります。

想定される被害

  • 公式サイトのドメイン上で不正スクリプトが実行されることによる、住民や職員のセッション情報・入力情報の漏えい
  • 公式サイトの改ざん表示、偽情報の掲出による信用失墜
  • 電子申請や問い合わせフォームへの誘導を装ったフィッシング

これらは単独で必ず起きるものではありませんが、アップロード機能や外部から入力される値を扱うシステムでは、他の不備(Content-Type の誤設定、入力検証の不足)と組み合わさって被害が拡大します。nosniff は低コストでその連鎖を断つ対策です。

MIMEスニッフィング対策の設定方法(Apache・nginx・IIS・Next.js)

基本方針

  1. サーバー全体(またはリバースプロキシ・CDN)で、すべての応答に X-Content-Type-Options: nosniff を付けます。
  2. 同時に、各ファイルに正しい Content-Type が付いているかを確認します(.js は text/javascript、.css は text/css、.json は application/json など)。
  3. エラー応答(404/500)にも付くよう、Apache では always、nginx では always を指定します。

Apache(.htaccess / httpd.conf)

<IfModule mod_headers.c>
  # エラー応答にも付けるため always を指定
  Header always set X-Content-Type-Options "nosniff"
</IfModule>

# 拡張子と MIME タイプの対応を明示(不足している場合)
<IfModule mod_mime.c>
  AddType text/javascript .js .mjs
  AddType text/css .css
  AddType application/json .json
</IfModule>

<IfModule> で囲むと、mod_headers が無効な環境でも 500 エラーになりません。ただし、その場合はヘッダーも付かないため、設定後に必ず確認してください。

nginx

server {
    # always を付けると 4xx/5xx 応答にも付与される
    add_header X-Content-Type-Options "nosniff" always;
}

nginx の add_header は、下位の location に別の add_header があると上位の設定を継承しません。location ごとに add_header を書いている場合は、各ブロックにも同じ行を入れるか、共通ファイルを include してください。nginx 1.29.3 以降では add_header_inherit merge; を指定すると上位の設定も引き継がれます。

IIS(web.config)

<configuration>
  <system.webServer>
    <httpProtocol>
      <customHeaders>
        <remove name="X-Content-Type-Options" />
        <add name="X-Content-Type-Options" value="nosniff" />
      </customHeaders>
    </httpProtocol>
  </system.webServer>
</configuration>

Next.js(Vercel)

// next.config.js
module.exports = {
  async headers() {
    return [
      {
        source: "/:path*",
        headers: [{ key: "X-Content-Type-Options", value: "nosniff" }],
      },
    ];
  },
};

CMS・ホスティング

  • WordPress などの CMS では、プラグインで付与するより Web サーバー設定で付与する方が、静的ファイル(アップロードされた PDF・画像)にも確実に適用されます。
  • CDN を使う場合は CDN 側のヘッダー付与機能でも設定できます。二重付与を避け、どちらか一方に寄せます。

段階的導入とサイトを壊さないための注意点

  1. まず検証環境で付与し、ブラウザの開発者ツールのコンソールに「MIME type ... is not executable」「strict MIME type checking is enabled」などのエラーが出ないか確認します。
  2. エラーが出た場合は nosniff を外すのではなく、該当ファイルの Content-Type を修正します(古い .js が text/plain で配信されているなど)。
  3. 外部の CDN から読み込んでいる JS/CSS は、配信元の Content-Type に依存します。読み込みが止まった場合は配信元を確認します。

設定後の確認方法

# トップページ
curl -sI https://www.example.lg.jp/ | grep -i x-content-type-options
# 存在しないURL(エラー応答にも付いているか)
curl -sI https://www.example.lg.jp/not-found-check | grep -i x-content-type-options
# 静的ファイル(PDF など)
curl -sI https://www.example.lg.jp/material/files/sample.pdf | grep -i -E "content-type|x-content-type-options"

期待値は x-content-type-options: nosniff が1行だけ表示されることです。設定を変えたら、セキュリティAIチェッカーで再診断し、この項目が○になっていることを確認します。サイト全体への適用状況は「nosniffを全応答へ適用」の結果もあわせて確認してください。

よくある質問(FAQ)

X-Content-Type-Optionsに設定できる値は何ですか?

値は nosniff の1種類だけです。nosniff; mode=block や no-sniff のような書き方はブラウザに nosniff と解釈されず、セキュリティAIチェッカーでも×になります。大文字小文字は区別されないため NOSNIFF は有効です。

nosniffはHTMLページにだけ付ければよいですか?

いいえ。OWASP ASVS 5.0.0 V3.4.4はすべてのHTTP応答を対象にしています。効果が大きいのはアップロードファイル、JSON、JavaScript、CSSなどHTML以外の応答なので、静的ファイルやエラー応答にも付けます。

nosniffを付けたらスクリプトやCSSが読み込まれなくなりました。外すべきですか?

外すのではなく、該当ファイルのContent-Typeを直します。nosniffが有効だと、JavaScriptのMIMEタイプでないスクリプトや text/css でないスタイルシートはブロックされます。古い .js が text/plain で配信されていないかなどを確認してください。

X-Content-Type-Optionsヘッダーが2回出ていても問題ありませんか?

Fetch Standardでは最初の値がnosniffなら有効なので、ブラウザ上は機能し、診断でも○になります。ただしWebサーバーとCMSの両方で付与していると管理場所が分かりにくくなるため、付与箇所は1か所にまとめることを勧めます。

MIMEスニッフィング対策が未設定だとどう判定されますか?

ヘッダーがない場合、または先頭の値がnosniff以外の場合は「× 要改善」で、重み2が0点になります。この項目では△と対象外は使いません。

下層ページやエラー応答への適用も診断されますか?

この項目は入力URLの最終応答だけを評価し、追加のリクエストは送りません。複数ページでの適用率は「nosniffを全応答へ適用」、エラー応答のヘッダー整合性は「エラー応答のヘッダー整合性」という別の項目で確認します。

セキュリティAIチェッカーを利用する

この項目を含む127項目を、URLを入れるだけで無料診断します。

参考資料