跳转到帖子

Linux sudo 堆溢出漏洞 CVE-2021-3156(Baron Samedit)验证、留痕与修复

精选回复

发布于

背景

CVE-2021-3156 是 sudo 在处理 sudoedit 命令行转义字符时产生的堆缓冲区溢出漏洞。攻击者只需具备本地普通用户权限,通常不要求账号存在于 sudoers 中,即可能利用该问题提升至 root。该漏洞适合纳入 Linux 主机漏洞库,重点排查多用户服务器、运维跳板机、开发测试机及容器宿主机。

上游受影响版本主要包括 sudo 1.8.2 至 1.8.31p2、1.9.0 至 1.9.5p1;上游修复版本为 1.8.32、1.9.5p2 及之后版本。发行版经常采用安全补丁回移,因此不能只按版本字符串判断,必须结合软件包修订号和厂商公告。

问题定位

漏洞位于 sudo 对 sudoedit 模式参数的解析流程。sudoedit 通常是指向 sudo 的符号链接,也可以通过 sudo 的 -e 参数进入相同模式。特定反斜杠结尾参数在转义和复制过程中出现长度计算不一致,导致堆内存越界写入。

在授权测试中,建议先做软件包清单和非破坏性行为验证,不要直接运行公开提权利用代码。生产系统上的利用尝试可能造成 sudo 进程崩溃、认证链路异常或不可预测的内存破坏。

技术分析

  • 攻击前提:攻击者已取得本地普通用户会话,例如 SSH 账号、Web 服务落地账号或容器逃逸后的宿主机低权限账号。
  • 权限边界:漏洞发生在 setuid root 的 sudo 程序内,成功利用后可跨越普通用户到 root 的权限边界。
  • sudoers 影响:移除用户的 sudo 授权不能作为有效修复。漏洞触发早于常规授权结果生效,非 sudoers 用户也需要纳入风险评估。
  • 主要留痕:进程执行审计、sudo 日志、系统日志、异常退出记录和 core dump。失败利用可能表现为 malloc、free 或堆一致性检查错误。

授权验证步骤

首先确认二进制属性、sudoedit 链接关系和软件包来源。以下命令只用于资产识别及低风险行为检查,不包含提权载荷。

id
command -v sudo sudoedit
ls -l "$(command -v sudo)" "$(command -v sudoedit)"
sudo --version | head -n 3

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

# RHEL / CentOS / Rocky / AlmaLinux
rpm -q sudo 2>/dev/null
rpm -q --changelog sudo 2>/dev/null | grep -i -m 3 'CVE-2021-3156\|Baron'

authselect current 2>/dev/null || true

在隔离测试机或维护窗口内,可使用下面的最小行为探针。不要附加长参数、环境变量构造或公开利用代码。不同发行版的输出可能不同,因此探针只能作为辅助证据。

sudoedit -s '\'
printf 'exit_code=%s\n' "$?"

历史上,部分未修复版本可能返回“/ 不是普通文件”一类信息,而修复后的版本通常直接打印用法或参数错误。由于厂商补丁回移、国际化消息和二次编译会改变结果,不能仅凭输出判定漏洞存在。最终结论应以发行版安全公告和软件包修订号为准。

发行版补丁核验

检查项核验方法
上游版本sudo --version,判断是否低于 1.8.32 或位于 1.9.0 至 1.9.5p1
发行版修订使用 dpkg-query 或 rpm -q 获取完整包版本,不截断 release 字段
安全公告对照当前发行版、主版本和架构对应的厂商 CVE 公告
实际加载文件确认 sudo 路径、符号链接及文件所属软件包,排除手工安装版本覆盖系统包

如果 /usr/local/bin、配置管理目录或应急工具目录中存在额外 sudo 副本,也应单独检查。只升级包管理器记录中的版本,但 PATH 实际优先调用手工编译副本,仍可能留下风险。

type -a sudo sudoedit
find /usr/local /opt -xdev -type f -name 'sudo*' -perm /4000 -ls 2>/dev/null

# 查询文件归属
dpkg -S "$(command -v sudo)" 2>/dev/null || rpm -qf "$(command -v sudo)" 2>/dev/null

# 校验发行版软件包文件
sudo debsums -s sudo 2>/dev/null || sudo rpm -V sudo 2>/dev/null

日志留痕与排查

sudo 的常规日志不一定完整记录漏洞触发,因为异常可能发生在正常授权日志写入之前。建议联合检查 systemd journal、认证日志、内核崩溃记录和 auditd 的 execve 事件。

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

