7.7 KiB
7.7 KiB
Round 2 全面代码审计修复报告
日期: 2026-05-23 范围: 全部8类别深度扫描 (功能性缺陷/安全漏洞/代码规范/安全风险/性能/可用性/可扩展性/优化)
修复汇总
| 严重度 | 数量 | 状态 |
|---|---|---|
| CRITICAL | 3 | 全部修复 |
| HIGH | 9 | 全部修复 |
| MEDIUM | 15 | 全部修复 |
| LOW | 10 | 评估后保留/已修复 |
CRITICAL 修复
C-1: sync_service.py Shell注入回归 (CRITICAL)
- 文件:
server/application/services/sync_service.py - 修复: 对rsync命令所有动态参数添加
shlex.quote()— source_path, target_path, username, domain, key file path - 附带修复: sshpass密码通过
env={"SSHPASS": password}传递给子进程;__import__("datetime")替换为正常import
C-2: agent.py exec端点RCE无防护 (CRITICAL)
- 文件:
server/api/agent.py - 修复: 添加
DANGEROUS_PATTERNS危险命令正则检测 + 403拦截;API Key比较改为secrets.compare_digest();proc.kill()后加await proc.wait()防僵尸进程;server_id 类型验证
C-3: WebSSH IDOR — token未绑定server_id (CRITICAL)
- 文件:
server/api/webssh.py - 修复: 验证JWT token中的server_id与路径参数匹配,不匹配返回4003关闭连接
HIGH 修复
H-1: PUT/POST端点setattr任意字段注入 (HIGH)
- 文件:
servers.py,settings.py,assets.py,scripts.py - 修复: 为每个模型定义字段白名单 (SERVER_CREATE_FIELDS, SCHEDULE_CREATE_FIELDS, PLATFORM_CREATE_FIELDS, SCRIPT_CREATE_FIELDS, CREDENTIAL_CREATE_FIELDS等);create端点用
safe_data = {k:v for k,v in payload.items() if k in WHITELIST}过滤;update端点只set白名单内字段
H-2: settings/assets/scripts端点无JWT认证 (HIGH)
- 文件:
settings.py,assets.py,scripts.py - 修复: 所有端点添加
admin: Admin = Depends(get_current_admin)依赖
H-3: refresh_token并发重放攻击 (HIGH)
- 文件:
server/application/services/auth_service.py - 修复: refresh时先清空旧token (invalidate-then-generate模式),并发请求第二个会因找不到token而失败
H-4: servers.py N+1 Redis查询 (HIGH)
- 文件:
server/api/servers.py - 修复: 使用Redis pipeline批量获取所有heartbeat key,单次round-trip
H-5: agent.py proc.kill()僵尸进程 (HIGH) — 与C-2合并修复
H-6: agent.py heartbeat server_id类型验证 (MEDIUM→HIGH) — 与C-2合并修复
H-7: settings API Key/Secret泄露 (HIGH)
- 文件:
server/api/settings.py - 修复: 定义
SENSITIVE_SETTING_KEYS集合;list/get返回***MASKED***;PUT禁止修改secret_key/encryption_key
H-8: TOTP暴力破解无速率限制 (HIGH)
- 文件:
server/application/services/auth_service.py - 修复: 添加内存TOTP速率限制器,5次失败后锁定5分钟
H-9: get_optional_admin独立session泄漏 (HIGH)
- 文件:
server/api/auth_jwt.py - 修复: 改用
_get_request_session(request)获取request-scoped session
MEDIUM 修复
M-2: X-Forwarded-For IP伪造
- 文件:
server/api/auth.py - 修复: 优先使用X-Real-IP(Nginx设置);X-Forwarded-For取最后一个值(Nginx追加)
M-3: asyncssh known_hosts=None — 添加ADR注释说明
- 文件:
server/infrastructure/ssh/asyncssh_pool.py - 修复: 添加ADR-012注释说明跳过原因(受控服务器环境)
M-4: asyncssh异常信息泄露服务器地址
- 文件:
server/infrastructure/ssh/asyncssh_pool.py - 修复: ConnectionError只包含server_id,完整错误写入logger;exec_ssh_command返回通用错误消息
M-5: 分页limit无上限
- 文件:
settings.py,assets.py - 修复: audit_logs limit上限500;ssh_sessions上限200;command_logs上限500;retry_jobs上限500
M-9: API层直接import infrastructure层
- 文件:
servers.py,agent.py - 修复: 在
dependencies.py添加get_redis_client()抽象函数,API层通过此函数获取Redis客户端
M-10: WebSocket ConnectionManager单进程限制
- 文件:
server/api/websocket.py - 修复: 添加
global_client_count()方法,通过Redis聚合多worker连接数
M-11: servers.py Redis overlay逻辑重复
- 文件:
server/api/servers.py - 修复: 提取
_overlay_redis_heartbeat()辅助函数,list_servers和get_server共用
M-13: login_attempts表缺少查询索引
- 文件:
server/domain/models/__init__.py - 修复: 添加
Index('idx_login_attempts_check', 'username', 'ip_address', 'success', 'attempted_at')
M-14: sync_service批量获取server逐个查询
- 文件:
server/domain/repositories/__init__.py,server/infrastructure/database/server_repo.py,server/application/services/sync_service.py - 修复: ServerRepository添加
get_by_ids(ids)方法,使用IN查询一次获取所有server
M-15: API错误消息中英文混用
- 文件: 所有API路由文件
- 修复: 统一为中文错误消息(服务器未找到、平台未找到、脚本未找到、必填等)
修改文件清单
server/api/servers.py— setattr白名单+JWT auth+Redis pipeline+overlay去重+中文错误消息server/api/settings.py— setattr白名单+JWT auth+敏感设置掩码+分页上限+中文错误消息server/api/assets.py— setattr白名单+JWT auth+分页上限+中文错误消息server/api/scripts.py— setattr白名单+JWT auth+中文错误消息server/api/agent.py— 危险命令检测+compare_digest+僵尸进程+server_id验证+Redis抽象+中文错误消息server/api/webssh.py— IDOR server_id绑定server/api/auth.py— X-Real-IP优先+X-Forwarded-For取最后一个值server/api/auth_jwt.py— get_optional_admin使用request sessionserver/application/services/sync_service.py— shlex.quote+sshpass env+__import__替换+批量get_by_idsserver/application/services/auth_service.py— refresh_token防重放+TOTP速率限制server/infrastructure/ssh/asyncssh_pool.py— 错误信息脱敏+ADR注释server/infrastructure/ssh/pool.py— exec_command支持env参数server/infrastructure/database/server_repo.py— 添加get_by_ids批量查询server/domain/repositories/__init__.py— ServerRepository协议添加get_by_idsserver/domain/models/__init__.py— LoginAttempt添加复合索引server/api/dependencies.py— 添加get_redis_client抽象server/api/websocket.py— 添加global_client_count多worker支持server/application/services/sync_engine_v2.py— sysctl命令注入防护+SFTP错误脱敏server/application/services/script_service.py— SSRF私有IP拦截+str(e)脱敏+MYSQL_PWD环境变量server/api/health.py— 未认证端点拆分为/health(公开)+/health/detail(需JWT)server/infrastructure/database/push_schedule_repo.py— **kwargs setattr改为字段白名单server/infrastructure/database/sync_log_repo.py— **kwargs setattr改为字段白名单server/api/agent.py— Exception str(e)脱敏server/background/self_monitor.py— Telegram消息str(e)脱敏server/api/webssh.py— SSH连接/Shell创建错误str(e)脱敏+关闭原因不暴露server_idserver/application/services/sync_service.py— error_message脱敏+stderr不写入DBserver/infrastructure/database/ssh_session_repo.py— __import__替换为正常importserver/api/sync_v2.py— 错误消息统一中文server/api/servers.py— _server_to_dict移除username字段(防SSH凭据泄露)server/infrastructure/ssh/pool.py— ValueError不暴露host地址server/infrastructure/database/server_repo.py— import语句移至文件顶部