jpskill.com
🛠️ 開発・MCP コミュニティ

php-archive-extract-audit

PHPのWebアーカイブ解凍時に発生しうるZip Slip脆弱性を検知し、その危険度や修正方法、検証コードを提示するSkill。

📜 元の英語説明(参考)

PHP Web 归档解压(Zip Slip/路径穿越)审计工具。识别解压条目名如何与目标目录拼接、是否存在 base dir 约束缺失,输出可利用性分级、可观测 PoC 与修复建议(禁止省略)。

🇯🇵 日本人クリエイター向け解説

一言でいうと

PHPのWebアーカイブ解凍時に発生しうるZip Slip脆弱性を検知し、その危険度や修正方法、検証コードを提示するSkill。

※ jpskill.com 編集部が日本のビジネス現場向けに補足した解説です。Skill本体の挙動とは独立した参考情報です。

⚠️ ダウンロード・利用は自己責任でお願いします。当サイトは内容・動作・安全性について責任を負いません。

🎯 このSkillでできること

下記の説明文を読むと、このSkillがあなたに何をしてくれるかが分かります。Claudeにこの分野の依頼をすると、自動で発動します。

📦 インストール方法 (3ステップ)

  1. 1. 上の「ダウンロード」ボタンを押して .skill ファイルを取得
  2. 2. ファイル名の拡張子を .skill から .zip に変えて展開(macは自動展開可)
  3. 3. 展開してできたフォルダを、ホームフォルダの .claude/skills/ に置く
    • · macOS / Linux: ~/.claude/skills/
    • · Windows: %USERPROFILE%\.claude\skills\

Claude Code を再起動すれば完了。「このSkillを使って…」と話しかけなくても、関連する依頼で自動的に呼び出されます。

詳しい使い方ガイドを見る →
最終更新
2026-05-17
取得日時
2026-05-17
同梱ファイル
1

📖 Skill本文(日本語訳)

※ 原文(英語/中国語)を Gemini で日本語化したものです。Claude 自身は原文を読みます。誤訳がある場合は原文をご確認ください。

[スキル名] php-archive-extract-audit

PHPアーカイブ解凍パス・トラバーサル監査(php-archive-extract-audit)

PHPプロジェクトにおける「アーカイブファイルをディスクディレクトリに解凍/展開する」実装ロジックを分析します。Zip Slipのような問題に重点を置いて監査します。これは、攻撃者が巧妙に作成したアーカイブエントリ名(entry name/path)によって、最終的な書き込み先がターゲットディレクトリから逸脱する可能性がある問題です。

分類と番号付け

  • 詳細については、shared/SEVERITY_RATING.mdをご覧ください。
  • 脆弱性番号:{C/H/M/L}-ARCHIVE-{連番}

ARCHIVE Sink(必須)

アーカイブ展開の呼び出し点を特定し、追跡します。少なくとも以下を含みます。

  • ZipArchive->extractTo($destination, {value})
  • ZipArchive->extract($destination, {value})(プロジェクトがラッパーを使用している場合)
  • PharData->extractTo($destination, {value})
  • Archive_Tar->extractTo($destination, {value})(プロジェクトがPEAR/同等のラッパーを使用している場合)
  • Archive_Tar->extract($destination, {value})(プロジェクトがラッパーを使用している場合)
  • カスタム解凍ラッパー:最終的には各エントリ名に対して「destinationディレクトリに結合してディスクに書き込む」処理を行います。

必須の証拠点(強制:trace契約の整合性)

各ARCHIVEの疑わしい脆弱性について、php-route-tracerのtrace出力における## 9) Sink Evidence Type ChecklistARCHIVE行に対応する証拠要点を項目ごとに引用する必要があります(ステータスは「検証待ち」でも構いませんが、証拠の引用は必須です)。

  1. EVID_ARCHIVE_EXTRACT_CALLSITE:アーカイブ解凍/展開呼び出し点の証拠(extractTo/extractToラッパー関数のエントリ)
  2. EVID_ARCHIVE_ENTRY_NAME_SOURCE:エントリ名/パスのソース証拠(アーカイブコンテンツのエントリリスト、またはユーザー入力によって構築されたエントリパス)
  3. EVID_ARCHIVE_ENTRY_SANITIZATION:エントリパスのサニタイズ/正規化の証拠(../、絶対パス、ドライブレターなどのパス・トラバーサル・フラグメントの削除/拒否、およびエンコーディング/同形文字の処理方法)
  4. EVID_ARCHIVE_EXTRACT_BASE_DIR:解凍ベースディレクトリの証拠(destination/base directoryのソースと渡し方)
  5. EVID_ARCHIVE_FINAL_TARGET:最終的な解決済み書き込み先の証拠(エントリ結合後の解決済み最終パス、およびベースディレクトリ制約の判定が成立するかどうか)