# RHEL 系
grep -Ei 'sudoedit|sudo:|segfault|malloc|corrupt|core dumped' \
  /var/log/secure /var/log/messages 2>/dev/null

# systemd 与崩溃记录
journalctl --since '7 days ago' | grep -Ei 'sudoedit|sudo|segfault|malloc|corrupt'
coredumpctl list sudo 2>/dev/null
last -Fai | head -n 50

需要临时增强监控时,可审计 sudo 可执行文件的执行事件。规则上线前应评估日志量,并同时覆盖 64 位和 32 位调用。由于 sudoedit 常为符号链接,实际 exe 字段通常仍指向 /usr/bin/sudo,可结合 comm、argc 和 execve 参数分析。

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

sudo ausearch -k sudo_exec -i --start recent
sudo ausearch -m ANOM_ABEND,SECCOMP -i --start this-week

长期规则可以写入 /etc/audit/rules.d/sudo-exec.rules,再通过 augenrules --load 生效。检测时重点关注 sudo 或 sudoedit 被普通服务账号调用、参数中出现异常反斜杠、同一用户短时间重复触发、随后生成 root shell 或修改高价值文件等组合信号。单个 sudoedit 事件不应直接判定为入侵。

入侵迹象检查

如果发现疑似利用行为,不要只升级软件后结束事件。应保留 audit 日志、journal、认证日志和相关 core dump,并检查漏洞触发前后的权限变化。

# 近期新增或异常的 SUID 文件
find / -xdev -type f -perm /4000 -printf '%TY-%Tm-%Td %TH:%TM %u %g %m %p\n' \
  2>/dev/null | sort

# 高价值文件近期变更
stat /etc/passwd /etc/shadow /etc/sudoers /root/.ssh/authorized_keys 2>/dev/null
find /etc/sudoers.d /etc/cron.d /var/spool/cron /root/.ssh \
  -type f -mtime -7 -ls 2>/dev/null

# UID 0 异常账号
awk -F: '$3 == 0 {print $1, $3, $6, $7}' /etc/passwd

# 近期进程与登录线索
journalctl --since '7 days ago' _COMM=sudo
ausearch -m USER_START,USER_LOGIN,USER_CMD -i --start this-week 2>/dev/null
文件时间戳可能被修改,mtime 只能作为线索。条件允许时,应与配置管理基线、包校验结果、集中日志和磁盘快照交叉验证。

修复与缓解建议

  • 通过发行版官方仓库升级 sudo,优先使用厂商标记已修复 CVE-2021-3156 的软件包。不要仅依赖自行编译的版本号比较。
  • 升级后重新执行包版本、文件归属和路径检查,确认运行的不是遗留副本;必要时重启长期运行的管理会话。
  • 无法立即升级时,可临时移除 sudo 二进制的 setuid 位或限制本地登录,但这会破坏正常运维流程,只适合作为经过审批的短时缓解措施。
  • 不能把修改 sudoers、禁止 sudoedit 或移除某个用户的 sudo 权限视为完整修复。
  • 对跳板机和多租户主机启用集中 auditd、认证日志转发及告警,避免本机 root 权限失陷后日志被清除。
  • 若已有可疑崩溃或提权迹象,应按主机失陷处理:隔离主机、保全证据、轮换凭据,并从可信镜像恢复。
# Debian / Ubuntu
sudo apt-get update
sudo apt-get install --only-upgrade sudo

# RHEL / Rocky / AlmaLinux
sudo dnf upgrade sudo

# 升级后复核
sudo --version | head -n 3
dpkg-query -W sudo 2>/dev/null || rpm -q sudo
ls -l "$(command -v sudo)" "$(command -v sudoedit)"

总结

CVE-2021-3156 的核心风险是普通本地用户可借助 setuid root 程序跨越权限边界。漏洞验证应以软件包修订和厂商公告为主,最小行为探针为辅,避免在生产主机直接执行公开提权代码。处置时除升级 sudo 外,还应检查额外二进制副本、异常崩溃、SUID 文件、UID 0 账号及关键持久化位置,才能形成完整的漏洞验证和闭环修复记录。

服务器与云环境安全示意图
服务器、云资产与权限边界梳理示意
漏洞验证与修复流程示意图
漏洞成因、验证条件与修复闭环示意

