拡張子はただの名札なのか

概要 — まず全体をつかむ

初級で「名札(拡張子)・中身(0と1)・読み方(形式)・担当(アプリ)」の4点セットを、中級で「中身側の証拠(マジックナンバー)」と「Webの宣言(MIMEタイプ)」を見ました。上級では、その裏側で中身をどう見破っているかを機構レベルまで下ろします。到達点は一つ——「拡張子は宣言に過ぎず、中身を保証しない」を、攻撃の手口まで含めて説明できることです。

用語には「※1・※2…」と番号を付け、各セクション末尾の「登場人物メモ」で説明します。セクションは初級・中級と id を揃えてあります。

アニメーション『ダブルクリックの3秒』を開く
あなたOSアプリファイルの中身
  • あなたファイルをダブルクリックする人
  • OS名札(拡張子)を見て、開く係を決める世話役
  • アプリそのファイルの「読み方」を知っている担当者
  • ファイルの中身実体はどれもただの0と1の列。読み方を知る係が必要
「▶ 再生」で通しで見るか、「次へ」で1手ずつ進めてください。
0 / 7

詳細 — 1段階ずつ追う

① 名札を見る — 中身側の証拠を読む

🎬 アニメーション『ダブルクリックの3秒』の のところです!

上級では「名札を信じない」立場から、種別を確かめる3系統を精密にします。

  1. 拡張子 — ファイル名の末尾。送り手が自由に付けられる自己申告で、証拠能力はない
  2. マジックナンバー※1 — ファイル先頭の固定バイト列。形式の仕様が定めた署名で、中身に埋まっている物証
  3. MIMEタイプ※2 — 「型/サブ型」の正式名。通信(HTTPのContent-Typeヘッダ)やアプリ間で形式を伝える宣言

種別を厳密に判定したいプログラムは、名札ではなく先頭バイトを読む。UNIX系の file コマンドや、サーバのアップロード検証がこれです。拡張子・マジックナンバー・MIMEタイプは互いに独立しており、一致する保証はない——その隙間こそが、後で見る偽装の余地になります。

登場人物メモ(※の説明):

  • ※1 マジックナンバー(ファイルシグネチャ) — PNGは 89 50 4E 47、ZIPは 50 4B、PDFは %PDF、ELF実行形式は 7F 45 4C 46 など、形式ごとに決まった先頭バイト列。中身側の物証
  • ※2 MIMEタイプ(メディアタイプ)image/png text/html のような「大分類/小分類」表記。名前の由来はメール(Multipurpose Internet Mail Extensions)だが、今はWeb全体の標準

⚠️ イレギュラー(3つの証言が食い違うとき):

  • 署名を持たない形式 — プレーンテキストやCSVには決まった先頭署名がない。中身推測に頼るしかなく、判定が曖昧になる
  • 署名を偽装したファイル — 先頭に本物の署名を貼り付けつつ、後続に別の中身を仕込むこともできる。署名の一致は「入口の一致」であって、全体の安全ではない

中身が結局すべて0と1であることは 2進数とデータ を参照。