悪用可能性と脆弱性成立条件(必須)

以下を出力し、判断する必要があります。

  • エントリ名/パスが攻撃者によって制御可能かどうか(少なくとも攻撃者が作成したzipの項目から)
  • ベースディレクトリ制約が「最終パス解決後」に実際に実行されているかどうか(例:realpath + プレフィックス検証であり、単なる文字列置換ではない)
  • 回避策が存在するかどうか:二重エンコーディング、混合区切り文字、Windowsドライブレター、絶対パス、末尾/空白/制御文字、Unicode同形文字など
  • 書き込みが実際にターゲットディレクトリ外で発生しているかどうか(または少なくとも最終ターゲットが逸脱していることを証明できるかどうか)

tracerトリガー条件(必須)

以下のいずれかの条件を満たす場合、php-route-tracerに依存する必要があります。

  • destination/base directoryまたはエントリ名が多層の関数/オブジェクトラッパーを介してextractToに入る場合
  • エントリ名リストまたは解凍パスに分岐ロジックが存在する場合(特定のエントリのみがフィルタリングされる/特定の分岐がフィルタリングされない)

レポート出力

以下に出力します。

{output_path}/vuln_audit/archive_{timestamp}.md

脆弱性項目テンプレート(強制)

各脆弱性は以下の構造に従う必要があります(省略不可)。

### [{等級プレフィックス}-ARCHIVE-{連番}] アーカイブ解凍パス・トラバーサル(Zip Slip)リスク

| 項目 | 情報 |
|------|------|
| 深刻度 | {🔴/🟠/🟡/🔵} (CVSS {score}) |
| 可達性 (R) | {0-3} - {理由} |
| 影響範囲 (I) | {0-3} - {理由} |
| 利用複雑度 (C) | {0-3} - {理由} |
| 悪用可能性 | ✅ 確認済み / ⚠️ 検証待ち / ❌ 悪用不可 / 🔍 環境依存 |
| 位置 | {file}:{line} ({Function/Class}) |

#### データフローチェーン(Source -> Transform -> Sink)
(各行に記述:アーカイブエントリ名/パスの入力 -> サニタイズ/正規化 -> ベースデスティネーション結合 -> 解決済み最終ターゲット -> ベース制約からの逸脱の有無 -> 実際の書き込み/展開呼び出し点)

#### 悪用可能な前提条件
- 認証要件:{不要/ログイン必要/特定の権限必要}
- 入力制御性:{完全に制御可能/条件付きで制御可能/制御不可}
- トリガー条件:{分岐/例外パス/特定のアーカイブ形式が必要/特定のサーバーファイル権限が必要}

#### 証拠引用(強制:php-route-tracerから)
以下を項目ごとに引用する必要があります。
- `EVID_ARCHIVE_EXTRACT_CALLSITE`:{証拠点の簡単な説明}
- `EVID_ARCHIVE_ENTRY_NAME_SOURCE`:{証拠点の簡単な説明}
- `EVID_ARCHIVE_ENTRY_SANITIZATION`:{証拠点の簡単な説明(欠落している場合は「フィルタリング/正規化の不足が未発見」と記述し、trace証拠を提示)}
- `EVID_ARCHIVE_EXTRACT_BASE_DIR`:{証拠点の簡単な説明}
- `EVID_ARCHIVE_FINAL_TARGET`:{証拠点の簡単な説明(解決済みターゲットが逸脱しているかどうかを説明)}