这个漏洞的验证建议分成“补丁状态确认”和“异常痕迹排查”两部分,不建议直接在生产机运行公开 PoC。Baron Samedit 属于本地提权,攻击者通常需要先取得低权限账户或代码执行能力。

1. 不要只按 sudo 上游版本号判断

上游受影响范围主要是 1.8.2~1.8.31p2、1.9.0~1.9.5p1,但发行版经常回移补丁,所以版本号看似较旧也可能已经修复。应同时检查软件包版本和发行版安全公告:

# Debian / Ubuntu
sudo --version | head -n 1
dpkg-query -W -f='${Package} ${Version}\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
sudo --version | head -n 1
rpm -q sudo
rpm -q --changelog sudo | grep -i -m1 'CVE-2021-3156'
dnf updateinfo info --cves CVE-2021-3156 2>/dev/null

如果机器使用厂商仓库,最终应以对应发行版公告列出的“已修复软件包版本”为准,而不是简单要求升级到上游 1.9.5p2。

2. 留痕排查要注意:普通 sudo 日志通常不足以证明未被利用

先看漏洞修复前后是否出现异常的 sudoedit 调用、sudo 崩溃、堆错误和提权后的账户变更:

# systemd 日志
journalctl --since '2021-01-01' | \
  grep -Ei 'sudo(edit)?|segfault|malloc|free\(\)|corrupted|core dumped'

# Debian / Ubuntu 常见认证日志
zgrep -Eai 'sudo(edit)?|session opened for user root|useradd|usermod' \
  /var/log/auth.log*

# RHEL 系常见认证日志
zgrep -Eai 'sudo(edit)?|session opened for user root|useradd|usermod' \
  /var/log/secure*

# 内核记录中的崩溃
journalctl -k | grep -Ei 'sudo(edit)?.*(segfault|general protection)'
coredumpctl list 2>/dev/null | grep -Ei 'sudo|sudoedit'

需要特别说明:成功利用不一定会留下完整命令行,默认 syslog 也未必记录 argv。因此“没有 sudoedit 日志”不能作为未失陷结论。还应核查修复窗口内新增的 UID 0 账户、异常 SUID 文件和持久化项:

# 非 root 名称但 UID 为 0 的账户
awk -F: '$3 == 0 {print $1 ":" $6 ":" $7}' /etc/passwd

# 最近修改的账户和 sudo 配置
stat /etc/passwd /etc/shadow /etc/group /etc/sudoers
find /etc/sudoers.d -type f -printf '%TY-%Tm-%Td %TH:%TM:%TS %p\n' 2>/dev/null

# 近 30 天新增或修改的 SUID/SGID 文件,结果需结合软件包基线判断
find / -xdev -type f \( -perm -4000 -o -perm -2000 \) \
  -mtime -30 -printf '%TY-%Tm-%Td %TH:%TM %m %u:%g %p\n' 2>/dev/null

# 常见持久化位置
find /etc/cron.d /etc/cron.daily /var/spool/cron /root/.ssh \
  -type f -mtime -30 -ls 2>/dev/null

如果启用了 auditd,可以查询进程执行记录;这里比普通 sudo 日志更有价值:

ausearch -x sudoedit -i
ausearch -x sudo -i
ausearch -m USER_CHAUTHTOK,ADD_USER,DEL_USER,USER_MGMT -i

3. 修复与复核

# Debian / Ubuntu
apt-get update
apt-get install --only-upgrade sudo

# RHEL 系
dnf upgrade sudo
# 老系统可使用:yum update sudo

# 升级后确认包文件未被替换
dpkg -V sudo 2>/dev/null || true
rpm -V sudo 2>/dev/null || true

# 检查 sudo 主程序权限,正常通常应带 setuid 位
stat -c '%A %a %U:%G %n' "$(command -v sudo)"

若暂时无法升级,短期止血可以移除 sudo 的 setuid 位,但这会直接导致普通用户无法使用 sudo,必须确保已有 root 控制台、带外管理或其他恢复路径:

chmod 0755 /usr/bin/sudo

# 完成升级后按发行版软件包预期恢复,通常为:
chown root:root /usr/bin/sudo
chmod 4755 /usr/bin/sudo

对于确认存在可疑崩溃、异常 SUID 文件或未知 UID 0 账户的主机,不建议只升级 sudo 后继续使用。应先隔离主机、保全 journal/audit/core dump 和文件时间线,再轮换本机及可横向访问的凭据;高置信度失陷场景优先从可信镜像重建。

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

最近浏览 0

  • 没有会员查看此页面。