跳转到帖子

漏洞库记录:CVE-2021-3156 Sudo Baron Samedit 本地提权漏洞验证与修复

精选回复

发布于

漏洞背景

CVE-2021-3156,通常称为 Baron Samedit,是 sudo 在命令行参数反转义过程中产生的堆缓冲区溢出漏洞。攻击者只需获得 Linux 或 Unix 主机的普通本地账户,即可能将权限提升至 root;用户是否存在于 sudoers 文件中,不是利用该漏洞的必要条件。

上游受影响版本主要包括 sudo 1.8.2 至 1.8.31p2,以及 1.9.0 至 1.9.5p1。上游修复版本为 1.8.32 和 1.9.5p2。实际排查不能只比较版本字符串,因为 Debian、Ubuntu、RHEL 等发行版通常会在保留原版本号的情况下回移安全补丁。

以下验证仅适用于已授权测试环境。最小触发测试可能导致单个 sudoedit 进程崩溃,不应在核心生产节点上反复执行。

问题定位

该漏洞位于 sudoers 插件处理命令行参数的逻辑中。当 sudo 以 sudoedit 模式运行并启用 shell 标志时,参数末尾的反斜杠可能绕过前置转义检查,但仍进入后续反转义流程,最终造成堆缓冲区越界写入。

典型权限链路是:攻击者先通过弱口令、Web 服务漏洞或泄露的 SSH 密钥获得普通用户权限,随后利用该漏洞取得 root。提权后可读取系统凭据、修改 SSH 配置、植入持久化任务,或进一步访问内网服务。因此它应被视为内网攻防链路中的高优先级本地提权节点。

适用条件与边界

  • 攻击者必须能够在目标主机上执行本地程序,例如已取得 Shell、SSH 普通账户或容器内可访问宿主机 sudo。
  • 目标安装了受影响的 sudo 或由其提供的 sudoedit。
  • sudo 二进制通常带有 setuid root 权限;如果文件系统以 nosuid 挂载,实际提权条件可能受限。
  • 是否允许当前用户执行 sudo 命令并不能直接判断是否受影响。
  • 容器中发现漏洞不等于可直接控制宿主机,还需结合容器用户命名空间、挂载和特权配置判断影响边界。

操作步骤一:确认二进制与软件包来源

首先记录 sudo 版本、实际路径、文件权限和软件包来源。不要直接根据公开版本区间下结论。

command -v sudo
command -v sudoedit
sudo --version | head -n 3
ls -l /usr/bin/sudo /usr/bin/sudoedit 2>/dev/null
stat /usr/bin/sudo
findmnt -no TARGET,OPTIONS / /usr 2>/dev/null

正常情况下,/usr/bin/sudo 通常具有 setuid 位,例如权限中出现 rws。若 sudo 位于自定义目录,应继续确认该文件是否由系统软件包管理器安装,避免遗漏手工部署的旧版本。

# Debian / Ubuntu
dpkg-query -W -f='${Package} ${Version} ${Status}\n' sudo
apt-cache policy sudo
zgrep -i 'CVE-2021-3156' /usr/share/doc/sudo/changelog.Debian.gz 2>/dev/null

# RHEL / CentOS / Rocky / AlmaLinux
rpm -q sudo
rpm -q --changelog sudo | grep -i -m1 'CVE-2021-3156'
dnf updateinfo info --cves CVE-2021-3156 2>/dev/null

# SUSE
rpm -q sudo
zypper lp --cve CVE-2021-3156 2>/dev/null

如果版本看似处于受影响区间,但发行版公告或软件包 changelog 明确包含 CVE-2021-3156 修复,则应以发行版安全公告和包修订号为准。反过来,sudo --version 显示较新,也要排除 PATH 劫持、自编译副本和未受包管理器维护的二进制。

操作步骤二:最小化漏洞验证

建议优先通过软件包元数据确认。只有在隔离测试机、快照主机或维护窗口内,才执行以下非提权型触发测试。该命令只用于观察参数解析异常,不包含获取 root Shell 的利用代码。

sudoedit -s '\' $(python3 -c 'print("A" * 1000)')

