Files
csm/wiki/SECURITY-AUDIT.md
iven 60ee38a3c2 feat: 新增补丁管理和异常检测插件及相关功能
feat(protocol): 添加补丁管理和行为指标协议类型
feat(client): 实现补丁管理插件采集功能
feat(server): 添加补丁管理和异常检测API
feat(database): 新增补丁状态和异常检测相关表
feat(web): 添加补丁管理和异常检测前端页面
fix(security): 增强输入验证和防注入保护
refactor(auth): 重构认证检查逻辑
perf(service): 优化Windows服务恢复策略
style: 统一健康评分显示样式
docs: 更新知识库文档
2026-04-11 15:59:53 +08:00

11 KiB
Raw Blame History

CSM 安全审计报告

审计日期: 2026-04-11 | 审计范围: 全系统 (Server + Client + Protocol + Frontend) 方法论: OWASP Top 10 (2021), CWE Top 25, 手动源码审查 + 攻击者视角分析


执行摘要

严重级别 数量 说明
CRITICAL 4 可直接被远程利用,导致系统完全沦陷
HIGH 12 需特定条件但影响重大
MEDIUM 12 有限影响或需较高权限
LOW 8 纵深防御建议

最关键发现: JWT Secret 硬编码在版本控制中、注册 Token 为空允许任意设备注册、凭据文件无 ACL 保护、默认无 TLS 传输加密。这四个问题组合意味着攻击者可以在数分钟内完全接管系统。


CRITICAL (4)

AUD-001: JWT Secret 硬编码在 config.toml 中

  • 文件: config.toml:12crates/server/src/config.rs
  • CWE: CWE-798 (硬编码凭证)
  • OWASP: A07:2021 - 安全配置错误

漏洞代码:

jwt_secret = "39ffc129-dd62-4eb4-bbc0-8bf4b8e2ccc7"

攻击场景: 任何能访问仓库的人可提取 secret为任意用户含 admin伪造 JWT获得系统完全管理控制权可推送恶意配置到所有医院终端、禁用安全控制、篡改审计记录。

修复:

  1. config.toml 中移除硬编码 secret
  2. 通过 CSM_JWT_SECRET 环境变量独占加载
  3. secret 为空时拒绝启动
  4. 立即轮换已泄露的 secret 39ffc129-dd62-4eb4-bbc0-8bf4b8e2ccc7
  5. config.toml 加入 .gitignore

AUD-002: 空 Registration Token — 任意设备注册

  • 文件: config.toml:1, crates/server/src/tcp.rs:549-558
  • CWE: CWE-306 (关键功能缺失认证)
  • OWASP: A07:2021

漏洞代码:

registration_token = ""
if !expected_token.is_empty() {  // 空字符串直接跳过验证

攻击场景: TCP 端口 9999 可达的任何攻击者可注册恶意设备,注入伪造审计数据掩盖安全事件,获取所有插件配置(含安全策略)。

修复: 设置强 registration token空 token 时拒绝启动。


AUD-003: Windows 凭据文件无 ACL 保护

  • 文件: crates/client/src/main.rs:280-283
  • CWE: CWE-732 (关键资源权限不当)
  • OWASP: A01:2021

漏洞代码:

#[cfg(not(unix))]
fn write_restricted_file(path: &std::path::Path, content: &str) -> std::io::Result<()> {
    std::fs::write(path, content)  // 无任何 ACL 设置
}

攻击场景: device_secret.txtHMAC 密钥)和 device_uid.txt(设备身份)以默认权限写入,设备上任何用户进程可读取。攻击者可提取密钥伪造心跳,在不同机器上模拟设备。

修复: 使用 icaclsSetSecurityInfo 设置仅 SYSTEM 可访问的 ACL。


AUD-004: 默认无 TLS — 明文传输所有敏感数据

  • 文件: config.toml (无 [server.tls]), crates/server/src/tcp.rs:411-414
  • CWE: CWE-319 (明文传输敏感信息)
  • OWASP: A02:2021

攻击场景: TCP 端口 9999 以明文运行。device_secret、所有插件配置、Web 过滤规则、USB 策略、软件黑名单均以明文 JSON 传输。网络嗅探者可提取设备认证密钥并逆向工程安全策略。

