Files
OpenFlare/docs/superpowers/specs/2026-07-19-waf-security-check-node-design.md
T
ryan 46ce7de513 perf(waf): 收窄安全防护扫描面并优化 UA 热路径
注入类检测仅扫 Query/Cookie/Referer/有限 Body,避免全 Header 匹配拖垮边缘 CPU;
按开关采集输入、GET 跳过 read_body,UA 仅 lower 一次并用 set 匹配白名单。
2026-07-19 14:16:34 +08:00

192 lines
6.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# WAF 规则节点:安全防护(security_check)
日期:2026-07-19
范围:WAF 编排图新节点 `security_check`(控制面校验/编译 + 边缘 Lua 特征检测 + 前端编辑器)
状态:已确认,待实现
## 背景
现有节点覆盖 IP / 地域 / UA / PoW,缺少请求载荷侧的基础攻击特征检测。产品需要在图中提供可编排的「安全防护」单元:多项基础规则可开关,**命中任意已启用规则返回 false**。
检测深度采用 **Lua 内置特征规则**(非 ModSecurity/CRS),能拦截常见扫描与明显 payload,允许有限误报/漏报。
## 目标
1. 新增 match 型节点 **`security_check`**,句柄 `true` / `false`。
2. 属性栏分组:**安全防护**说明 + **基础防护** 9 项 Switch。
3. 语义:**任一已启用规则命中 → false**;全部未命中 → true。
4. 默认仅开启误报较低的两项:**路径穿越**、**文件包含**;其余默认关闭。
## 非目标(v1)
- ModSecurity / OWASP CRS / libinjection 完整引擎
- 响应侧 XSS 检测、机器学习
- 自定义规则上传 / 严重级别评分 / 命中日志字段(可后续加)
- 无限制大 Body 全量扫描
## 节点模型
### 类型
| 字段 | 值 |
|------|-----|
| `type` | `security_check` |
| 句柄 | `true`, `false` |
| 可删除 / 可命名 / 可拖放 | 是 |
### Config
```json
{
"sql_injection": false,
"path_traversal": true,
"command_injection": false,
"xss": false,
"ssrf": false,
"file_inclusion": true,
"malicious_upload": false,
"xxe": false,
"crlf_injection": false
}
```
| 字段 | 默认 | UI 文案 | 检测面(v1) |
|------|------|---------|--------------|
| `sql_injection` | false | SQL 注入 | Query、Cookie、Referer、Body |
| `path_traversal` | **true** | 路径穿越防护 | Path(`uri`)、Query、Body |
| `command_injection` | false | 命令注入 | Query、Cookie、Referer、Body |
| `xss` | false | XSS | Query、Cookie、Referer、Body |
| `ssrf` | false | SSRF | Query、Cookie、Referer、Body 中 URL 形态 |
| `file_inclusion` | **true** | 文件包含(LFI/RFI) | Path(`uri`)、Query、Body |
| `malicious_upload` | false | 恶意文件上传 | Multipart Body |
| `xxe` | false | XXE | Body(Content-Type 含 xml 时) |
| `crlf_injection` | false | CRLF 注入 | Query、Cookie、Referer、Body |
全部关闭时:节点恒 **true**(空操作),合法。
## 求值语义
```
inputs := collect_inspection_strings(request) // 见下
for each enabled rule:
if rule_matches(rule, inputs) → return false
return true
```
- **false** = 命中攻击特征(接阻止)
- **true** = 未命中(接通过或其它节点)
### 采集与限制
| 来源 | 方式 |
|------|------|
| Path | 仅 `ngx.var.uri`(不重复扫完整 `request_uri`,避免与 Query 双计),URL 解码(含常见双重编码路径变体) |
| Query | `get_uri_args` 键与值(仅当已启用规则需要 Query) |
| Header | **不**扫描通用浏览器头(UA / Accept 等);注入类仅采 **Cookie、Referer** |
| Cookie | `ngx.var.http_cookie` |
| Body | 仅当已启用规则需要 Body 且 `Content-Length` > 0 且 ≤ **65536**;GET/零长度不 `read_body` |
Body 读取失败:跳过 Body 类检测并限频 warn(可用性优先,不 fail-closed 整图)。
### 规则特征方向(v1 模式包)
实现以可维护的模式表为准,下表为方向约束:
1. **SQL 注入**:`union select`、`or 1=1`、`sleep(`、`benchmark(`、注释符、十六进制/char 拼接等
2. **路径穿越**:`../`、`..\\`、`%2e%2e`、`%252e`、绝对路径探测
3. **命令注入**:`;` `|` `` ` `` `$()` 结合 shell 关键字、换行拼接
4. **XSS**:`<script`、`javascript:`、事件处理器 `onerror=` 等
5. **SSRF**:内网 IP、`localhost`、`169.254.`、`file://`、`gopher://`、`dict://`
6. **文件包含**:`php://`、`file://`、`/etc/passwd`、`%00` 等(可与路径穿越重叠)
7. **恶意上传**:multipart 文件名双扩展、危险扩展、可疑 Content-Type
8. **XXE**:`<!ENTITY`、`SYSTEM`、外部实体(仅 XML 类 Content-Type)
9. **CRLF**:`%0d%0a`、裸 `\r\n` 注入特征
模式在 worker 内缓存;大小写不敏感(除明确大小写敏感的协议串)。
## 控制面
### `graph_types.go`
- `RuleNodeSecurityCheck = "security_check"`
- `SecurityCheckConfig` 九个 `bool` 字段(JSON snake_case 如上)
### `graph_validate.go`
- `requiredHandles`: `true`, `false`
- 严格 JSON;仅允许已知布尔字段
### `graph_compile.go`
- 原样编译布尔字段进运行时配置
### 测试
- 合法全关 / 默认子集 / 全开
- 未知字段拒绝
- 编译保留默认
## 数据面
### `waf_runtime.lua`
```lua
elseif node.type == "security_check" then
handle = matches_security_check(node.config or {}) and "true" or "false"
```
`matches_security_check` 返回 **true 表示安全通过**(未命中),与 `ip_match` 的「条件成立」命名不同,但句柄语义与产品一致:命中攻击 → 走 `false` 边。
建议将模式表与匹配函数放在同文件或 `waf/security.lua`(若体积过大再拆,并在 `waf_assets.go` 嵌入)。
### `waf_runtime_spec.lua`
覆盖:默认配置拦路径穿越;全关放行;SQL/XSS 样例;Body 超限不炸;multipart 文件名危险扩展(若开启)。
## 前端
| 文件 | 变更 |
|------|------|
| `types.ts` | `security_check` + `SecurityCheckConfig` |
| `node-factory.ts` | 默认:path_traversal+file_inclusion true,其余 false |
| `node-library.tsx` | 「安全防护」+ 图标 |
| `rule-node.tsx` | `true`/`false` handles |
| `node-properties.tsx` | 显示名称;分组说明 + 9 Switch(问号 Tooltip) |
| `graph-validation.ts` / `editor-behavior.ts` | handles |
### 属性栏草图
```
显示名称
── 安全防护 ──
命中任意已启用规则返回 False [?]
── 基础防护 ──
[Switch] 路径穿越防护 [?]
[Switch] 文件包含(LFI/RFI) [?]
[Switch] SQL 注入 [?]
...
```
Tooltip 文案包含检测面与简要说明(与产品表一致)。
## 文档
- 更新 `docs/design/waf-orchestration-design.md` 节点表
- `docs/changelog/index.md` `[Unreleased]`
## 验收标准
- [ ] 可拖入并配置 9 开关,默认仅路径穿越+文件包含
- [ ] 保存/发布后 Agent 执行;命中 → false 边;未命中 → true
- [ ] 全关恒 true
- [ ] Lua/Go/前端相关测试与 `make code-check` 通过
## 风险
| 风险 | 缓解 |
|------|------|
| 误报 | 默认仅开低误报两项;模式偏保守 |
| 漏报 | 文档标明特征检测边界;后续可加强模式 |
| Body 性能 | 64KiB 上限;未启用 Body 规则不读 Body |
| 与路径/包含重叠 | 允许重叠;任一命中即 false |