Hello there, ('ω')ノ
✅ サイトがやりがちな誤ったファイル検証方法
多くのWebサイトではファイルアップロードの際に Content-Typeヘッダー(MIMEタイプ) を確認することで アップロード可否を判断しています。
🎯 例:画像ファイルのみ許可したいケース
Content-Type: image/jpeg
や
Content-Type: image/png
のみを許可。
⚠️ しかしこの方法には重大な欠陥がある!
🎭 Content-Typeは信頼できない
- この値は クライアント(ブラウザや攻撃者)側が自由に設定できます。
- Burp Suite や Repeater などを使えば 簡単に偽装できます。
📚 攻撃者の例
Content-Type: image/jpeg
と偽装しながら
実際のファイルはPHPスクリプト → shell.php
を送信。
✅ サーバー側がMIMEタイプだけを見ていると…
- サーバーは
image/jpeg
と認識 → 問題なしと判断 - 実ファイルはPHP → アップロード完了
- 攻撃者がURLから直接アクセス
- サーバーが
shell.php
を スクリプトとして実行 → RCE発生
🧠 攻撃者のバイパス戦略
手法 | 説明 |
---|---|
Content-Type偽装 | application/x-php → image/jpeg に変更 |
拡張子偽装 | shell.jpg.php , image.pHp など |
Content-Disposition偽装 | フォームデータ内のファイル名やフィールド名を変更 |
✅ 安全な検証に必要なこと
1️⃣ マジックバイト(Magic Number)の確認
- 実ファイルの先頭バイト(例:JPEGなら
FF D8 FF
)をチェック - 本物の画像データかどうかをサーバー側で確認
2️⃣ 二重検証
- 拡張子 + MIMEタイプ + マジックバイト をすべて確認
- どれか1つでも不一致ならアップロード拒否
3️⃣ 実行権限のない領域に保存
uploads/
やfiles/
ディレクトリを PHPやJSPの実行不可に設定
🎯 まとめ:MIMEタイプ信頼の危険性
サーバー側の誤信 | 攻撃者の悪用方法 |
---|---|
Content-Typeだけで検証 | 任意のContent-Typeで偽装可能 |
拡張子チェックが甘い | .jpg.php や .pHp によるバイパス |
実ファイル内容未検証 | PHPやJSPスクリプトを画像としてすり抜け |
✅ 結論
- 「Content-Typeを信じる=攻撃者を信じる」
- 安全なファイル検証には 実ファイルの構造・内容まで検証することが不可欠
「攻撃者はいつでも自由にContent-Typeを偽装できる」 サーバー側の安全設計では 「外部から送られたデータはすべて疑う」 ことが鉄則です。
Best regards, (^^ゞ