修复: 生产环境强制 TLS无 TLS 时拒绝启动(CSM_DEV=1 除外)。


HIGH (12)

AUD-005: Refresh Token 未存储 — 撤销机制不完整

  • 文件: crates/server/src/api/auth.rs:131-133
  • CWE: CWE-613
  • refresh_tokens 表存在但从未写入。登录不存储 token record刷新仅检查 family 是否撤销,不验证 token 是否曾被实际颁发。无法强制注销所有 session。

AUD-006: Refresh Token Family Rotation 存在 TOCTOU 竞争条件

  • 文件: crates/server/src/api/auth.rs:167-183
  • CWE: CWE-367
  • 检查 family 撤销状态与执行撤销之间无事务保护。并发使用同一 stolen token 的两个请求均可通过检查,攻击者获得全新的未撤销 token family。

AUD-007: 客户端不验证服务器身份

  • 文件: crates/client/src/network/mod.rs:149-162
  • CWE: CWE-295
  • 客户端盲目连接任何响应的服务器。ARP/DNS 欺骗攻击者可推送恶意配置禁用所有安全插件、注入有害规则。HMAC 仅保护心跳,不保护配置推送。

AUD-008: PowerShell 命令注入面

  • 文件: crates/client/src/asset/mod.rs:82-83, crates/client/src/clipboard_control/mod.rs:143-159
  • CWE: CWE-78
  • powershell_lines() 通过 format!() 拼接命令参数。若服务器推送含引号/转义字符的恶意规则,可能导致 PowerShell 命令注入。

AUD-009: 服务停止/卸载未受保护

  • 文件: crates/client/src/service.rs:17-69
  • CWE: CWE-284
  • csm-client.exe --uninstall 无认证保护。终端管理员权限用户可完全移除安全代理,绕过所有监控。无服务恢复策略、无看门狗进程、无反调试保护。

AUD-010: JWT Token 存储在 localStorage

  • 文件: web/src/lib/api.ts:25-28, 175-176
  • CWE: CWE-922
  • Access token 和 refresh token 均存储在 localStorage,可被同源任意 JS 访问。XSS 漏洞可直接窃取 7 天有效期的 refresh token。

AUD-011: CSP 允许 unsafe-inline + unsafe-eval

  • 文件: crates/server/src/main.rs:142-143
  • CWE: CWE-693
  • script-src 'self' 'unsafe-inline' 'unsafe-eval' 使 CSP 对 XSS 几乎无效。结合 localStorage token 存储,单个 XSS 即可导致管理员会话完全沦陷。

AUD-012: WebSocket JWT 在 URL 查询参数中

  • 文件: crates/server/src/ws.rs:36-73
  • CWE: CWE-312
  • JWT 通过 /ws?token=eyJ... 传输。Token 出现在浏览器历史、服务器访问日志、代理日志中。且 WebSocket handler 不检查用户角色,非管理员可接收所有广播事件。

AUD-013: 告警规则 Webhook SSRF

  • 文件: crates/server/src/api/alerts.rs:115-131
  • CWE: CWE-918
  • notify_webhook 字段无 URL 验证。可设置为 http://169.254.169.254/latest/meta-data/ (AWS 元数据) 或 file:///etc/passwd,将服务器变成 SSRF 代理。

AUD-014: 仅基于用户名的速率限制可绕过

  • 文件: crates/server/src/api/auth.rs:101
  • CWE: CWE-307
  • 速率限制仅以用户名为 key。攻击者可用 AdminADMIN 等变体绕过。无 IP 限制,可分布式暴力破解。

