Security audit (2026-03-31): 5 HIGH + 10 MEDIUM issues, all fixed. HIGH: - H1: JWT password_version mechanism (pwv in Claims, middleware verification, auto-increment on password change) - H2: Docker saas port bound to 127.0.0.1 - H3: TOTP encryption key decoupled from JWT secret (production bailout) - H4+H5: Tauri CSP hardened (removed unsafe-inline, restricted connect-src) MEDIUM: - M1: Persistent rate limiting (PostgreSQL rate_limit_events table) - M2: Account lockout (5 failures -> 15min lock) - M3: RFC 5322 email validation with regex - M4: Device registration typed struct with length limits - M5: Provider URL validation on create/update (SSRF prevention) - M6: Legacy TOTP secret migration (fixed nonce -> random nonce) - M7: Legacy frontend crypto migration (static salt -> random salt) - M8+M9: Admin frontend: removed JS token storage, HttpOnly cookie only - M10: Pipeline debug log sanitization (keys only, 100-char truncation) Also: fixed CLAUDE.md Section 12 (was corrupted), added title.rs middleware skeleton, fixed RegisterDeviceRequest visibility.
5.8 KiB
5.8 KiB
ZCLAW 安全渗透测试报告 V1.0
审计日期: 2026-03-31 审计范围: zclaw-saas 后端、desktop Tauri 应用、admin-v2 管理面板 审计方法: 白盒代码审计 + 灰盒攻击面分析 整体评级: B+ (良好)
一、执行摘要
对 ZCLAW 项目三大子系统进行了全面安全审计,覆盖 12 个安全领域、80+ API 端点、~80 个 Tauri IPC 命令。
核心结论: 未发现 Critical 级漏洞。项目安全架构设计良好(Argon2id、参数化 SQL、AES-256-GCM、RBAC),但在 JWT 生命周期管理、CSP 策略、密钥隔离方面存在改进空间。
共发现 5 项 HIGH + 10 项 MEDIUM + 7 项 LOW 级问题,全部已修复(HIGH + MEDIUM)或记录(LOW)。
二、已修复漏洞清单
HIGH 级 (5 项 — 全部已修复)
| # | 漏洞 | 影响 | 修复方案 |
|---|---|---|---|
| H1 | 密码修改后 JWT 不失效 | 攻击者窃取 JWT 后密码修改仍可使用 24h | password_version 机制: JWT claims 加入 pwv,中间件比对 DB 值,密码修改时递增 |
| H2 | Docker SaaS 端口绑定所有接口 | 生产环境 SaaS 直接暴露公网 | 改为 127.0.0.1 绑定,仅通过 nginx 反代访问 |
| H3 | TOTP 加密密钥与 JWT 密钥耦合 | JWT 泄露 → 所有加密数据同时泄露 | 生产环境强制独立 ZCLAW_TOTP_ENCRYPTION_KEY,缺失时拒绝启动 |
| H4 | Tauri CSP connect-src http://* |
XSS 后可向任意 HTTP 端点外泄数据 | 收紧为 http://localhost:* https://* |
| H5 | Tauri CSP unsafe-inline 脚本 |
允许内联脚本执行,削弱 XSS 防护 | 移除 script-src 'unsafe-inline' |
MEDIUM 级 (10 项 — 全部已修复)
| # | 漏洞 | 修复方案 |
|---|---|---|
| M1 | 限流仅内存存储 | PostgreSQL rate_limit_events 表持久化 |
| M2 | 无账户锁定机制 | 5 次失败锁定 15 分钟,DB 字段追踪 |
| M3 | 弱邮箱验证 | RFC 5322 regex + 254 字符长度限制 |
| M4 | 设备注册无输入约束 | typed struct + 字段长度限制 |
| M5 | Provider URL 仅执行时验证 SSRF | 创建/更新时即验证 URL,拒绝私有 IP |
| M6 | Legacy 固定 Nonce TOTP 加密 | 启动时自动迁移到随机 Nonce 格式 |
| M7 | Legacy 静态 Salt 前端加密 | v1→v2 自动迁移,随机 salt |
| M8 | Token 存储 JS 内存 | 移除 Zustand 中的 token 字段,仅用 HttpOnly Cookie |
| M9 | Refresh Token 重复传递 Header | 移除 Authorization Bearer 回退 |
| M10 | Pipeline 日志含用户数据 | 截断到 100 字符,敏感值替换为 [REDACTED] |
三、已确认安全区域
| 领域 | 评级 | 证据 |
|---|---|---|
| SQL 注入 | 安全 | 全量参数化查询 (sqlx .bind()),无字符串拼接 |
| 命令注入 | 安全 | Command::new 不用 shell,参数均为编译时常量 |
| 路径遍历 | 安全 | 文件操作用硬编码路径,pipeline_id 严格过滤 |
| 密码存储 | 安全 | Argon2id + OsRng 随机盐 + spawn_blocking |
| 加密实现 | 安全 | AES-256-GCM + 随机 12 字节 Nonce |
| 错误泄露 | 安全 | 内部错误统一返回 "服务内部错误" |
| JWT 基础 | 安全 | audience 验证、JTI 唯一、refresh 单次 rotation |
| RBAC | 安全 | 自我角色提升阻断、Token 权限范围限制 |
| SSRF | 安全 | 全面的 URL 验证 (私有 IP/DNS/混淆) |
| CORS | 安全 | 生产强制白名单,缺失拒绝启动 |
| Cookie | 安全 | HttpOnly + Secure + SameSite=Strict |
| XFF | 安全 | 仅信任配置代理 IP |
四、涉及修改的文件
数据库迁移 (新增)
migrations/20260401000004_accounts_password_version.sqlmigrations/20260401000005_rate_limit_events.sql
Rust 后端 (修改)
crates/zclaw-saas/src/auth/jwt.rs— Claims pwv 字段crates/zclaw-saas/src/auth/handlers.rs— 登录锁定 + 邮箱验证 + pwvcrates/zclaw-saas/src/auth/mod.rs— 中间件 pwv 验证crates/zclaw-saas/src/config.rs— TOTP 密钥强制独立crates/zclaw-saas/src/state.rs— AppCache 字段crates/zclaw-saas/src/lib.rs— cache 模块注册crates/zclaw-saas/src/models/account.rs— AccountLoginRow 字段crates/zclaw-saas/src/cache.rs— 已存在,注册到 libcrates/zclaw-saas/src/crypto.rs— Legacy TOTP 迁移函数crates/zclaw-saas/src/main.rs— 调用迁移crates/zclaw-saas/src/middleware.rs— 持久化限流crates/zclaw-saas/src/account/handlers.rs— 设备注册约束crates/zclaw-saas/src/model_config/handlers.rs— Provider URL 验证crates/zclaw-pipeline/src/executor.rs— 日志脱敏crates/zclaw-pipeline/src/actions/mod.rs— 日志脱敏
前端 (修改)
desktop/src-tauri/tauri.conf.json— CSP 加固desktop/src/lib/crypto-utils.ts— Legacy 加密迁移admin-v2/src/stores/authStore.ts— 移除 token 存储admin-v2/src/services/request.ts— 移除 Bearer headeradmin-v2/src/router/AuthGuard.tsx— isAuthenticated 检查admin-v2/src/pages/Login.tsx— login 调用更新
配置 (修改)
docker-compose.yml— 端口绑定 + env_file
五、验证结果
| 检查项 | 结果 |
|---|---|
cargo check -p zclaw-saas |
✅ 通过 |
cargo test -p zclaw-saas --lib |
✅ 17/17 通过 |
npx tsc --noEmit (admin-v2) |
✅ 零错误 |
| 安全扫描 | 建议: cargo audit + pnpm audit + trivy |
六、LOW 级监控项 (暂不修复)
| # | 项目 | 说明 |
|---|---|---|
| L1 | Dev JWT fallback 密钥 | #[cfg(debug_assertions)] 保护 |
| L2 | Demo API Key 种子数据 | 显然假值 |
| L3 | 浏览器自动化 eval | 设计如此 |
| L4 | 自定义 Markdown 渲染器 | 已用 DOMPurify 缓解 |
| L5 | Console 日志引用 Token | 不记录值 |
| L6 | format!() 用于表名 | 编译时常量 |
| L7 | docker-compose env_file 引用示例 | 文档说明即可 |