Hello there, ('ω')ノ
✅ 通常のフォーム送信とファイル送信の違い
1. 📝 通常のフォーム送信
- Content-Type:
application/x-www-form-urlencoded
- 主に テキストデータ(例:名前、メールアドレスなど)を送信
📋 送信例
name=John&email=john@example.com
2. 🖼️ ファイル送信(画像・PDFなど)
- バイナリデータを送信する場合、
application/x-www-form-urlencoded
では不向き - 代わりに Content-Type: multipart/form-data が使用される
📋 送信例(抜粋)
POST /upload HTTP/1.1 Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryabc123 ------WebKitFormBoundaryabc123 Content-Disposition: form-data; name="file"; filename="image.jpg" Content-Type: image/jpeg (binary image data) ------WebKitFormBoundaryabc123--
🎯 攻撃者が悪用するポイント
✅ multipart/form-dataの特徴
- ファイル名やContent-Typeヘッダーを自由に設定できる
- 攻撃者は
filename="shell.php"
+Content-Type: image/jpeg
のように 拡張子とMIMEタイプを偽装できる
✅ サーバー側のよくあるミス
- Content-Typeヘッダーを信じて画像ファイルと判定 → 実際にはPHPスクリプト
- 拡張子チェックとContent-Typeチェックの組み合わせが中途半端
🛡️ 理解すべきポイント
- multipart/form-data自体は 正常なファイルアップロード方式
- 攻撃者は multipartの柔軟さ を利用して検証をバイパスしようとする
🎯 攻撃者の手口例
filename=avatar.jpg.php
Content-Type: image/jpeg
- 実体はPHPコード
- サーバー側がMIMEや拡張子チェックを誤ればアップロード成功
/uploads/avatar.jpg.php?cmd=whoami
→ サーバー制御権奪取
✅ 開発者側の防御策
対策 | 説明 |
---|---|
✅ MIMEだけでなくマジックバイトも確認 | 実ファイルのヘッダー情報を確認 |
✅ 拡張子+MIMEの両方検証 | 二重チェックでバイパスを防ぐ |
✅ 実行不可ディレクトリにファイルを保存 | 仮にPHPをアップロードされても実行されない |
✅ ファイル名はサーバー側でランダム化 | 攻撃者の意図したファイル名を無効化 |
🎯 まとめ
- multipart/form-dataは 便利だが攻撃者にも好都合
- ブラウザとBurp Suite等の手動リクエストでは内容が変えられる
- サーバー側の不十分なファイルタイプ検証は即座に突破される可能性がある
「標準機能=安全ではない!」 multipart/form-dataの仕組みを深く理解することで、 攻撃者の視点と守る側の視点が両方身につきます。
Best regards, (^^ゞ