$npx -y skills add 0xShe/PHP-Code-Audit-Skill --skill php-file-upload-audit---
| 1 | # PHP 文件上传审计(php-file-upload-audit) |
| 2 | |
| 3 | |
| 4 | |
| 5 | |
| 6 | |
| 7 | ## 统一执行策略(强制) |
| 8 | |
| 9 | |
| 10 | |
| 11 | |
| 12 | |
| 13 | 必须遵循:`shared/PHP_AUDIT_EXECUTION_POLICY.md`。 |
| 14 | |
| 15 | |
| 16 | |
| 17 | |
| 18 | |
| 19 | 执行时统一采用“双通道 + 证据分层”规则: |
| 20 | |
| 21 | |
| 22 | |
| 23 | |
| 24 | |
| 25 | - 高召回通道:先做静态 `source/sink` 初筛,覆盖 HTTP 路由与非路由入口(CLI/cron/queue/include) |
| 26 | |
| 27 | |
| 28 | |
| 29 | |
| 30 | |
| 31 | - 高置信通道:再用 `trace/EVID` 做确认与降噪 |
| 32 | |
| 33 | |
| 34 | |
| 35 | |
| 36 | |
| 37 | 状态判定统一为:`✅已确认 / 🟡高概率 / ⚠️待验证 / ❌不可利用 / 🔍环境依赖` |
| 38 | |
| 39 | |
| 40 | |
| 41 | |
| 42 | |
| 43 | - 满足最小证据集(可达片段 + 可控线索 + sink 触发线索)=> 可标记 `🟡高概率` |
| 44 | |
| 45 | |
| 46 | |
| 47 | |
| 48 | |
| 49 | - 满足完整 trace + EVID => 标记 `✅已确认` |
| 50 | |
| 51 | |
| 52 | |
| 53 | |
| 54 | |
| 55 | - 证据不足 => 标记 `⚠️待验证` |
| 56 | |
| 57 | |
| 58 | |
| 59 | |
| 60 | |
| 61 | 严谨性要求保持不变,但不得因 trace 不完整而沉默:仍需输出疑似高危与缺失证据。 |
| 62 | |
| 63 | |
| 64 | |
| 65 | |
| 66 | |
| 67 | 分析 PHP 项目源码,识别文件上传逻辑:`$_FILES`、`move_uploaded_file` 等,追踪保存目录与文件名处理方式,检测: |
| 68 | |
| 69 | |
| 70 | |
| 71 | |
| 72 | |
| 73 | - 任意文件上传(任意类型/任意扩展名) |
| 74 | |
| 75 | |
| 76 | |
| 77 | |
| 78 | |
| 79 | - 路径穿越(使用原始文件名拼接) |
| 80 | |
| 81 | |
| 82 | |
| 83 | |
| 84 | |
| 85 | - 可执行文件上传(上传到 Web 可访问目录且未限制执行) |
| 86 | |
| 87 | |
| 88 | |
| 89 | |
| 90 | |
| 91 | - 覆盖/同名冲突风险 |
| 92 | |
| 93 | |
| 94 | |
| 95 | |
| 96 | |
| 97 | |
| 98 | ## 统一审计标准(强制) |
| 99 | 必须遵循:`shared/PHP_AUDIT_UNIFIED_STANDARD.md`。 |
| 100 | |
| 101 | 状态顺序必须固定为:`✅已确认 / 🟡高概率 / ⚠️待验证 / ❌不可利用 / 🔍环境依赖`。 |
| 102 | trace 证据判定必须分层执行: |
| 103 | - 满足最小证据集(入口可达 + 参数可控链路 + sink 执行线索 + 基本前置条件)=> `🟡高概率` |
| 104 | - 满足完整证据集(trace COMPLETE + EVID 对齐 + 分支覆盖)=> `✅已确认` |
| 105 | - 不满足最小证据集 => `⚠️待验证` |
| 106 | |
| 107 | 误报抑制必须检查:硬编码覆盖、白名单生效、不可达分支、沙箱/权限边界。 |
| 108 | 漏报抑制必须执行:trace 不全不沉默、sink-only 回退。 |
| 109 | 输出最小字段必须包含:位置、source->sink、前置条件、状态、PoC、修复。 |
| 110 | 执行优先级必须遵循:先发现、后文档。 |
| 111 | |
| 112 | ## 证据置信度字段与复核清单(强制) |
| 113 | 证据置信度字段(强制):按 `shared/PHP_AUDIT_UNIFIED_STANDARD.md` 输出 HIGH/MEDIUM/LOW,并给出判定依据(与状态一致)。 |
| 114 | 复核清单(强制,至少 5 项): |
| 115 | - 是否已执行高召回通道(阶段0)或已启用 sink-only 回退,并覆盖非路由入口 |
| 116 | - 是否完成同类扩展检查(命中某类 upload sink 后横向扫同类入口/保存封装) |
| 117 | - 是否按最小证据集/完整证据集规则给出 🟡高概率/✅已确认/⚠️待验证,并说明缺失点 |
| 118 | - 是否明确 source->sink 数据流链到文件名解析/扩展名净化/落点拼接/访问可达性 |
| 119 | - 是否对误报抑制做了硬编码/白名单/不可达/权限边界/格式不成立说明 |
| 120 | - 是否给出可执行 PoC 与可替换修复建议(含随机化策略/MIME 校验/访问面限制/搜索定位要点) |
| 121 | |
| 122 | ## 分级与编号 |
| 123 | |
| 124 | |
| 125 | |
| 126 | |
| 127 | |
| 128 | - 详见:`shared/SEVERITY_RATING.md` |
| 129 | |
| 130 | |
| 131 | |
| 132 | |
| 133 | |
| 134 | - 漏洞编号:`{C/H/M/L}-UPLOAD-{序号}` |
| 135 | |
| 136 | |
| 137 | |
| 138 | |
| 139 | |
| 140 | ## 上传入口识别(必做) |
| 141 | |
| 142 | |
| 143 | |
| 144 | |
| 145 | |
| 146 | 识别: |
| 147 | |
| 148 | |
| 149 | |
| 150 | |
| 151 | |
| 152 | - `$_FILES['{value}']` 字段 |
| 153 | |
| 154 | |
| 155 | |
| 156 | |
| 157 | |
| 158 | - `move_uploaded_file($_FILES['{value}']['tmp_name'], $dest)` |
| 159 | |
| 160 | |
| 161 | |
| 162 | |
| 163 | |
| 164 | - 保存路径拼接:`$uploadDir.$filename`、`sprintf`、`join` 等 |
| 165 | |
| 166 | |
| 167 | |
| 168 | |
| 169 | |
| 170 | - 重命名:`uniqid`/`random_bytes`/时间戳(若仍可控 filename 仍高危) |
| 171 | |
| 172 | |
| 173 | |
| 174 | |
| 175 | |
| 176 | ## 校验逻辑审计(必做) |
| 177 | |
| 178 | |
| 179 | |
| 180 | |
| 181 | |
| 182 | 必须逐点检查并输出证据: |
| 183 | |
| 184 | |
| 185 | |
| 186 | |
| 187 | |
| 188 | - 扩展名/白名单:是否只校验后缀(可绕过) |
| 189 | |
| 190 | |
| 191 | |
| 192 | |
| 193 | |
| 194 | - 扩展名解析安全:是否存在“双后缀/多点后缀”绕过(如 `a.php.jpg`、`.pHp` 大小写绕过、尾部空白/Unicode 分隔符) |
| 195 | |
| 196 | |
| 197 | |
| 198 | |
| 199 | |
| 200 | - MIME/魔数:是否做 `finfo_file`/`mime_content_type`/文件头识别 |
| 201 | |
| 202 | |
| 203 | |
| 204 | |
| 205 | |
| 206 | - MIME/魔数一致性:是否检查“服务端实际内容类型”与“扩展名/后缀”是否一致(避免仅信任 `Content-Type`) |
| 207 | |
| 208 | |
| 209 | |
| 210 | |
| 211 | |
| 212 | - 文件名净化:是否去除路径分隔符与危险字符(`../`、`\`、`:`、空字节等) |
| 213 | |
| 214 | |
| 215 | |
| 216 | |
| 217 | |
| 218 | - 上传目录:是否在 Web 根目录;是否有执行权限控制 |
| 219 | |
| 220 | |
| 221 | |
| 222 | |
| 223 | |
| 224 | - 写入后可访问性链:是否存在上传目录的静态映射/直链访问(需要结合路由或 webserver 配置证据) |
| 225 | |
| 226 | |
| 227 | |
| 228 | |
| 229 | |
| 230 | - 鉴权:上传接口是否受保护 |
| 231 | |
| 232 | |
| 233 | |
| 234 | |
| 235 | |
| 236 | ## tracer 触发条件(必做) |
| 237 | |
| 238 | |
| 239 | |
| 240 | |
| 241 | |
| 242 | - 保存路径或文件名经过多层封装函数 |
| 243 | |
| 244 | |
| 245 | |
| 246 | |
| 247 | |
| 248 | - 校验逻辑存在分支,难以确认对所有上传路径生效 |
| 249 | |
| 250 | |
| 251 | |
| 252 | |
| 253 | |
| 254 | ## 报告输出 |
| 255 | |
| 256 | |
| 257 | |
| 258 | |
| 259 | |
| 260 | 输出到: |
| 261 | |
| 262 | |
| 263 | |
| 264 | |
| 265 | |
| 266 | ``` |
| 267 | |
| 268 | |
| 269 | |
| 270 | |
| 271 | |
| 272 | {output_path}/vuln_audit/upload_{timestamp}.md |
| 273 | |
| 274 | |
| 275 | |
| 276 | |
| 277 | |
| 278 | ``` |
| 279 | |
| 280 | |
| 281 | |
| 282 | |
| 283 | |
| 284 | ## 漏洞条目模板(强制) |
| 285 | |
| 286 | |
| 287 | |
| 288 | |
| 289 | |
| 290 | 必须包含: |
| 291 | |
| 292 | |
| 293 | |
| 294 | |
| 295 | |
| 296 | - 位置证据(保存/校验函数位置) |
| 297 | |
| 298 | |
| 299 | |
| 300 | |
| 301 | |
| 302 | - 数据流链(filename/path 来源 -> 校验 -> 目标路径 -> 写入) |
| 303 | |
| 304 | |
| 305 | |
| 306 | |
| 307 | |
| 308 | - 证据引用(来自 `php-route-tracer` 输出,必须逐项引用):必须对应并引用 trace 的 `## 9) Sink Evidence Type Checklist`(UPLOAD 行)中的证据要点 |
| 309 | |
| 310 | |
| 311 | |
| 312 | |
| 313 | |
| 314 | - `EVID_UPLOAD_DESTPATH`:destPath(保存目录最终落点) |
| 315 | |
| 316 | |
| 317 | |
| 318 | |
| 319 | |
| 320 | - `EVID_UPLOAD_FILENAME_EXTENSION_PARSING_SANITIZE`:file name/extension parsing & sanitization(文件名/扩展名解析与净化逻辑) |
| 321 | |
| 322 | |
| 323 | |
| 324 | |
| 325 | |
| 326 | - `EVID_UPLOAD_ACCESSIBILITY_PROOF`:可访问面证据(写入后是否形成可访问面:静态直连证据/映射证据) |
| 327 | |
| 328 | |
| 329 | |
| 330 | |
| 331 | |
| 332 | - `EVID_UPLOAD_EXEC_DISABLE_STRATEGY`:执行禁用策略证据(服务端执行禁用策略,如有) |
| 333 | |
| 334 | |
| 335 | |
| 336 | |
| 337 | |
| 338 | - 可利用前置条件(鉴权/目录可访问性/绕过条件) |
| 339 | |
| 340 | |
| 341 | |
| 342 | |
| 343 | |
| 344 | - 验证 PoC(包含真实上传路由,给出必要的 multipart 请求结构) |
| 345 | |
| 346 | |
| 347 | |
| 348 | |
| 349 | |
| 350 | - 修复建议(白名单 + 魔数校验 + 目录隔离 + 随机化文件名 + 覆盖策略 + Webserver 执行禁用要点) |
| 351 | |
| 352 | |
| 353 | |
| 354 | |
| 355 | |
| 356 | ## tracer 证据缺失处理(强制,遵循统一标准) |
| 357 | - 若 trace 的 `## 9) Sink Evidence Type Checklist`(UPLOAD 行)中上述关键证据要点缺失: |
| 358 | - **满足最小证据集**(可达性 + 参数可控性线索 + Sink 执行线索 + 基本前置条件):可标记为 `🟡高概率`,在报告中注明缺失的 EVID 点与补全建议。 |
| 359 | - **不满足最小证据集**:只能标记为 `⚠️待验证`(不得直接给出 `✅已确认可利用`)。 |
| 360 | - **满足完整证据集**(全部 EVID 对齐 + 完整 trace + 分支覆盖):可标记为 `✅已确认可利用`。 |