受影响环境可能出现 malloc、heap corruption、invalid size、segmentation fault 等错误,也可能仅返回异常的 sudoedit 报错。已修复版本通常会拒绝该参数组合并显示正常用法或参数错误。

需要注意:

  • 未崩溃不能证明不存在漏洞,堆布局、编译参数、C 库版本都会影响触发表现。
  • 出现崩溃也应结合版本和软件包来源复核,避免将普通参数错误误判为可利用漏洞。
  • 不要扩大参数长度或循环执行。验证完成后应检查是否产生 core 文件,并按取证要求保存或清理。

日志与留痕排查

常规 sudo 日志不一定完整记录本次触发,因为漏洞发生在策略处理早期。排查时应同时检查认证日志、systemd journal、内核崩溃信息和审计日志。

# Debian / Ubuntu
grep -Ei 'sudoedit|sudo|segfault|malloc|corrupt|invalid size' \
  /var/log/auth.log /var/log/syslog 2>/dev/null

# RHEL 系列
grep -Ei 'sudoedit|sudo|segfault|malloc|corrupt|invalid size' \
  /var/log/secure /var/log/messages 2>/dev/null

# systemd journal
journalctl --since '7 days ago' | \
  grep -Ei 'sudoedit|sudo|segfault|malloc|corrupt|invalid size'

# 检查崩溃记录
coredumpctl list 2>/dev/null | grep -Ei 'sudo|sudoedit'

如果主机已启用 auditd,可查询 sudo 和 sudoedit 的执行记录:

ausearch -x sudo -ts recent -i 2>/dev/null
ausearch -x sudoedit -ts recent -i 2>/dev/null
ausearch -k sudo_exec_watch -ts recent -i 2>/dev/null

在授权监控窗口内,可临时增加执行审计规则。以下规则会增加日志量,部署前应评估审计分区容量:

auditctl -a always,exit -F arch=b64 -S execve \
  -F exe=/usr/bin/sudo -k sudo_exec_watch

# 32 位兼容环境按需增加
auditctl -a always,exit -F arch=b32 -S execve \
  -F exe=/usr/bin/sudo -k sudo_exec_watch

# 测试结束后移除对应规则
auditctl -d always,exit -F arch=b64 -S execve \
  -F exe=/usr/bin/sudo -k sudo_exec_watch

历史日志中若出现 sudoedit、-s、异常反斜杠参数以及紧邻的堆错误或进程崩溃,应提升事件优先级。但仅凭命令行特征不能认定已成功提权,还要继续检查后续 root 行为。

提权后的关联排查

如果存在疑似成功利用,应重点核查漏洞触发时间前后新增的高权限持久化和凭据访问行为:

# 近期账户及权限文件变更
stat /etc/passwd /etc/shadow /etc/group /etc/sudoers
find /etc/sudoers.d -type f -mtime -7 -ls 2>/dev/null

# 近期新增或修改的 systemd 服务、定时任务
find /etc/systemd/system /usr/lib/systemd/system -type f -mtime -7 -ls 2>/dev/null
find /etc/cron.d /var/spool/cron -type f -mtime -7 -ls 2>/dev/null

# root SSH 持久化
find /root/.ssh -type f -mtime -7 -ls 2>/dev/null

# 近期出现的 setuid 文件
find / -xdev -type f -perm -4000 -mtime -7 -ls 2>/dev/null

mtime 可被高权限攻击者修改,因此只能作为初筛条件。关键主机应进一步比对 EDR、集中审计、软件包校验、文件完整性基线和远端登录日志。RPM 系统可使用 rpm -Va sudo 检查包文件是否被修改;Debian 系统可结合 debsums 或可信镜像中的哈希进行比对。

