$npx -y skills add 0xShe/PHP-Code-Audit-Skill --skill php-auth-auditPHP Web 源码鉴权机制审计工具。从源码中识别所有认证/鉴权实现并分析风险,输出路由-鉴权映射与漏洞分析(含 PoC 与修复建议)。
| 1 | # PHP 鉴权机制审计(Auth Audit) |
| 2 | |
| 3 | 分析 PHP Web 项目源码,识别认证与授权链路,判断每条路由的鉴权状态,并检测鉴权绕过/越权/IDOR 风险。 |
| 4 | |
| 5 | ## CRITICAL:完整分析(强制) |
| 6 | - 必须处理所有在 `php-route-mapper` 中出现的路由 |
| 7 | - 必须识别认证链:Session/JWT/中间件/自定义校验函数 |
| 8 | - 必须输出路由-鉴权映射表(不做省略) |
| 9 | - 对所有可疑点给出:位置证据 + 数据流链 + 可利用性分析 + 验证 PoC + 修复建议 |
| 10 | |
| 11 | ## 运行模式(强制:与流水线阶段对齐) |
| 12 | 此技能支持两种模式,用于解决“尚未生成 trace 之前无法引用 EVID_*”的问题: |
| 13 | |
| 14 | 1. `STATIC_MAPPING`(推荐用于流水线阶段 1) |
| 15 | - 只生成 `auth_mapping_{timestamp}.md`(以及可选的 `auth_README_{timestamp}.md`) |
| 16 | - 允许缺少 `php-route-tracer` 的 `EVID_*` 证据点引用 |
| 17 | - 必须给出:鉴权状态分级(✅/⚠️/❌/❓)与 P0/P1 分桶依据(不需要 PoC) |
| 18 | |
| 19 | 2. `TRACE_AUDIT`(推荐用于流水线阶段 4,trace 已存在) |
| 20 | - 生成完整的 `auth_audit_report_{timestamp}.md`,并强制逐条引用 trace 契约中的 `EVID_*` 证据点 |
| 21 | - PoC/修复建议必须齐全 |
| 22 | |
| 23 | ## 漏洞分级 |
| 24 | 详见:`shared/SEVERITY_RATING.md` |
| 25 | |
| 26 | ## 输入依赖 |
| 27 | 建议输入(与 `shared/IO_PATH_CONVENTION.md` 一致;合并流水线时读总报告中等价章节): |
| 28 | - `routes_{timestamp}.md`(独立落盘时常为 `route_mapping/routes_{timestamp}.md`) |
| 29 | - `params_{timestamp}.md`(独立落盘时常为 `route_mapping/params_{timestamp}.md`) |
| 30 | |
| 31 | 可选: |
| 32 | - `source_path` |
| 33 | |
| 34 | ## 识别鉴权实现(必做) |
| 35 | 按框架识别: |
| 36 | - Laravel: |
| 37 | - `middleware('auth'|'can'|'role:')` |
| 38 | - `Auth::check()/Auth::user()` |
| 39 | - Policies/Gates:`Gate::allows`、`->can({value})` |
| 40 | - 路由保护:`Route::middleware([{value}])->group({value})` |
| 41 | - Symfony: |
| 42 | - security.yaml / access_control |
| 43 | - `denyAccessUnlessGranted`、`isGranted` |
| 44 | - voter/policy |
| 45 | - 原生 PHP: |
| 46 | - `session_start` + `$_SESSION` 判断 |
| 47 | - `if (!isset($_SESSION['user']))`/`requireLogin()` |
| 48 | - 自定义函数:`checkAuth/authorize/hasRole/isAdmin` |
| 49 | |
| 50 | ## 路由-鉴权映射(必做) |
| 51 | 对每条路由输出以下状态: |
| 52 | - ✅ 公开:显式允许,无鉴权检查 |
| 53 | - ✅ 受保护:存在完整认证/授权检查 |
| 54 | - ⚠️ 仅认证:只校验登录态,无角色/资源级授权 |
| 55 | - ❌ 无鉴权:没有任何鉴权链路命中 |
| 56 | - ❓ 不确定:动态权限/复杂自定义逻辑导致难判(仍必须写出证据点) |
| 57 | |
| 58 | 并输出风险类型:`AUTH`,包括: |
| 59 | - 认证绕过(登录态校验被绕过) |
| 60 | - 授权绕过/越权(角色校验缺失或错误) |
| 61 | - IDOR(对象访问缺少所有权/归属校验) |
| 62 | |
| 63 | ## 可疑模式检测(必做,给出证据链) |
| 64 | ### 1) 路径/URI 匹配导致鉴权绕过 |
| 65 | 在 PHP 中常见根因: |
| 66 | - 用原始 `$_SERVER['REQUEST_URI']` 或 `parse_url` 结果做白名单匹配,但路径未规范化 |
| 67 | - 编码/大小写/重复斜杠/尾部字符差异导致匹配失败(实际路由进入受保护 handler) |
| 68 | |
| 69 | 必须输出: |
| 70 | - 白名单检查位置与代码片段 |
| 71 | - 绕过请求(PoC)与命中的 handler 证据 |
| 72 | |
| 73 | ### 2) 仅校验登录态,缺少角色/资源授权 |
| 74 | 必须输出: |
| 75 | - 路由的“认证检查”位置 |
| 76 | - “授权检查缺失”位置(例如只判断 `user!=null` 后直接执行敏感操作) |
| 77 | |
| 78 | ### 3) IDOR/越权 |
| 79 | 必须输出: |
| 80 | - 敏感对象 id 来自哪里(GET/POST/URL) |
| 81 | - 用于查询/更新的“归属校验”是否存在(WHERE 里是否包含 user_id/owner_id) |
| 82 | - 未校验的原因与可达性 |
| 83 | |
| 84 | ## 报告输出(按运行模式) |
| 85 | 输出到: |
| 86 | ``` |
| 87 | {output_path}/auth_audit/ |
| 88 | ├── auth_audit_report_{timestamp}.md |
| 89 | ├── auth_mapping_{timestamp}.md |
| 90 | └── auth_README_{timestamp}.md |
| 91 | ``` |
| 92 | 强制规则: |
| 93 | - `STATIC_MAPPING`:必须生成 `auth_mapping_{timestamp}.md`;`auth_audit_report_{timestamp}.md` 可以省略或生成空壳(并标注:仅分桶映射,不含 trace 证据) |
| 94 | - `TRACE_AUDIT`:必须生成完整三文件,并要求 trace 证据点齐全 |
| 95 | |
| 96 | ### 文件1:主报告 `auth_audit_report_{timestamp}.md` |
| 97 | 包含: |
| 98 | - 鉴权框架识别(含版本/实现证据) |
| 99 | - 鉴权架构概览(middleware/函数/handler) |
| 100 | - 风险统计 |
| 101 | - 每条风险的完整漏洞结构(编号/分级/数据流/PoC/修复) |
| 102 | |
| 103 | ### 文件2:映射表 `auth_mapping_{timestamp}.md` |
| 104 | 只列路由与鉴权状态、所需角色/条件(不要放漏洞详细分析)。 |
| 105 | 但必须新增分桶字段(用于流水线阶段 3 选路): |
| 106 | - `p_bucket`:`P0` 或 `P1` |
| 107 | - `P0`:❌ 无鉴权 |
| 108 | - `P1`:⚠️ 仅认证,或检测到存在授权绕过/越权/IDOR 风险(即使鉴权状态显示为“仅认证”,也要在 `p1_reason` 里说明为什么进入 P1) |
| 109 | - `p1_reason`:一段简短静态依据(如“仅登录态,缺少 hasRole/authorize 或缺少 owner_id 校验”) |
| 110 | |
| 111 | ### 文件3:说明文档 `auth_README_{timestamp}.md` |
| 112 | 只说明方法论、工具与验证指南,不包含具体漏洞细节。 |
| 113 | |
| 114 | ## PoC 验证模板(强制) |
| 115 | 必须区分至少以下场景: |
| 116 | - 未登录访问(无 cookie/session/JWT) |
| 117 | - 普通用户访问(普通账号 cookie/JWT) |
| 118 | - 管理员/高权限对照(如适用) |
| 119 | |
| 120 | PoC 必须是可执行 HTTP 请求代码块,并且路由路径必须使用真实路由规则。 |
| 121 | |
| 122 | ## 证据引用(按运行模式强制) |
| 123 | - `STATIC_MAPPING`:不强制引用 trace 的 `EVID_*` 证据点(只需输出鉴权分级与 P0/P1 分桶依据)。 |
| 124 | - `TRACE_AUDIT`:每条疑似鉴权风险必须逐项引用 trace 输出中的证据(允许状态标记为待验证,但证据引用必须存在): |
| 125 | 1. `EVID_AUTH_PATH_PROTECTED_MATCH`:路由进入受保护 handler 的路径匹配证据(对应 trace 的分支路径证据) |
| 126 | 2. `EVID_AUTH_TOKEN_DECODE_JUDGMENT`:登录态/Token 解码结果如何被判断的证据(对应 trace 中 session/JWT 读取与条件分支) |
| 127 | 3. `EVID_AUTH_PERMISSION_CHECK_EXEC`:权限判断函数或条件语句(如 `hasRole/authorize`)的执行证据(trace sink 定位或分支证据) |
| 128 | 4. `EVID_AUTH_IDOR_OWNERSHIP_CONDITION`:IDOR 归属校验(WHERE/条件)是否包含 owner_id/user_id 的证据(trace 中最终查询条件或状态更新语句) |
| 129 | |
| 130 | ## tracer 证据缺失处理(强制) |
| 131 | - `STATIC_MAPPING`:不适用(分桶依据以静态代码证据为准)。 |
| 132 | - `TRACE_AUDIT`:若 trace 契约校验失败或无法定位 1~4 任一关键证据点:该风险只能标记为 `⚠️待验证`,不得给出 `✅已确认可利用` 或“确定可绕过”的结论。 |