【vCenter】VCSA 6.0 suidcheck 安全告警排查:原厂基线巡检为何被识别为提权侦察
文章目录14 节
一、先说结论
一台 VCSA 6.0.0.20000 触发了安全告警:系统以 root 身份运行 /usr/bin/find / -perm -4000,行为被识别为本地提权前的 SUID 枚举。
我后来部署了同版本 VMware-VCSA-all-6.0.0-3634788 环境,对脚本内容、RPM 来源、文件哈希、定时任务调用链和实际输出进行了核对。最终确认:
本次告警是 VMware 原厂
vasecurity安全加固组件部署的每周安全基线检查触发的行为误报。suidcheck只枚举并记录已有的 SUID 文件,不会给文件添加 SUID 权限,不会修改或执行找到的文件,也不会直接实施提权。
不过,“这一次是正常巡检”不等于所有 find / -perm -4000 都可以放行。攻击者确实会用相同命令寻找本地提权入口,安全平台识别出的行为特征没有错;真正决定性质的是父进程、脚本路径、内容与哈希、执行时间和软件包来源。
本文保留实际版本、命令、输出特征和哈希,公开内容中的地址、资产名称和连接标识均已脱敏。
二、事件流程
整个事件可以概括为:
flowchart LR
A["VMware 原厂 vasecurity<br/>虚拟设备安全加固组件"] --> B["部署每周安全检查脚本"]
B --> C["/etc/cron.weekly/suidcheck"]
D["/etc/crontab"] --> E["/usr/lib/cron/run-crons"]
E -->|"每周以 root 身份调用"| C
C --> F["/usr/bin/find / -perm -4000"]
F --> G["枚举系统中的 SUID 文件"]
G --> H["写入 /var/log/suidlist/"]
F -. "命令也常用于提权前侦察" .-> I["安全平台行为告警"]这条链路中要区分三个角色:
| 角色 | 对应组件 | 作用 |
|---|---|---|
| 安装来源 | vasecurity RPM | 提供并应用 VMware 虚拟设备安全加固规则 |
| 调度来源 | /etc/crontab、/usr/lib/cron/run-crons | 判断周任务是否到期,并以 root 身份调用脚本 |
| 检查工具 | /etc/cron.weekly/suidcheck、/usr/bin/find | 枚举 SUID 文件并把结果写入本地日志 |
vasecurity 并不是每周直接启动 find 的常驻服务。它主要在设备部署或加固阶段生成最终脚本;之后的周期执行由系统 cron 机制负责。
三、复现环境与证据边界
我用于核对的环境如下:
| 项目 | 实测值 |
|---|---|
| 部署介质 | VMware-VCSA-all-6.0.0-3634788 |
| VCSA 版本 | 6.0.0.20000 |
| Appliance 内部 BUILDNUMBER | 3634791 |
| 分支 | vsphere60u2 |
| 操作系统 | SUSE Linux Enterprise Server 11 SP3 |
| 内核 | 3.0.101-0.47.71-default |
| 加固包 | vasecurity-6.0.0.0-3588047 |
OVA 文件名中的 build 3634788、Appliance 内部 build 3634791 和部分组件 build 不完全相同。它们分别属于发布介质、Appliance 和组件构建编号,不能因为数字略有差异就直接判断介质被修改。
这次已经验证:
- 四个
/etc/cron.weekly/脚本在全新同版本 VCSA 中真实存在。 - 脚本的属主、权限、修改时间、内容和 SHA-256 已记录。
vasecurity的 VMware 厂商元数据及加固源脚本的 RPM 归属可以对应。/etc/crontab → run-crons → cron.weekly调度关系可以对应。- 首次满足周任务条件后,四个日志目录均生成了带时间戳的结果。
- 告警中
/usr/bin/find的 SHA-256 与全新环境原厂文件一致。
这次没有验证业务 VCSA 上所有历史时期的脚本是否从未被改动。判断某一台业务主机时,仍应现场计算哈希并与可信基线比较,不能只凭文件名相同就认定安全。
四、四个脚本分别做什么
同版本环境中的四个脚本都是 root:root、权限 0700,修改时间为 2016-02-24。它们只负责检查和记录,不负责自动修复。
| 脚本 | 实际检查 | 输出目录 | 作用 |
|---|---|---|---|
devcheck | 枚举块设备和字符设备节点 | /var/log/devicelist/ | 建立设备节点基线,发现异常新增节点 |
rpmcheck | 校验已安装 RPM 文件 | /var/log/rpmcheck/ | 发现文件缺失、摘要、权限、属主等变化 |
sgidcheck | 枚举设置 SGID 位的文件 | /var/log/sgidlist/ | 建立组权限程序基线,辅助识别异常 SGID 文件 |
suidcheck | 枚举设置 SUID 位的文件 | /var/log/suidlist/ | 建立高权限程序基线,辅助识别异常 SUID 文件 |
下面是全新环境中读取到的原始脚本内容。这里是证据摘录,不建议为了验证而手工执行这些全盘扫描命令。
devcheck:
/usr/bin/find / -type b -o -type c > /var/log/devicelist/device_list.$(date +%m%d%Y-%H%M%S)rpmcheck:
rpm -qVa | awk '$2!="c" {print $0}' > /var/log/rpmcheck/rpmcheck.$(date +%m%d%Y-%H%M%S)sgidcheck:
/usr/bin/find / -perm -2000 2>/dev/null > /var/log/sgidlist/sgid_list.$(date +%m%d%Y-%H%M%S)suidcheck:
/usr/bin/find / -perm -4000 2>/dev/null > /var/log/suidlist/suid_list.$(date +%m%d%Y-%H%M%S)其中 rpmcheck 使用 rpm -qVa 将当前文件状态与 RPM 数据库记录比较,再排除标记为配置文件 c 的项目。它输出差异并不等于系统一定被入侵:补丁、正常配置、初始化和 VMware 加固过程本身都可能造成差异。
五、为什么 suidcheck 会触发告警
suidcheck 的核心行为是:
/usr/bin/find / -perm -4000参数含义如下:
| 参数 | 含义 |
|---|---|
/ | 从根目录开始搜索 |
-perm -4000 | 匹配已设置 SUID 权限位的文件 |
2>/dev/null | 丢弃扫描过程中的标准错误 |
> /var/log/suidlist/... | 将标准输出写入带时间戳的结果文件 |
SUID 可执行文件运行时可能获得文件所有者的有效身份。如果文件所有者是 root,这类程序就属于本地提权排查的重点。攻击者进入 Linux 主机后,经常先枚举 SUID 文件,寻找错误配置或存在漏洞的高权限程序。
因此安全平台看到下面的特征时触发告警是合理的:
用户身份:root
程序:/usr/bin/find
参数:/ -perm -4000
扫描范围:整个根文件系统但这只能证明“发生了 SUID 枚举”,不能单独证明“发生了提权”。本次现场的关键区别是:命令由正常的 run-crons 周任务链启动,脚本与二进制哈希能够对应原厂基线,结果写入固定的安全检查目录,并且没有修改权限、执行 SUID 程序或建立网络连接。
六、怎样确认脚本来自 VMware 原厂
1. 查看 vasecurity 的 RPM 元数据
风险等级:INFO(只读)
作用: 在 VCSA Bash Shell 中查询已安装
vasecurity软件包的名称、版本、厂商、构建时间和描述。 执行位置: VCSA;需要能够进入 Bash Shell。该命令只读取本机 RPM 数据库,不修改系统。 完成判断: 输出应显示本机实际安装的包版本和Vendor: VMware, Inc.。不同 VCSA 补丁版本的 Release 可能不同,应以现场结果为准。
rpm -qi vasecurity本次同版本环境的实际输出为:
Name : vasecurity
Version : 6.0.0.0
Release : 3588047
Vendor : VMware, Inc.
Build Date : 2016-02-24
Summary : VA Secutiry Hardening scripts for VMware
Description : Virtual Appliance Security Hardening for VMware.Secutiry 是包内 Summary 原文的拼写,不是本文录入错误。
2. 查询加固源脚本的 RPM 归属
只看到 Vendor: VMware, Inc. 还不足以证明任意同名脚本都来自原厂。下一步需要把 vasecurity 包登记的加固源脚本与最终周期脚本对应起来。
风险等级:INFO(只读)
作用: 通过 RPM 数据库确认四个安全加固源路径属于哪个软件包。 执行位置: VCSA Bash Shell。即使安装后的加固流程已经移除源文件,RPM 数据库仍可能保留这些路径的归属记录。 完成判断: 四条查询均应返回现场安装的
vasecurity包;如果返回归属不同或数据库错误,需要停止套用本文结论并继续调查。
rpm -qf /vasecurity/va_hardening/patches/government/GEN002260-device-list.sh
rpm -qf /vasecurity/va_hardening/patches/government/GEN002400-weekly-setuid-check.sh
rpm -qf /vasecurity/va_hardening/patches/government/GEN002460-all-suid-binaries-weekly.sh
rpm -qf /vasecurity/va_hardening/patches/government/GEN006565-audit-packages.sh本次四条查询都对应:
vasecurity-6.0.0.0-3588047对应关系为:
| 最终脚本 | vasecurity 包中的加固源路径 |
|---|---|
/etc/cron.weekly/devcheck | GEN002260-device-list.sh |
/etc/cron.weekly/sgidcheck | GEN002400-weekly-setuid-check.sh |
/etc/cron.weekly/suidcheck | GEN002460-all-suid-binaries-weekly.sh |
/etc/cron.weekly/rpmcheck | GEN006565-audit-packages.sh |
这里有一个容易误判的细节:
rpm -qf /etc/cron.weekly/suidcheck可能返回“文件不属于任何软件包”。原因是 /etc/cron.weekly/suidcheck 是加固过程生成或部署的最终文件,不一定作为普通文件直接登记在 RPM 清单中;RPM 登记的是用于应用加固规则的源路径。因此不能只用最终文件的 rpm -qf 结果下结论。
另外,安装完成后 /vasecurity 下的部分源文件可能已经不存在,导致 rpm -V vasecurity 报告多个 missing。我在全新 Appliance 中也观察到了这种情况,它属于加固脚本应用后的安装状态,不能单凭这些 missing 判断系统遭到删除或入侵。
3. 核对最终脚本和 find 哈希
RPM 来源证明了生成链,文件哈希则用于判断业务主机上的当前文件是否仍与可信基线一致。
风险等级:INFO(只读)
作用: 计算四个周期脚本和
/usr/bin/find的 SHA-256,供同版本基线比对。 执行位置: 待排查的 VCSA Bash Shell;读取系统文件通常需要 root。 注意事项: 只有版本、补丁级别和文件内容相同的主机才应直接比较本节基线。哈希不一致不等于一定恶意,但必须继续检查文件内容、RPM 校验结果和变更来源。
sha256sum \
/etc/cron.weekly/devcheck \
/etc/cron.weekly/rpmcheck \
/etc/cron.weekly/sgidcheck \
/etc/cron.weekly/suidcheck \
/usr/bin/find本次 VMware-VCSA-all-6.0.0-3634788 全新环境基线为:
| 文件 | SHA-256 |
|---|---|
devcheck | d2f1c2b745e1f502df708d98bb02944ae2e4392af1579a2bbb3a8ef58564016a |
rpmcheck | 5523812c1cf607e7a61580899adfa6a8dc9bb1d77fe0f15bf45b4074d7f75816 |
sgidcheck | a524298be8187b383ad957b3c79c88509d02aaff04d0e68cb87418e294144464 |
suidcheck | d474c0491237745e356990927870d5ff4d6a1d2e24db93aefd3f7ae22d8573e0 |
/usr/bin/find | 8997b68e8900bb4ad2e73c479428b4b0d9e6e6247bd500c07b7732f8885e8058 |
/usr/bin/find 属于 findutils-4.4.0-38.26.1。本次告警记录中的 find 哈希与全新环境相同,这是确认告警二进制为原厂文件的重要证据。
七、脚本实际怎样被执行
/etc/crontab 每 15 分钟调用一次:
test -x /usr/lib/cron/run-crons && /usr/lib/cron/run-crons >/dev/null 2>&1run-crons 并不是每 15 分钟执行一遍所有周任务,而是检查 /var/spool/cron/lastrun/cron.weekly 标记。标记不存在或距离上一次执行超过 10080 分钟时,才顺序执行 /etc/cron.weekly/ 下的脚本,并通过 nice -n 15 降低调度优先级。
所以“安装完 VCSA 就会立即跑一遍”并不准确。更严谨的说法是:
新部署 VCSA 在首次满足
cron.weekly条件时通常会运行一次周任务。如果最后执行标记不存在或已经到期,下一次周期检查会触发执行;它不是由安装程序在完成按钮按下后直接同步执行。
直接观察 ps 也不是最可靠的验证方式。suidcheck 在本次环境中大约 2 秒就结束,很容易错过;而且 2>/dev/null 和输出文件重定向由 Shell 处理,通常不会完整出现在 find 进程自身的参数中。
更可靠的验证方法是同时查看脚本内容、周任务标记和输出文件时间。
风险等级:INFO(只读)
作用: 查看
suidcheck的实际内容、周任务最后执行标记以及已经生成的 SUID 清单。 执行位置: VCSA Bash Shell;读取这些系统路径可能需要 root。 注意事项: 命令只读取现有文件,不会主动再次运行全盘扫描。日志可能暴露系统程序路径,对外分享前应检查并脱敏。 完成判断: 将安全告警时间、cron.weekly标记时间和suid_list.<时间戳>文件时间进行对应。
sed -n '1,20p' /etc/cron.weekly/suidcheck
stat /var/spool/cron/lastrun/cron.weekly
ls -lht /var/log/suidlist/如果只看到 /var/log/suidlist/ 下存在历史文件,只能证明脚本曾经运行过。要判断某条具体告警是否由正常周任务触发,还应对应:
- 安全平台的告警时间;
- 告警记录中的父进程和完整参数;
cron.weekly标记的修改时间;suid_list.<时间戳>文件名和文件修改时间;- 脚本及
/usr/bin/find的 SHA-256。
八、首次周任务的实际开销
我在全新环境中观察到四个脚本首次执行的结果如下:
| 脚本 | 大约耗时 | 输出规模 |
|---|---|---|
devcheck | 16 秒 | 271 行,约 3.7 KB |
rpmcheck | 32 秒 | 1924 行,约 145 KB |
sgidcheck | 2 秒 | 5 行 |
suidcheck | 2 秒 | 21 行 |
| 合计 | 约 53 秒 | 约 160 KB |
suidcheck 找到的 21 个路径中包含 sudo、passwd、mount、ping、su 等正常系统程序;sgidcheck 找到 5 个路径。清单里出现高权限程序并不等于这些程序恶意,真正需要关注的是相对可信基线新增、内容被替换或权限异常的项目。
这四个脚本存在两个运行层面的注意点:
- 多个
find都从/开始,且没有使用-xdev,可能进入其他已挂载文件系统并产生短时间磁盘读取。 /var/log/devicelist、rpmcheck、sgidlist、suidlist使用带时间戳的新文件。我没有在该版本中找到这些目录的专用 logrotate 规则,长期运行可能造成日志缓慢累积。
这些属于性能和日志管理风险,不是恶意代码或直接提权风险。
九、风险判断
| 风险项 | 判断 | 依据 |
|---|---|---|
| 脚本恶意性 | 低,未发现恶意证据 | VMware 加固包来源、同版本基线、正常 cron 调用链均可对应 |
| 直接提权 | 无 | 只枚举 SUID/SGID 文件,不修改权限,不执行找到的程序 |
| 系统文件篡改 | 无 | 四个脚本只把结果重定向到各自日志目录 |
| 网络行为 | 无 | 脚本没有网络连接命令 |
| 脚本篡改面 | 较低 | 文件为 root:root、权限 0700,但仍应通过哈希验证当前内容 |
| CPU、I/O 影响 | 中等 | 全盘 find 和 rpm -qVa 会读取大量目录和软件包文件 |
| 日志累积 | 低到中等 | 带时间戳结果持续新增,未发现专用轮转规则 |
| 平台生命周期 | 高 | VCSA/vSphere 6.0 已属于老旧版本,脚本正常不能代表整个平台仍具备充分安全维护 |
因此不建议写成“这个脚本完全没有任何风险”。更准确的结论是:
未发现恶意行为和直接提权风险;脚本属于 VMware 原厂周期安全审计,但存在全盘读取产生的短时 I/O、跨挂载点扫描和日志累积风险。VCSA 6.0 本身的版本生命周期风险需要单独评估。
十、安全平台怎样设置例外才不会放得太宽
不能仅按照下面这个命令特征做全局白名单:
find / -perm -4000攻击者也会执行完全相同的枚举。更稳妥的例外条件应同时限定:
父进程:/usr/lib/cron/run-crons
脚本路径:/etc/cron.weekly/suidcheck
脚本 SHA-256:d474c0491237745e356990927870d5ff4d6a1d2e24db93aefd3f7ae22d8573e0
子进程:/usr/bin/find
参数:/ -perm -4000
find SHA-256:8997b68e8900bb4ad2e73c479428b4b0d9e6e6247bd500c07b7732f8885e8058
执行时间:与 cron.weekly 标记及 suid_list 文件时间相符如果出现以下任一情况,就不应直接套用例外:
- 父进程不是
run-crons或正常 Shell 调用链; - 脚本路径、内容、属主或权限发生变化;
- 脚本或
/usr/bin/find哈希与当前可信版本不一致; - 输出被发送到临时目录、网络位置或异常进程;
- 命令后续继续执行发现的 SUID 程序;
- 同一行为在非周任务时间大量重复出现。
十一、最终结论
这次排查最容易犯的错误有两个:一是看到 find / -perm -4000 就直接认定攻击;二是看到 Vendor: VMware, Inc. 就直接认定安全。
真正完整的判断依据应该是:
flowchart TD
A["告警行为<br/>find 枚举 SUID"] --> B["核对父进程与执行时间"]
B --> C["读取最终脚本内容与权限"]
C --> D["查询 vasecurity RPM 元数据"]
D --> E["确认加固源脚本的 RPM 归属"]
E --> F["与同版本全新环境比较 SHA-256"]
F --> G["对应 cron.weekly 标记和输出文件"]
G --> H["确认原厂周巡检触发的行为误报"]综合同版本环境实测,本次 suidcheck 告警属于 VMware VCSA 6.0 正常的每周安全基线巡检。脚本的任务是发现并记录 SUID 文件,而不是设置 SUID 或进行提权。安全平台命中了真实存在的双用途行为,但在这条确定的原厂调度链中,行为目的属于安全审计。
处置时可以针对完整执行上下文建立窄范围例外,同时继续保留对其他来源 find / -perm -4000 的检测。这样既能消除原厂巡检产生的重复误报,也不会把攻击者常用的提权侦察命令整体放行。