修复与缓解建议

  • 通过发行版安全仓库升级 sudo,不建议只下载一个来源不明的 sudo 二进制覆盖系统文件。
  • 升级后重新检查软件包修订号及发行版安全公告,确认明确包含 CVE-2021-3156 修复。
  • sudo 通常是短生命周期程序,更新二进制后一般不需要重启服务;对于不可变镜像、容器基础镜像和离线模板,应重新构建并替换实例。
  • 无法立即升级时,可在确认存在独立 root 运维通道后临时移除 sudo 的 setuid 位,但这会导致正常 sudo 功能失效,不适合作为长期方案。
  • 不要把删除普通用户的 sudoers 权限当作修复措施,因为漏洞并不要求用户已获 sudo 授权。
  • 同步清查跳板机、开发机、CI Runner、运维容器和灾备节点。这些位置经常保留旧版 sudo,同时拥有较高的横向访问价值。
# 推荐:使用发行版仓库更新
apt-get update && apt-get install --only-upgrade sudo
# 或
dnf upgrade sudo

# 仅作为紧急缓解,执行前必须准备其他 root 登录通道
chmod u-s /usr/bin/sudo

# 修复后复核
sudo --version | head -n 3
ls -l /usr/bin/sudo
rpm -V sudo 2>/dev/null || true
dpkg-query -W -f='${Version}\n' sudo 2>/dev/null

结论

CVE-2021-3156 的风险点不在 sudoers 配置是否宽松,而在 sudo 本身的本地高权限边界。排查时应按照“二进制来源确认、发行版补丁核验、隔离环境最小验证、日志关联、提权后持久化检查”的顺序执行。版本字符串只能用于初筛,最终结论应以发行版安全公告、软件包修订号和实际文件完整性为依据。

代码审计与漏洞定位示意图
代码审计、调用链与关键函数定位示意
漏洞验证与修复流程示意图
漏洞成因、验证条件与修复闭环示意

这个漏洞验证时不建议直接跑公开 PoC。CVE-2021-3156 属于堆溢出,本地验证很容易造成 sudoedit 崩溃;而且即使用户不在 sudoers 中,也可能具备利用条件。

排查重点应放在发行版的软件包修复状态,而不是只看上游版本号。上游在 sudo 1.9.5p2 修复,但 Debian、Ubuntu、RHEL 等通常会向旧版本回移补丁。

# 基础信息
sudo --version | head
command -v sudo sudoedit
ls -l "$(command -v sudo)" "$(command -v sudoedit)"

# Debian / Ubuntu
dpkg-query -W -f='${Package} ${Version}\n' sudo
apt-cache policy sudo

# RHEL / CentOS / Rocky / Alma
rpm -q --changelog sudo | grep -i -E 'CVE-2021-3156|Baron Samedit'
rpm -q sudo
dnf updateinfo info --cves CVE-2021-3156

还要检查是否存在绕过包管理器遗留的 SUID 副本,例如手工安装到 /usr/local 或备份目录中的旧版 sudo:

find / -xdev -type f -perm -4000 \( -name sudo -o -name sudoedit \) \
  -exec ls -l {} \; 2>/dev/null

修复优先使用发行版安全更新,升级后确认实际执行文件和包归属:

# Debian / Ubuntu
apt-get update
apt-get install --only-upgrade sudo
dpkg -S "$(readlink -f "$(command -v sudo)")"

# RHEL 系
dnf upgrade sudo
rpm -qf "$(readlink -f "$(command -v sudo)")"

如果暂时无法更新,可以临时移除 sudo 的 SUID 位作为止血措施,但这会导致普通用户无法使用 sudo,需要预留 root 控制台或其他恢复通道:

chmod u-s /usr/bin/sudo
# 完成升级并核对包文件后恢复;更稳妥的是直接重装对应软件包
chmod u+s /usr/bin/sudo

应急排查时可关注异常的 sudoedit 调用、sudo 崩溃及 core dump,但没有相关日志不能证明未被利用:

journalctl --since "2021-01-01" | grep -Ei 'sudoedit|sudo.*segfault|core dumped'
coredumpctl list sudo sudoedit 2>/dev/null
ausearch -x sudoedit -ts recent 2>/dev/null

更新完成后建议同时核对主机镜像、容器基础镜像和长期不重启的运维节点,避免只修在线软件包而遗漏旧镜像或额外安装的 sudo 副本。

创建帐户或登录后发表意见

最近浏览 0

  • 没有会员查看此页面。