fbf5eadcf2
CRITICAL: - C-1: sync_service.py rsync命令shlex.quote防Shell注入回归 - C-2: agent.py exec端点危险命令正则拦截+compare_digest+僵尸进程修复 - C-3: WebSSH JWT token绑定server_id防IDOR HIGH: - H-1: 所有PUT/POST端点setattr改为字段白名单防任意字段注入 - H-2: settings/assets/scripts端点添加JWT认证 - H-3: refresh_token invalidate-then-generate防并发重放 - H-4: servers.py Redis pipeline解决N+1查询 - H-7: settings API Key/Secret掩码+禁止修改 - H-8: TOTP暴力破解速率限制(5次/5分钟) - H-9: get_optional_admin改用request-scoped session MEDIUM: - M-2: X-Real-IP优先+X-Forwarded-For取末值防IP伪造 - M-4: asyncssh异常信息脱敏(只含server_id) - M-5: 分页limit上限(500/200/500/500) - M-9: API层Redis依赖抽象至dependencies.py - M-10: WebSocket ConnectionManager多worker Redis聚合 - M-13: login_attempts复合索引 - M-14: ServerRepository.get_by_ids批量查询 - M-15: API错误消息统一中文 R3追加: - sysctl命令注入防护+regex验证 - $DB_PASS明文存储→masked_command双命令方案 - MYSQL_PWD环境变量替代-p flag - health端点拆分(公开/需认证) - repo层**kwargs→字段白名单 - 全局str(e)信息泄露修复(API/Telegram/WebSocket) - SSRF私有IP拦截 - Nginx HTTPS配置+DB备份脚本 - 前端CDN SRI哈希+XSS修复 - __import__替换为正常import Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
10 KiB
10 KiB
Nexus 6.0 — 全面代码扫描审计报告 (Round 2 合并版)
合并来源: 本地深度扫描 + worktree独立审计
说明: 两份独立审计报告去重合并,标注已修复项
P0 — CRITICAL (立即修复)
C-1: sync_service.py rsync命令 — Shell注入回归
- 文件:
server/application/services/sync_service.py:195 - 来源: 本地审计 BUG-2
- 描述: rsync命令f-string直接嵌入
source_path,server.username,server.domain,target_path,无shlex.quote()。sync_engine_v2.py 已修复(C8),但 sync_service.py 遗漏。恶意用户名如root'; rm -rf /;#可执行任意命令。 - 修复:
import shlex;所有动态参数shlex.quote()
C-2: agent.py exec — 命令注入无防护(RCE)
- 文件:
server/api/agent.py:193-209 - 来源: 两份报告均发现 (本地 SEC-1 / worktree S-02)
- 描述:
/api/agent/exec直接create_subprocess_shell(command)执行任意命令,无白名单/危险命令检测。仅全局API Key保护。Nexus被攻破后可对所有Agent执行任意命令。 - 修复: 添加与 script_service.py 一致的危险命令检测;命令白名单;
secrets.compare_digest替代==比较API Key
C-3: WebSSH 横向越权(IDOR)
- 文件:
server/api/webssh.py:82-97 - 来源: worktree S-01/B-01
- 描述: JWT无
server_idclaim时不校验路径server_id,任意已登录管理员可改URL连任意服务器SSH。_verify_webssh_token()返回server_id但未与路径参数比较。 - 修复: 签发WebSSH专用短期JWT(必含
server_id);验证时比对 token_server_id == path server_id;不匹配则close(4003)
P1 — HIGH (本周修复)
H-1: PUT/POST端点 setattr 无白名单 — 任意字段注入
- 文件:
servers.py:121-123,settings.py:89-91,assets.py:52-54,109-111,scripts.py:69-71,servers.py:106 - 来源: 本地审计 BUG-4/5
- 描述: 所有PUT端点
for key, value in payload.items(): setattr(obj, key, value),攻击者可注入is_active=False,password_hash="...",is_online=True等敏感字段。POST端点Server(**payload)同理。 - 修复: 定义每端点允许字段白名单;或使用Pydantic请求模型
H-2: settings/assets 端点 — 无JWT认证
- 文件:
server/api/settings.py,server/api/assets.py - 来源: 本地审计 SEC-2
- 描述: 所有端点使用
Depends(get_db)而非Depends(get_current_admin)。任何人可读/改系统设置、创建/删除节点、查看SSH会话和命令日志。 - 修复: 所有端点添加
admin: Admin = Depends(get_current_admin)依赖
H-3: agent.py proc.kill() — 僵尸进程泄漏
- 文件:
server/api/agent.py:223 - 来源: 两份报告均发现 (本地 BUG-1 / worktree B-05)
- 描述:
asyncio.TimeoutError分支proc.kill()后无await proc.wait(),产生僵尸进程。 - 修复:
proc.kill()后加await proc.wait()
H-4: refresh_token 并发重放攻击
- 文件:
server/application/services/auth_service.py:105-127 - 来源: 本地审计 BUG-3
- 描述: 并发请求使用同一refresh_token都能成功获取新token。违反rotation安全原则。
- 修复: 数据库层面加唯一约束或应用层加锁
H-5: N+1 Redis查询 — 2000+服务器性能瓶颈
- 文件:
server/api/servers.py:40-65 - 来源: 两份报告均发现 (本地 PERF-1 / worktree P-02)
- 描述: 每台服务器单独
redis.hgetall(),2000+服务器=2000+次Redis往返。 - 修复: Redis pipeline 批量获取
H-6: Agent心跳直写MySQL — 与文档矛盾
- 文件:
server/api/agent.py:172 - 来源: worktree B-04/P-01
- 描述: 每次心跳
service.update_heartbeat()+ commit,与文档"Redis实时+10min批量落MySQL"矛盾。2000+服务器×60s = 高MySQL负载。 - 修复: 心跳仅写Redis,由
heartbeat_flush.py批量刷库
H-7: API Key reveal 端点
- 文件:
server/api/settings.py(如存在/api-key/reveal) - 来源: worktree S-03
- 描述: 对已登录管理员返回完整全局API_KEY,一旦XSS即可窃取。
- 修复: 禁止回读;仅轮换时展示一次
H-8: TOTP disable 无二次验证
- 文件:
server/api/auth.py:151-165 - 来源: worktree S-09
- 描述:
totp/disable仅需JWT,无密码/TOTP二次验证。JWT被盗后攻击者可直接关闭双因素。 - 修复: 要求
current_password+ 有效TOTP码
H-9: 全局无JWT中间件 — 新路由易漏认证
- 文件: 架构层面
- 来源: worktree E-01
- 描述: 每路由靠
Depends(get_current_admin),新路由开发易遗漏。settings/assets 已漏。 - 修复:
main.py默认拒绝 + 白名单(install/health/agent/auth/login)
P2 — MEDIUM (迭代修复)
M-1: server_id 类型验证缺失
- 文件:
server/api/agent.py:103 - 来源: 本地审计 BUG-6
- 修复:
try: server_id = int(payload["server_id"]); except: raise 400
M-2: get_optional_admin session泄漏
- 文件:
server/api/auth_jwt.py:128-133 - 来源: 本地审计 BUG-7
- 修复: 接收Request参数,通过
_get_request_session(request)获取session
M-3: sshpass环境变量未设置
- 文件:
server/application/services/sync_service.py:188-193 - 来源: 本地审计 BUG-8
- 修复: exec_command调用时传递
env={"SSHPASS": password}
M-4: X-Forwarded-For IP伪造
- 文件:
server/api/auth.py:19-24 - 来源: 本地审计 SEC-3
- 修复: 优先使用
X-Real-IPheader(Nginx设置);或使用X-Forwarded-For最后一个值
M-5: known_hosts=None — SSH中间人攻击
- 文件:
server/infrastructure/ssh/asyncssh_pool.py:145 - 来源: 本地审计 RISK-1
- 修复: 实现known_hosts缓存机制
M-6: 异常信息泄露服务器拓扑
- 文件:
server/infrastructure/ssh/asyncssh_pool.py:164 - 来源: 本地审计 RISK-2
- 修复: 日志记录完整错误,返回客户端隐藏内部地址
M-7: TOTP brute-force 无限制
- 文件:
server/application/services/auth_service.py:179-191 - 来源: 本地审计 RISK-3
- 修复: TOTP验证添加速率限制(5次失败后锁定5分钟)
M-8: payload: dict → Pydantic模型
- 文件: 多处API路由
- 来源: 本地审计 STD-1
- 修复: 为每个端点创建Pydantic请求模型
M-9: 在线统计与列表数据源不一致
- 文件:
server/api/servers.py - 来源: worktree B-03
- 修复: 统计接口与列表共用Redis数据源
M-10: login_attempts 缺少复合索引
- 文件:
server/infrastructure/database/admin_repo.py:48-58 - 来源: 本地审计 PERF-3
- 修复: 添加
Index('idx_login_attempts_check', 'username', 'ip_address', 'success', 'attempted_at')
M-11: audit_logs/settings 无分页上限
- 文件:
server/api/settings.py:23-27 - 来源: 本地审计 PERF-2
- 修复: 添加limit上限保护
M-12: install路由生产环境仍挂载
- 文件:
server/api/install.py - 来源: worktree S-08
- 修复: 安装完成后卸载路由或IP白名单+一次性token
M-13: API Key比较非常量时间
- 文件:
server/api/agent.py:37 - 来源: worktree S-12
- 修复:
secrets.compare_digest(x_api_key, settings.API_KEY)
M-14: 告警冷却多worker重复Telegram
- 文件:
server/api/websocket.py - 来源: worktree P-03
- 修复: Redis SETNX + TTL 去重
M-15: AES-CBC遗留兼容代码
- 文件:
server/infrastructure/database/crypto.py:59-75 - 来源: worktree R-01
- 修复: 迁移期后移除CBC;统一Fernet
P3 — LOW (优化改进)
L-1: __import__("datetime") 应改为正常import
- 文件:
server/application/services/sync_service.py:168,200,212,219,228 - 来源: 本地审计 STD-2
L-2: infrastructure层直接import到api层
- 文件:
server/api/servers.py:17,server/api/agent.py:22-23 - 来源: 本地审计 STD-3
L-3: Fernet key无rotation机制
- 文件:
server/infrastructure/database/crypto.py:16-21 - 来源: 本地审计 SEC-4
L-4: Redis overlay逻辑重复(DRY)
- 文件:
server/api/servers.py:44-61vs:80-95 - 来源: 本地审计 OPT-2
L-5: API响应含SSH username字段
- 文件:
server/api/servers.py:206 - 来源: 本地审计 OPT-3
L-6: 错误消息中英文混用
- 文件: 多处
- 来源: 本地审计 UX-1
L-7: refresh token单设备限制
- 文件:
server/domain/models/__init__.py:157-158 - 来源: 本地审计 SCALE-2
L-8: batch_push顺序获取server
- 文件:
server/application/services/sync_service.py:67-72 - 来源: 本地审计 PERF-4
L-9: 前端esc()重复定义
- 文件: 多处
web/app/*.html - 来源: worktree C-02
L-10: 前端空catch吞错误
- 文件:
web/app/api.js - 来源: worktree U-01
L-11: install.py同步subprocess阻塞事件循环
- 文件:
server/api/install.py:283-284 - 来源: worktree C-03
L-12: 前端15页独立内联脚本无组件复用
- 文件:
web/app/*.html - 来源: worktree E-04
汇总
| 严重度 | 数量 | 类别覆盖 |
|---|---|---|
| P0 CRITICAL | 3 | Shell注入回归、Agent RCE、WebSSH IDOR |
| P1 HIGH | 9 | setattr注入、无JWT认证、僵尸进程、token重放、N+1 Redis、心跳写库矛盾、API Key reveal、TOTP disable、全局JWT |
| P2 MEDIUM | 15 | 类型验证、session泄漏、sshpass、IP伪造、SSH MITM、信息泄露、TOTP brute-force、Pydantic、数据源不一致、索引缺失、分页、install路由、compare_digest、告警去重、AES遗留 |
| P3 LOW | 12 | import规范、架构违规、key rotation、DRY、字段脱敏、i18n、多设备、批量查询、前端esc统一、错误处理、install阻塞、前端复用 |
修复执行顺序
第一批(P0 — 安全致命):
- C-1: sync_service.py shlex.quote()
- C-2: agent exec 危险命令检测 + compare_digest
- C-3: WebSSH server_id绑定验证
第二批(P1 — 安全+性能): 4. H-1: setattr白名单/Pydantic模型 5. H-2: settings/assets JWT认证 6. H-9: 全局JWT中间件 7. H-3: proc.kill() + await proc.wait() 8. H-4: refresh_token并发保护 9. H-5: Redis pipeline 10. H-6: 心跳仅写Redis 11. H-7: API Key reveal禁止 12. H-8: TOTP disable二次验证
第三批(P2 — 纵深防御): M-1 ~ M-15
第四批(P3 — 优化): L-1 ~ L-12