# PHP Logging Audit

> PHP Web 安全日志与监控审计工具。识别安全事件缺失、敏感信息写入日志、日志注入/伪造风险，以及日志与告警链路缺陷，并输出可利用性分级、可观测 PoC 与修复建议（禁止省略）。

- Skill: `0xshe/php-logging-audit` (Agent Skill)
- Install (CLI): `npx skillmds@latest add 0xshe/php-logging-audit`
- Raw SKILL.md: https://api.skillmd.com/api/skills/0xshe/php-logging-audit/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Security
- Author: 0xshe (https://skillmd.com/u/0xshe)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/0xshe/php-logging-audit

---


# PHP 安全日志与监控审计（php-logging-audit）

分析 PHP 项目在“安全可观测性”方面的代码与配置缺陷。核心目标不是泛化“要不要打日志”，而是识别可落地的问题：攻击者可否通过输入污染日志、系统是否把敏感信息写入日志、关键安全事件是否缺失、以及告警/审计链是否被破坏。

## 分级与编号
- 详见：`shared/SEVERITY_RATING.md`
- 漏洞编号：`{C/H/M/L}-LOG-{序号}`

## 覆盖范围（必做：必须逐项检查并输出证据）
本 skill 必须覆盖下列四类缺陷，并为每一类给出“证据点 + 影响 + 可利用性分析 + 修复建议”：

### 1) 安全事件审计缺失（Audit Gap）
识别缺失的安全事件日志点，例如（以项目实际入口为准）：
- 登录失败/成功与账号枚举相关失败原因记录（避免泄露敏感细节）
- 权限拒绝/越权尝试（拒绝原因可抽象化记录）
- 密码重置、邮箱变更、管理员角色变更、2FA 变更等关键账户事件
- 敏感操作（导出数据、下载密钥、删除/修改权限、批量导入）
- CSRF 校验失败、会话失效、注销成功等安全相关状态变化

要求输出：
- “应当记录哪些事件”（按你在源码里识别到的功能点映射）
- “实际写日志的位置是否存在/是否被绕过”（给出证据）
- 缺失导致的真实后果推演（例如审计不可用、事后无法追溯、告警无法触发）

### 2) 敏感信息写入日志（Sensitive Data in Logs）
识别任何可能把敏感数据写入日志的路径：
- `Authorization` 头、Cookie、`session_id`、JWT 原文
- 密码/验证码/恢复 token/一次性口令
- 用户隐私数据在失败栈或 debug 输出中被原样打印
- 将请求体/参数（尤其是包含密钥字段）直接拼进日志消息

要求输出：
- 敏感信息来源（来自哪些变量/请求字段）
- 写日志的调用点与 message 构造方式
- 日志的落地介质（文件路径/系统日志通道/日志库）

### 3) 日志注入与伪造（Log Injection / Forging）
识别“用户可控字符串进入日志消息但未做控制字符净化”的问题：
- `\r` / `\n` 进入日志消息导致日志行拆分
- 可能造成伪造时间戳、级别、请求路径等“假条目”
- 若日志格式使用 JSON 或键值对，检查是否存在转义缺陷造成结构被破坏

要求输出：
- 哪些字段可控（GET/POST/Headers/Body/Cookie）
- 注入进入点（日志 message 拼接点）
- 是否存在过滤/归一化（尤其是换行与控制字符处理）

### 4) 日志与告警链路缺陷（Monitoring & Alert Gaps）
识别监控链路缺口（以代码/配置能证明的为准）：
- 关键安全事件只记录 debug/info，未进入可告警通道
- 日志级别与告警规则缺失（例如 production 关闭了安全告警 channel）
- 错误处理吞掉异常导致关键事件没有被写入

要求输出：
- 你在源码里定位到的日志级别/通道/handler 配置证据
- 这些证据如何导致告警无法触发或取不到关键证据

## 识别逻辑（必做）
### 日志写入 Sink（代码）
必须识别以下日志相关 API（按项目实际替换）：
- PHP：`error_log({value})`
- 系统：`syslog({value})`
- PSR-3/框架：`->info({value})` `->warning({value})` `->error({value})` `->critical({value})` `->debug({value})`
- Laravel/Symfony/自定义封装：`Log::{value}({value})`、`logger->{value}` 或项目自己的 logger wrapper
- Monolog：`Monolog\Logger` 及 handler/channel 相关配置

### 消息构造与可控性（数据流）
对每个日志写入点，必须追踪至少一条链：
- Source（请求字段/用户输入/敏感 token 来源）
-> 中间变量处理（拼接、格式化、json_encode、模板字符串）
-> Sink（最终写入日志的 message 参数）

并输出：
- 可控字段名（或 JSON 路径）
- 进入日志前是否有净化（换行/控制字符/敏感字段脱敏）
- 是否有条件分支导致“只有某些分支才写日志”（写日志绕过）

## PoC（必做：可观测验证框架）
由于“日志缺陷”往往需要观察日志输出，你必须给出可观测 PoC 框架（可执行或可手动验证），至少包括以下两类其一：
- 使用真实路由触发日志写入，并说明预期日志中出现的字段/格式变化
- 使用构造 payload 注入换行/控制字符，说明预期日志会被拆行或出现伪造片段

PoC 输出要求：
- 必须包含真实路由（优先从 `routes_{timestamp}.md` 替换；独立落盘见 `route_mapping/routes_{timestamp}.md`，约定见 `shared/IO_PATH_CONVENTION.md`）
- 必须写出用于触发的请求头与 body/参数（至少包含一个会进入日志消息的可控字段）
- 必须说明你要在日志文件/控制台/系统日志中观察什么（例如某字段是否原样出现）

## 报告输出
输出到：
```
{output_path}/vuln_audit/logging_{timestamp}.md
```

## 漏洞条目模板（强制）
每条漏洞必须遵循以下结构（不得省略）：
```markdown
### [{等级前缀}-LOG-{序号}] {风险标题}

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

#### 漏洞类型与证据点
- 缺陷类别：{Audit Gap / Sensitive Data in Logs / Log Injection / Monitoring Gap}
- 证据点 A（日志写入调用点）：{file}:{line} 说明
- 证据点 B（消息构造/可控字段进入点）：{file}:{line} 说明
- 证据点 C（净化/脱敏是否存在）：{file}:{line} 说明（如无则写“未发现脱敏/未发现过滤”并给出搜索结论）

#### 数据流链（Source -> Transform -> Sink）
（逐行写出：请求输入如何被读取/解析/格式化 -> 是否进入日志 message -> 最终写入日志）

#### 可利用前置条件
- 鉴权要求：{无需/需登录/需特定权限}
- 输入可控性：{完全可控/条件可控/不可控}
- 触发条件：{分支/错误路径/异常路径/日志级别条件}
- 可观测性：{日志落地位置是否可读/是否在生产可见/是否需要运维权限}

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

{Payload}
```
（PoC 之后你需要观察的日志现象：{明确写出预期日志内容/格式变化/是否出现换行拆分}）

#### 建议修复
- 安全写法要点：敏感字段脱敏、控制字符净化、structured logging、日志级别与告警映射
- 代码搜索语句：使用 `rg` 定位所有日志写入与 message 构造相关代码块
```

## 输出完整性检查（强制）
- [ ] 每条漏洞都包含：编号、等级、位置、数据流链、可利用前置条件、可观测 PoC、修复建议
- [ ] 日志注入类问题必须明确使用控制字符 payload（至少包含换行注入场景）
- [ ] 敏感信息类问题必须明确指出敏感字段来源与写入位置
- [ ] 审计缺失类问题必须明确指出“应该记录但未记录”的对照逻辑（基于源码事件点推断，而不是泛泛而谈）
```