やさしく言うと(中級

🎬 アニメーション『ダブルクリックの3秒』の のところです!

名札は拡張子だけではありません。世界には3種類の「種別の伝え方」があります:

  1. 拡張子 — ファイル名の一部。OSのダブルクリック判定が見る(自己申告)
  2. マジックナンバー※1 — ファイル先頭の決まったバイト列。中身側の証拠で、file コマンドやアップロード検証が見る
  3. MIMEタイプ※2 — Webの世界の種別宣言。HTTPレスポンスの Content-Type ヘッダで配信側が宣言し、ブラウザはこれに従う

登場人物メモ(※の説明):

  • ※1 マジックナンバー — PNGなら 89 50 4E 47、ZIPなら 50 4B、PDFなら %PDF など、形式ごとの署名。名札と違って中身に埋まっている
  • ※2 MIMEタイプtext/html image/png のような「大分類/小分類」表記。名前の由来はメールだが、今はWeb全体の標準

⚠️ イレギュラー(3つの証言が食い違うとき):

  • 名札と中身の不一致 — 拡張子は .png なのに先頭バイトはJPEG、のようなファイルは検証のあるシステムで弾かれる。逆に検証しないシステムは偽装ファイルの侵入口になる
  • ブラウザの推測(MIMEスニッフィング) — 宣言が曖昧なとき、ブラウザが中身から推測する機能。便利だが「テキストのふりをした攻撃コード」の実行につながるため、無効化を宣言するヘッダ(X-Content-Type-Options: nosniff)が存在する

② 対応表を引く — 関連付けの機構

🎬 アニメーション『ダブルクリックの3秒』の ③〜④ のところです!

「拡張子→アプリ」の対応表を、OSは具体的にどこに持っているか。機構はOSごとに違います。

  1. Windowsレジストリ(設定を集約した階層データベース)に「拡張子→ファイルタイプ→開くアプリ」を記録する。.pdf の担当変更は、この階層の書き換え
  2. Linuxxdg-mime の仕組み。拡張子や中身からMIMEタイプを求め、mimeapps.list で「このMIMEタイプ→この既定アプリ」を引く。拡張子を直接ではなく、いったんMIMEタイプを介すのが特徴
  3. macOS — かつてのUTI※1(形式の抽象的な型)とLaunchServices※2 が、拡張子・種別・担当アプリを対応づける
  4. どのOSでも、コマンドラインや「プログラムから開く」は表を経由せず、任意のアプリに任意のファイルを渡せる

共通する構図は「関連付けはファイルではなくOSのローカル設定」。だから同じ拡張子でも人のPCで担当アプリが違い、世界共通の一元データベースは存在しません。

登場人物メモ(※の説明):

  • ※1 UTI — Uniform Type Identifier。macOSが使う「形式の型」の識別子。拡張子やMIMEタイプを一段抽象化したもの
  • ※2 LaunchServices — macOSで「どの種別をどのアプリが開くか」を管理する仕組み

⚠️ イレギュラー(関連付けまわりの事故):

  • 既定アプリの乗っ取り — インストール時に関連付けを一斉に自分へ向けるお行儀の悪いソフトがある。急に開くアプリが変わったらここを疑う
  • MIMEと拡張子のズレ(Linux/Web) — MIMEタイプを軸にする機構では、拡張子と中身から求めたMIMEタイプが食い違うと、意図しないアプリが選ばれることがある

OSがアプリを起動して橋渡しする流れは アプリとOS を参照。

やさしく言うと(中級

🎬 アニメーション『ダブルクリックの3秒』の ③〜④ のところです!

OSの対応表と、その周辺の実装です:

  1. OSは「拡張子 → 既定のアプリ」の対応表を持つ(Windowsはレジストリ、macはLaunchServicesが管理)
  2. 「常にこのアプリで開く」は、この表の1行の書き換え
  3. アプリをインストールすると、アプリが「自分は .pdf を開けます」と候補登録する——既定を奪い合う通知が出るのはこのため
  4. ダブルクリック以外の入り口(コマンドラインや「プログラムから開く」)は表を経由せず、任意のアプリに任意のファイルを渡せる

⚠️ イレギュラー(対応表まわりの事故):

  • 既定アプリの乗っ取り — インストール時に関連付けを一斉に自分へ向けるお行儀の悪いソフトがある。急に開くアプリが変わったらここを疑う
  • 二重拡張子 + 非表示設定 — 初級で見た「請求書.pdf.exe」。OSの既定が拡張子非表示だと成立してしまうので、表示設定が対策になる

③ アプリが解読する — 宣言と中身のどちらを信じるか

🎬 アニメーション『ダブルクリックの3秒』の ⑤〜⑦ のところです!

担当が中身を読む段でも、「宣言(拡張子・ヘッダ)」と「物証(中身)」のどちらを信じるかで挙動が変わります。

  1. きちんとしたアプリは、まず中身の署名や構造を検証してから解読する(宣言を鵜呑みにしない)
  2. Webのブラウザは原則、配信側が宣言したMIMEタイプに従って扱いを決める
  3. ただし宣言が曖昧・欠落のとき、ブラウザが中身から種別を推測するMIMEスニッフィング※1 が働くことがある
  4. スニッフィングは便利だが、「テキストのふりをしたスクリプト」を実行扱いにしてしまう危険があり、推測を禁じる宣言(X-Content-Type-Options の nosniff)で無効化できる

つまり「中身を見破る」には二つの態度がある——宣言を信じて速くするか、中身を検証して安全にするか。上級のシステム設計は、この綱引きの上に立っています。

登場人物メモ(※の説明):

  • ※1 MIMEスニッフィング — 宣言されたMIMEタイプが曖昧なとき、ブラウザが中身の先頭を覗いて種別を推測する機能。利便と危険の両面を持つ

⚠️ イレギュラー(解読の判断ミス):

  • 推測の悪用 — 攻撃者は「無害な型に見せかけつつ、ブラウザに危険な型と推測させる」ことを狙う。nosniff はこの推測経路を塞ぐ防御
  • 宣言と中身の不一致 — 宣言は image/png なのに中身がHTML、のようなファイルは、検証するシステムでは弾かれ、検証しないシステムでは侵入口になる
やさしく言うと(中級

🎬 アニメーション『ダブルクリックの3秒』の ⑤〜⑦ のところです!

「読み方の決まり」の実名はファイルフォーマット仕様です。解読には層があります:

  1. まず大きくテキストバイナリ※1 かに分かれる
  2. テキストの解読には文字コード※2 が要る——「このバイト列はこの文字」の対応表。UTF-8 が現在の標準で、Shift_JIS などの旧規格と取り違えると文字化けになる(データは無傷、読み方の取り違え)
  3. バイナリは形式ごとの仕様書どおりに解読する。多くの形式は圧縮※3 も組み込んでいて、可逆(ZIP・PNG)と非可逆(JPEG・MP3)で性格が違う
  4. 変換(.jpg → .png)とは、デコードして別の決まりで再エンコードすること。改名では起きない

登場人物メモ(※の説明):

  • ※1 テキスト / バイナリ — 文字コード表だけで人間が読める形式か、専用の仕様書が要る形式かの大別
  • ※2 文字コード — バイト列と文字の対応表。UTF-8 / Shift_JIS / EUC-JP など。取り違え=文字化け
  • ※3 可逆 / 非可逆圧縮 — 完全に戻せる圧縮(ZIP・PNG)と、知覚しにくい情報を捨てて縮める圧縮(JPEG・MP3)。非可逆は保存のたびに劣化が積む

⚠️ イレギュラー(解読の事故):

  • 文字化け — 原因は必ず「書いた文字コード ≠ 読んだ文字コード」。正しいコードで開き直せば直る(データは壊れていない)
  • JPEGの再保存劣化 — 非可逆圧縮を重ね掛けするたび情報が捨てられる。編集の元データはPNG等の可逆形式で持つのが定石
「fileコマンド」で中身の正体を見る

Linux/Macのターミナルで file 名前 と打つと、拡張子を無視してマジックナンバーから種別を判定してくれます。cat.txt に改名した画像も JPEG image data と見破ります。名札(拡張子)・中身(マジックナンバー)・読み方(フォーマット)が別物であることを、手元で1分で確認できる実験です。

まとめ——種別の証言は名札(拡張子)/ 中身の署名(マジックナンバー)/ Webの宣言(MIMEタイプ)の3系統あり、食い違いこそがトラブルと攻撃の源でした。そして解読の最下層には文字コードと圧縮がいる。「開けない・化ける・劣化する」は全部、この地図のどこかで説明がつきます。

拡張子偽装という攻撃

ここが上級の核心です。拡張子は「実行するか/どう扱うか」の判断に効くのに、中身を保証しない——この非対称が攻撃に使われます。手口は「表示と実体のズレ」を突くのが共通点です。

  1. 二重拡張子 — 「請求書.pdf.exe」。効くのは最後の .exe だけで、正体はPDFを装った実行プログラム。OSの既定が拡張子非表示だと「請求書.pdf」に見え、成立してしまう
  2. RLO(右書き制御文字)※1 — ファイル名に見えない制御文字を1つ挟むと、そこから先の表示の向きだけが反転する。目には .pdf などに見えるのに、OSが扱う実際の拡張子は末尾の実行形式のまま
  3. 紛らわしい名前 — 「写真.jpg     .exe」のように空白を大量に入れ、末尾の実体を画面外へ追いやる古典手口
  4. いずれも中身も関連付けも変えていない。変えたのは「人間の目に映る名札」だけ——だから対策も「拡張子を常に表示する」「中身で判定する」に行き着く

登場人物メモ(※の説明):

  • ※1 RLO — Right-to-Left Override(U+202E)。「以降を右から左へ表示せよ」という制御文字。アラビア語などの表示用だが、拡張子偽装に悪用される

⚠️ イレギュラー(偽装を見抜くには):

  • 拡張子を常に表示する設定にする — 二重拡張子・空白詰めはこれだけで大半が見える
  • 中身(マジックナンバー)で判定するfile コマンドや検証付きのシステムは、名札を無視して物証を見るので偽装に強い
  • 未知のファイルは隔離環境で扱う — 名札の真偽に関係なく、危険な中身は実行させない構え(サンドボックス)が最後の砦

こうした手口の全体像は 攻撃の種類マルウェア を参照。

⚠️ 上級の落とし穴

  • 拡張子を検証と取り違える — 拡張子チェックは「宣言の確認」であって「中身の検証」ではない。アップロード受け入れはマジックナンバーと構造で確かめる
  • 署名さえ合えば安全という誤解 — 先頭署名の一致は入口の一致にすぎない。後続に危険な中身を仕込む余地は残る
  • MIMEスニッフィングを無防備に放置 — 宣言を曖昧にしたまま配信すると、ブラウザの推測が攻撃経路になる。nosniff と正確なMIMEタイプ宣言で塞ぐ
  • 拡張子非表示のまま運用 — 二重拡張子・RLO・空白詰めは、非表示設定が成立条件。表示に切り替えるだけで多くが露見する
  • 関連付けを世界共通と思い込む — 対応表はOSのローカル設定。自分のPCで安全に開けたことは、他人の環境の安全を意味しない

関連する知識

理解度チェック

そのまま解けます(成績は保存されません)。無料アカウントを作ると、学習の記録と進捗の山登りが始まります。

1. 通信やアプリ間で形式を伝える「MIMEタイプ」の説明として正しいものはどれ?

2. 「請求書‮fdp.exe」のようにRLO(右書き制御文字)を使った拡張子偽装がある。RLOは何をしている?

3. 「拡張子が .txt なら安全」と考えるのが危険な理由として、最も適切なものはどれ?

4. 宣言されたMIMEタイプが曖昧なとき、ブラウザが中身の先頭から種別を推測する機能と、その危険を封じる手段の組み合わせとして正しいのはどれ?

5. アップロードされたファイルの先頭バイトが正しいPNG署名と一致した。このことから確実に言えるのはどれ?

6. ファイル先頭に埋め込まれた形式ごとの署名バイト列を「マジックナンバー」と呼ぶが、その別名(○○シグネチャ)を答えてください。

7. サーバがアップロードされた画像を受け取るとき、「本当に画像か」を確かめる最も確実な方法はどれ?

8. 「この拡張子はこのアプリで開く」という関連付けを管理している仕組みについて、正しいものはどれ?