< Back to blog list

CVE-2026-31431 批量巡检:从脚本到可用工具

为什么“能扫”不等于“能用”

很多漏洞扫描脚本的实际情况是:

  • 能连上机器
  • 能判断有没有漏洞
  • 打印一堆结果

但在内网环境里,这种脚本基本用不起来。原因很简单:

  • 机器多了就跑不动
  • 扫描和修复混在一起,不敢直接跑
  • 执行过程不可控,卡住也不知道
  • 结果没法复用,只能人工看

这个项目要解决的,不是“能不能扫”,而是:

能不能在真实环境里反复、安全地用


资产配置:把“目标机器”变成“配置”

第一步不是写逻辑,而是把机器抽出来。

fleet.env 管理所有设备:

DEVICE_1_HOST=192.168.1.10
DEVICE_1_USER=root
DEVICE_1_KEY=./keys/node1

再用:

FLEET_COUNT=3

控制数量。

这样做之后,脚本不再关心“要连哪台机器”,只负责:

  • 读配置
  • 遍历设备
  • 执行动作

这一步的意义很直接:

  • 可以复用
  • 可以批量跑
  • 不需要改代码

执行模型:必须并发 + 必须可控

单线程跑几十台机器基本不可接受。

这里做了两件事:

MAX_WORKERS=8

控制并发数。

DEVICE_MAX_DURATION_SECONDS=1800

限制单台机器最长执行时间。

结果是:

  • 多台机器同时跑
  • 某一台卡住不会拖死整体

这一步不复杂,但很关键。没有这个,工具在生产环境基本不可用。


执行模式:检测和修复必须分开

很多脚本的问题是:

  • 一跑就改系统

这种在生产环境基本没人敢用。

这里强制分两种模式:

MODE=audit
MODE=fix

audit

  • 只检测
  • 不做任何修改

fix

  • 先做临时缓解
  • 再尝试修复
  • 可选是否重启
AUTO_REBOOT=0

这样可以做到:

  • 先全量扫一遍
  • 再挑一部分机器修
  • 最后再复检

而不是一次性全动。


修复逻辑:不是一步完成

修复分两层:

1. 临时缓解

  • 禁用 algif_aead
  • 尝试卸载模块

优点是:

  • 不依赖重启
  • 可以立刻降低风险

2. 内核升级

  • 按发行版升级内核

这是最终解决方案,但有几个现实问题:

  • 需要维护窗口
  • 可能要重启
  • 不能一次性全做

所以必须把这两步拆开。


状态定义:结果要能用,不只是能看

不是简单输出“有漏洞 / 没漏洞”,而是给每台机器一个状态:

  • SAFE
  • MITIGATED
  • NEEDS_PATCH
  • UNKNOWN
  • FAILED

这样做的目的很实际:

  • NEEDS_PATCH → 后续重点处理
  • FAILED → 单独排查
  • MITIGATED → 已经降风险,但还没彻底修

这比一堆文本输出有用得多。


报告输出:不是给人看的,是给系统用的

每次执行会输出:

  • JSON
  • CSV
  • Markdown
  • 执行日志

核心信息包括:

  • 主机
  • 系统版本
  • 模块状态
  • 修复情况

关键点在于:

  • JSON 可以被其他系统接入
  • CSV 可以直接给运维用
  • Markdown 用来查看结果

不是为了好看,是为了后续处理。


执行过程:必须能看到进度

加了两个配置:

PROGRESS_HEARTBEAT_SECONDS=5
PROGRESS_LOG_TO_FILE=1

效果是:

  • 执行过程中有持续输出
  • 长任务不会看起来像“卡死”
  • 日志可以回看

这在批量执行时很重要。

< Back to blog list

<BLOG>

</BLOG>