#### 検証PoC(強制:観測可能な検証フレームワーク)
```http
{HTTP Method} {実際のルートと完全なパラメータ} HTTP/1.1
Host: {host}
{必要なHeader/Session/JWT/Cookie}

{Payload}

PoC生成/トリガー戦略(何を観察するかを明確に記述する必要があります):

  • パス・トラバーサル・エントリを含む悪意のあるアーカイブを作成します。例:../../../../var/www/html/pwn.php(またはWindowsパスのバリアント)
  • 解凍ルートをトリガーします(通常はアーカイブのアップロード、またはダウンロード可能なURLを提供してサーバー側で解凍)。
  • 観察点:ターゲットディレクトリ外にファイルが出現するかどうか、書き込み先にアクセスできるかどうか(サイトの権限/書き込み可能ディレクトリポリシーによる)。

推奨される修正

  • 「最終的な解決済み書き込み先」を基準とします:エントリ名を正規化した後、realpath + ベースプレフィックス検証を実行します。
  • 絶対パス/ドライブレター/バックスラッシュ区切り/ディレクトリの上位移動を禁止します:エントリ名にトラバーサル・フラグメントが発見された場合は、直接拒否またはスキップします。
  • アーカイブ処理フローにおいて、エントリ名リストを一元的にサニタイズし、解凍プロセスに一貫したベース制約を強制します。
  • コード検索ステートメントを提示します:rgを使用して、すべてのextractTo/extract/アーカイブ解凍ラッパーのエントリとdestination結合ロジックを特定します。

tracer証拠欠落の処理(強制)

  • traceにおいて、いずれかの主要な証拠点(EVID_ARCHIVE_EXTRACT_CALLSITE / EVID_ARCHIVE_ENTRY_NAME_SOURCE / EVID_ARCHIVE_ENTRY_SANITIZATION / EVID_ARCHIVE_EXTRACT_BASE_DIR / EVID_ARCHIVE_FINAL_TARGET)が欠落しているか、この脆弱性に対応できない場合:その脆弱性のステータスは⚠️検証待ちとしかマークできず、直接✅悪用可能と確認済みとすることはできません。
📜 原文 SKILL.md(Claudeが読む英語/中国語)を展開

PHP 归档解压路径穿越审计(php-archive-extract-audit)

分析 PHP 项目中“解压/提取归档文件到磁盘目录”的实现逻辑。重点审计 Zip Slip 类问题:攻击者可通过精心构造归档条目名(entry name/path)使最终写入落点逃逸目标目录。

分级与编号

  • 详见:shared/SEVERITY_RATING.md
  • 漏洞编号:{C/H/M/L}-ARCHIVE-{序号}

ARCHIVE Sink(必做)

识别并追踪归档提取调用点,至少包括:

  • ZipArchive->extractTo($destination, {value})
  • ZipArchive->extract($destination, {value})(若项目使用封装)
  • PharData->extractTo($destination, {value})
  • Archive_Tar->extractTo($destination, {value})(若项目使用 PEAR/等价封装)
  • Archive_Tar->extract($destination, {value})(若项目使用封装)
  • 自定义解压封装:最终仍对每个 entry name 做“拼接到 destination 目录并落盘”

必检证据点(强制:trace 契约对齐)

每条 ARCHIVE 疑似漏洞必须逐项引用 php-route-tracer trace 输出中 ## 9) Sink Evidence Type ChecklistARCHIVE 行对应证据要点(允许状态为待验证,但证据引用必须存在):

  1. EVID_ARCHIVE_EXTRACT_CALLSITE:归档解压/提取调用点证据(extractTo/extractTo 包装函数入口)
  2. EVID_ARCHIVE_ENTRY_NAME_SOURCE:entry name/path 来源证据(来自归档内容的 entry 列表,或由用户输入构造的条目路径)
  3. EVID_ARCHIVE_ENTRY_SANITIZATION:条目路径净化/归一化证据(去除/拒绝 ../、绝对路径、盘符等路径穿越片段;以及如何处理编码/同形字符)
  4. EVID_ARCHIVE_EXTRACT_BASE_DIR:解压基目录证据(destination/base directory 的来源与传入方式)
  5. EVID_ARCHIVE_FINAL_TARGET:最终解析落点证据(entry join 后的 resolved final path,以及 base 目录约束判定是否成立)

可利用性与漏洞成立条件(必做)

必须输出并判断:

  • entry name/path 是否可被攻击者控制(至少来自 attacker's crafted zip 的条目)
  • 基目录约束是否真正执行到“最终路径解析之后”(例如 realpath + 前缀校验,而不是仅字符串替换)
  • 是否存在绕过:双重编码、混合分隔符、windows 盘符、绝对路径、尾部/空白/控制字符、Unicode 同形字符等
  • 写入是否真的发生在目标目录之外(或至少能够证明 final target 逃逸)

tracer 触发条件(必做)

当满足任一条件时必须依赖 php-route-tracer

  • destination/base directory 或 entry name 经过多层函数/对象封装后才进入 extractTo
  • entry name 列表或解压路径存在分支逻辑(某些 entry 才被过滤/某些分支未过滤)

报告输出

输出到:

{output_path}/vuln_audit/archive_{timestamp}.md

漏洞条目模板(强制)

每条漏洞必须遵循以下结构(不得省略):

### [{等级前缀}-ARCHIVE-{序号}] 归档解压路径穿越(Zip Slip)风险

| 项目 | 信息 |
|------|------|
| 严重等级 | {🔴/🟠/🟡/🔵} (CVSS {score}) |
| 可达性 (R) | {0-3} - {理由} |
| 影响范围 (I) | {0-3} - {理由} |
| 利用复杂度 (C) | {0-3} - {理由} |
| 可利用性 | ✅ 已确认 / ⚠️ 待验证 / ❌ 不可利用 / 🔍 环境依赖 |
| 位置 | {file}:{line} ({Function/Class}) |

#### 数据流链(Source -> Transform -> Sink)
(逐行写出:归档 entry name/path 进入 -> 净化/归一化 -> base destination join -> resolved final target -> 是否逃逸 base 约束 -> 实际写入/提取调用点)

#### 可利用前置条件
- 鉴权要求:{无需/需登录/需特定权限}
- 输入可控性:{完全可控/条件可控/不可控}
- 触发条件:{分支/异常路径/需要特定归档格式/需要特定服务器文件权限}

#### 证据引用(强制:来自 php-route-tracer)
必须逐项引用:
- `EVID_ARCHIVE_EXTRACT_CALLSITE`:{证据点简述}
- `EVID_ARCHIVE_ENTRY_NAME_SOURCE`:{证据点简述}
- `EVID_ARCHIVE_ENTRY_SANITIZATION`:{证据点简述(缺失则写“未发现过滤/归一化不足”并给出 trace 证据)}
- `EVID_ARCHIVE_EXTRACT_BASE_DIR`:{证据点简述}
- `EVID_ARCHIVE_FINAL_TARGET`:{证据点简述(说明 resolved target 是否逃逸)}

#### 验证 PoC(强制:可观测验证框架)
```http
{HTTP Method} {真实路由与完整参数} HTTP/1.1
Host: {host}
{必要 Header/Session/JWT/Cookie}

