$npx -y skills add 0xShe/PHP-Code-Audit-Skill --skill php-expr-audit--- name: php-expr-audit description: PHP Web 源码表达式注入(非模板)审计工具。识别用户可控表达式字符串进入表达式引擎求值/编译并最终导致敏感语义执行,输出可利用性分级、PoC 与修复建议(禁止省略)。 ---
| 1 | # PHP 表达式注入(非模板)审计(php-expr-audit) |
| 2 | |
| 3 | 分析 PHP 项目源码,识别“表达式求值/编译”入口点:用户可控表达式字符串被传入表达式引擎(或 PHP 语言级代码执行函数),从而改变条件判断、路由决策、权限表达式或执行敏感语义(Expression Injection/代码注入类)。 |
| 4 | |
| 5 | ## 分级与编号 |
| 6 | - 详见:`shared/SEVERITY_RATING.md` |
| 7 | - 漏洞编号:`{C/H/M/L}-EXPR-{序号}` |
| 8 | |
| 9 | ## EXPR Sink(必做) |
| 10 | 识别表达式引擎的求值/编译入口点(优先),以及 PHP 语言级“字符串即代码”的执行函数: |
| 11 | - `ExpressionLanguage->evaluate({value})` |
| 12 | - `ExpressionLanguage->compile({value})` 后续的执行/求值使用点 |
| 13 | - `eval($code)`(当 `$code` 可由用户控制时) |
| 14 | - `assert($assertion)`(当 `$assertion` 为字符串且可由用户控制时) |
| 15 | - `preg_replace({value}, $replacement, {value})` 中使用 deprecated 的 `/e` 修饰符(当 replacement 可控时) |
| 16 | - 以及等价的“表达式解析/求值”引擎(项目封装的 evaluate/parse/compile 方法,只要最终把表达式字符串作为输入) |
| 17 | |
| 18 | ## 必检证据点(必做,trace 契约对齐) |
| 19 | 每条 EXPR 疑似漏洞必须逐项引用 `php-route-tracer` trace 中 `## 9) Sink Evidence Type Checklist` 的 **EXPR 行**对应证据点 ID: |
| 20 | 1. `EVID_EXPR_EVAL_ENTRY`:表达式解析/编译/求值入口点位置证据 |
| 21 | 2. `EVID_EXPR_EXPR_CONTROL`:表达式字符串是否来自用户可控输入的映射证据 |
| 22 | 3. `EVID_EXPR_EXEC_CHAIN_ENTRY`:表达式求值链的后续使用证据(求值结果如何进入敏感语义/安全关键分支,或最终执行点) |
| 23 | |
| 24 | ## 可控性与注入语义确认(必做) |
| 25 | 必须输出并判断: |
| 26 | - 表达式字符串从哪里来:请求字段/JSON 字段/参数拼接后作为表达式输入 |
| 27 | - 是否存在白名单/沙箱:是否限制函数、变量、常量、类型;是否对表达式语法进行拒绝或替换 |
| 28 | - 是否存在“求值结果进入安全关键逻辑”:例如进入 if/过滤条件、权限判定、模板外表达式执行等 |
| 29 | - 是否存在分支绕过:某些分支对表达式不做限制、或仅对部分输入做净化 |
| 30 | |
| 31 | ## tracer 触发条件(必做) |
| 32 | 当满足任一条件时触发 `php-route-tracer`(或同等深度追踪): |
| 33 | - 表达式字符串经过多层函数/JSON 解码/拼接后才进入 evaluate/compile |
| 34 | - 表达式引擎求值结果参与安全关键条件或敏感操作(必须能在 trace 中追踪) |
| 35 | - 表达式限制逻辑存在条件分支(某些分支没限制、或限制可被绕过) |
| 36 | |
| 37 | ## 报告输出 |
| 38 | 输出到: |
| 39 | ``` |
| 40 | {output_path}/vuln_audit/expr_{timestamp}.md |
| 41 | ``` |
| 42 | |
| 43 | ## 漏洞条目模板(强制) |
| 44 | 每条 EXPR 注入漏洞必须包含以下结构: |
| 45 | ```markdown |
| 46 | ### [{等级前缀}-EXPR-{序号}] 表达式注入漏洞(非模板) |
| 47 | |
| 48 | | 项目 | 信息 | |
| 49 | |------|------| |
| 50 | | 严重等级 | {🔴/🟠/🟡/🔵} (CVSS {score}) | |
| 51 | | 可达性 (R) | {0-3} - {理由} | |
| 52 | | 影响范围 (I) | {0-3} - {理由} | |
| 53 | | 利用复杂度 (C) | {0-3} - {理由} | |
| 54 | | 可利用性 | ✅ 已确认 / ⚠️ 待验证 / ❌ 不可利用 / 🔍 环境依赖 | |
| 55 | | 位置 | {file}:{line} ({Function}) | |
| 56 | |
| 57 | #### 数据流链(Source → Sink) |
| 58 | (按路由逐行写出:输入读取 -> 表达式字符串构造 -> evaluate/compile 入口 -> 求值结果进入敏感语义,禁止省略) |
| 59 | |
| 60 | #### 可利用前置条件 |
| 61 | - 鉴权要求:{无需/需登录/需特定权限} |
| 62 | - 输入可控性:{完全可控/条件可控/不可控} |
| 63 | - 触发条件:{分支/异常/环境依赖} |
| 64 | - 沙箱/白名单可靠性:{已可靠防护/防护缺失/防护可绕过} |
| 65 | |
| 66 | #### 证据引用(强制:来自 php-route-tracer) |
| 67 | - `EVID_EXPR_EVAL_ENTRY`:{对应证据要点简述} |
| 68 | - `EVID_EXPR_EXPR_CONTROL`:{对应证据要点简述} |
| 69 | - `EVID_EXPR_EXEC_CHAIN_ENTRY`:{对应证据要点简述} |
| 70 | |
| 71 | #### 验证 PoC(强制:给出可执行请求) |
| 72 | ```http |
| 73 | {HTTP Method} {真实路由与完整参数} HTTP/1.1 |
| 74 | Host: {host} |
| 75 | {必要 Cookie/Auth} |
| 76 | |
| 77 | {Payload} |
| 78 | ``` |
| 79 | |
| 80 | PoC 生成策略(必须写清楚): |
| 81 | - 第一步:使用“探测 payload”证明表达式确实被求值(例如算术结果、条件分支结果变化、返回值差异) |
| 82 | - 第二步:在探测成立后,构造“注入 payload”证明可改变安全关键语义(如绕过过滤/更改权限判断结果),若必须依赖具体引擎函数白名单,则标注为 `🔍环境依赖/⚠️待验证`,但仍给出可落地尝试方式 |
| 83 | |
| 84 | #### 建议修复 |
| 85 | - 禁止将用户输入直接作为表达式字符串传入 evaluate/compile |
| 86 | - 使用严格 allowlist:仅允许固定表达式模板 + 参数占位符(并对参数做类型/范围校验) |
| 87 | - 为表达式引擎启用沙箱策略:限制函数/变量/访问范围;禁用危险操作(若引擎支持) |
| 88 | - 对表达式语法做拒绝策略(例如拒绝注入控制字符)并说明拒绝点位置 |
| 89 | - 给出代码搜索语句(`rg`)定位所有 evaluate/compile 入口与表达式字符串构造点 |
| 90 | ``` |
| 91 | |
| 92 | ## tracer 证据缺失处理(强制) |
| 93 | - 若 trace 契约的 EXPR 行中任一关键证据点(`EVID_EXPR_EVAL_ENTRY / EVID_EXPR_EXPR_CONTROL / EVID_EXPR_EXEC_CHAIN_ENTRY`)缺失或无法对应到本条漏洞:状态只能标记为 `⚠️待验证`,不得直接给出 `✅已确认可利用`。 |