AUD-015: 磁盘加密确认在只读路由层 — 权限提升

  • 文件: crates/server/src/api/plugins/mod.rs:42
  • CWE: CWE-862
  • PUT acknowledge_alertread_routes() 中(仅需认证,不需 admin。任何认证用户可确认忽略加密告警掩盖合规违规。

AUD-016: 初始管理员密码输出到 stderr

  • 文件: crates/server/src/main.rs:270-275
  • CWE: CWE-532
  • 初始密码通过 eprintln! 输出。容器化部署中 stderr 被日志聚合系统捕获,有日志访问权限者可获取管理员密码。

MEDIUM (12)

# 发现 文件 CWE
AUD-017 多个 Update handler 跳过输入验证 (软件黑名单/Web过滤器/剪贴板) software_blocker.rs:79, web_filter.rs:62, clipboard_control.rs:107 CWE-20
AUD-018 USB 策略 rules 字段接受任意 JSON 无验证 usb.rs:94-135 CWE-20
AUD-019 密码无最大长度限制 (bcrypt 72 字节截断) auth.rs:303 CWE-20
AUD-020 多个字段缺少长度验证 (弹出窗口/剪贴板/USB策略名) 多处 CWE-20
AUD-021 多个列表端点无分页 (黑名单/白名单/规则/策略) 多处 CWE-770
AUD-022 磁盘加密状态列表无分页可全库转储 disk_encryption.rs:12-55 CWE-770
AUD-023 JWT 角色仅信任 claim 不查库 (降级延迟) auth.rs:273 CWE-863
AUD-024 缺少 HSTS 头 main.rs:123-143 CWE-319
AUD-025 CORS 配置需严格限制 main.rs:284-301 CWE-942
AUD-026 日志中泄露设备 UID 和服务器地址 main.rs:62, network/mod.rs:34 CWE-532
AUD-027 注册 Token 回退空字符串 main.rs:72 CWE-254
AUD-028 conflict.rs 中 format! SQL 模式 (当前安全但脆弱) conflict.rs:205 CWE-89

LOW (8)

# 发现 文件
AUD-029 组名未过滤 HTML 特殊字符 groups.rs:72-96
AUD-030 弹出窗口阻止器更新可创建无过滤器的规则 popup_blocker.rs:67-104
AUD-031 设备删除非原子 (自毁帧在事务前发送) devices.rs:215-306
AUD-032 受保护进程列表硬编码且可修补绕过 software_blocker/mod.rs:9-73
AUD-033 hosts 文件修改可能与 EDR 冲突 web_filter/mod.rs:59-93
AUD-034 软件拦截器 TOCTOU 竞争条件 (已缓解) software_blocker/mod.rs:329-386
AUD-035 前端路由守卫不验证 JWT 签名 router/index.ts:38-49
AUD-036 WebSocket 不验证入站消息 (当前丢弃) ws.rs:108-119

修复优先级

P0 — 立即 (24h)

修复项 对应发现 工作量
轮换 JWT Secret移至环境变量 AUD-001 30min
设置非空 registration_token AUD-002 15min
凭据文件添加 Windows ACL AUD-003 1h
生产环境强制 TLS AUD-004 2h

P1 — 短期 (1 周)

修复项 对应发现 工作量
Refresh token 存储到 DB + 事务保护 AUD-005, 006 4h
Update handler 添加输入验证 AUD-017 4h
Webhook URL 验证防 SSRF AUD-013 1h
磁盘加密确认移至 admin 路由 AUD-015 15min
初始密码写入文件替代 stderr AUD-016 30min
添加 IP 速率限制 AUD-014 2h

P2 — 中期 (1 月)

修复项 对应发现 工作量
Token 迁移至 HttpOnly Cookie AUD-010 8h
CSP 强化 (nonce-based) AUD-011 4h
WebSocket ticket 认证 AUD-012 4h
服务器身份验证 (证书固定) AUD-007 8h
服务保护 (恢复策略/看门狗) AUD-009 4h
PowerShell 注入面消除 AUD-008 6h
HSTS + Permissions-Policy 头 AUD-024, 036 1h
分页补充 AUD-021, 022 4h

安全亮点 (做得好的地方)

  1. SQL 注入防御: 全库一致使用 sqlx::bind() 参数化
  2. 错误处理: ApiResponse::internal_error() 不泄露内部错误详情
  3. 密码哈希: bcrypt cost=12符合行业标准
  4. Token Family 轮换: 检测 token 重放并撤销整个 family
  5. 常量时间比较: 注册 token 验证已使用 constant_time_eq()
  6. 帧速率限制: 100 帧/5秒/连接
  7. 审计日志: 所有管理员写入操作记录到 admin_audit_log
  8. HMAC 心跳: 设备认证使用 HMAC-SHA256
  9. 进程保护列表: 防止误杀系统关键进程
  10. 输入验证: Create handler 普遍有字段验证