{Payload}

PoC 生成/触发策略(必须写清楚你要观察什么):

  • 制作恶意归档,包含路径穿越 entry,例如 ../../../../var/www/html/pwn.php(或 Windows 路径变体)
  • 触发解压路由(通常是上传归档/或提供可下载 URL 后由服务端解压)
  • 观察点:目标目录之外是否出现文件、是否能访问到落点(取决于站点权限/可写目录策略)

建议修复

  • 以“最终解析落点”为准:对 entry name 做规范化后执行 realpath + base 前缀校验
  • 禁止 absolute path/盘符/反斜杠分隔/目录上跳:entry name 发现穿越片段直接拒绝或跳过
  • 在归档处理流程中对 entry name 列表做统一净化,并对解压过程强制一致的 base 约束
  • 给出代码搜索语句:rg 定位所有 extractTo/extract/归档解压封装入口与 destination 拼接逻辑

tracer 证据缺失处理(强制)

  • 若 trace 中任一关键证据点(EVID_ARCHIVE_EXTRACT_CALLSITE / EVID_ARCHIVE_ENTRY_NAME_SOURCE / EVID_ARCHIVE_ENTRY_SANITIZATION / EVID_ARCHIVE_EXTRACT_BASE_DIR / EVID_ARCHIVE_FINAL_TARGET)缺失或无法对应到本条漏洞:该条漏洞状态只能标记为 ⚠️待验证,不得直接给出 ✅已确认可利用