发布于16小时前16小时 漏洞概况CVE-2021-3156,又称 Baron Samedit,是 sudo/sudoedit 参数解析过程中的堆缓冲区溢出漏洞。攻击者只需具备本地普通用户权限,即可能利用以 setuid root 运行的 sudo 获取 root 权限。漏洞类型:本地权限提升、堆缓冲区溢出影响组件:sudo、sudoeditCWE:CWE-122CVSS 3.x:7.8上游影响范围:sudo 1.8.2 至 1.8.31p2、1.9.0 至 1.9.5p1上游修复版本:sudo 1.9.5p2利用前提:攻击者已获得本地普通用户执行权限发行版通常会将补丁回移到旧版本,因此不能只根据 sudo 的上游版本号判断是否存在漏洞,应同时核对发行版安全公告和软件包 changelog。权限边界与风险该漏洞不要求用户出现在 sudoers 文件中,也不要求其拥有任何 sudo 命令授权。只要系统上的 sudo 二进制保留 setuid root 权限,本地低权限账户就处于潜在攻击面内。在授权渗透或主机失陷排查中,以下入口需要重点关注:Web 服务被写入 WebShell 后获得的 www-data、apache、nginx 等账户。容器逃逸后进入宿主机的低权限账户。运维跳板机、开发服务器上的普通 SSH 账户。定时任务、CI Runner 或中间件服务账户。允许本地交互登录但不在 sudo 组中的外包或临时账户。如果攻击成功,攻击者可能读取密钥与配置、修改审计日志、植入持久化任务,或继续横向使用主机上的凭据。该漏洞应按完整 root 权限失陷风险处理。技术分析sudo 在以 sudoedit 方式运行并处理 shell 模式参数时,对反斜杠转义字符的解析存在不一致。参数长度计算与后续反转义复制使用了不同的边界条件,特定输入可导致数据写出目标堆缓冲区。由于 sudo 通常带有 setuid 位,相关解析代码运行在 root 权限上下文中。攻击者可尝试控制相邻堆对象,使单纯的越界写进一步转化为代码执行。漏洞核心不在 sudoers 授权规则,因此配置“用户无 sudo 权限”不能阻断此问题。资产与版本排查首先确认 sudo 的真实路径、文件权限、安装来源和发行版修订版本。以下命令只读取系统信息,不触发漏洞利用:# 二进制路径与 setuid 状态 command -v sudo command -v sudoedit ls -l "$(command -v sudo)" "$(command -v sudoedit)" stat -c '%A %a %U:%G %n' "$(command -v sudo)" # 上游版本及插件版本 sudo --version | head -n 12 # Debian / Ubuntu dpkg-query -W -f='${Package} ${Version} ${Architecture}\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 / Fedora rpm -q sudo --qf '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n' rpm -q --changelog sudo | grep -i -m 3 'CVE-2021-3156'正常情况下,sudo 文件权限中会出现 s,例如 -rwsr-xr-x。若所在挂载点启用了 nosuid,内核不会赋予其 setuid 权限,但这只能视为当前利用条件受限,不能替代软件修复。# 检查 sudo 所在文件系统及挂载参数 findmnt -T "$(command -v sudo)" -o TARGET,SOURCE,FSTYPE,OPTIONS # 核对软件包文件是否被本地修改 # Debian / Ubuntu dpkg -V sudo # RPM 系发行版 rpm -V sudo判断时应遵循以下顺序:优先查看发行版安全公告是否明确标注 CVE-2021-3156 已修复。检查已安装包的完整发行版版本号,包括 revision、release 和 security 后缀。通过包内 changelog 或厂商漏洞数据库确认是否包含回移补丁。不要因为版本号低于 1.9.5p2 就直接认定存在漏洞,也不要因为运行时未崩溃就认定安全。授权验证建议生产环境不建议直接运行公开利用脚本,也不建议使用可能触发堆损坏的探测参数。堆布局会受发行版、glibc、环境变量和本地配置影响,失败的验证可能只表现为进程崩溃,同时留下不完整证据。授权测试中建议采用“软件包证据优先”的验证方式:记录操作系统版本、内核版本、sudo 包完整版本和仓库来源。确认 sudo 是否具有 setuid root 权限。确认本地低权限账户能否执行 sudo 二进制;无需验证其 sudoers 权限。对照对应发行版公告判断当前软件包是否包含补丁。需要动态复现时,应使用隔离快照、测试账户和与目标一致的软件包构建环境,不在业务主机执行利用载荷。# 建议保存到授权测试证据中的基础信息 id uname -a cat /etc/os-release sudo --version | head -n 12 stat -c '%A %a %U:%G %n' "$(command -v sudo)" findmnt -T "$(command -v sudo)" -o TARGET,SOURCE,FSTYPE,OPTIONS日志留痕与失陷排查该漏洞利用发生在本地进程中,sudo 日志未必包含完整命令参数。成功利用后,攻击者也可能主动删除 auth.log 或 journal,因此“未发现 sudo 记录”不能证明未被利用。可先检查 sudo、sudoedit 调用记录以及内核中的崩溃信息:# systemd journal journalctl --since '7 days ago' _COMM=sudo journalctl --since '7 days ago' _COMM=sudoedit journalctl -k --since '7 days ago' | grep -Ei 'sudo(edit)?.*(segfault|general protection|core dumped)' # Debian / Ubuntu 传统日志 zgrep -hEi 'sudo|sudoedit|segfault|general protection' /var/log/auth.log* /var/log/kern.log* 2>/dev/null # RHEL 系传统日志 zgrep -hEi 'sudo|sudoedit|segfault|general protection' /var/log/secure* /var/log/messages* 2>/dev/null # auditd 已启用时 ausearch -x sudo -ts recent -i ausearch -x sudoedit -ts recent -i ausearch -m EXECVE -ts recent -i | grep -Ei 'sudo|sudoedit'需要重点关联的异常包括:普通服务账户执行 sudo 或 sudoedit,但 sudoers 中没有对应业务需求。sudo 进程出现 segfault、general protection fault 或异常 core dump。sudo 调用后短时间内出现 uid=0 的 shell、解释器或网络工具。/etc/sudoers.d、/etc/passwd、/etc/shadow、root 的 authorized_keys 被修改。/etc/cron.d、systemd unit、LD_PRELOAD 配置或 setuid 文件出现新增和变更。# 排查近期权限与持久化变更 find /etc/sudoers.d /etc/cron.d /etc/systemd/system /root/.ssh \ -xdev -type f -mtime -14 -ls 2>/dev/null # 查找异常 setuid 文件,结果应与基线比对 find / -xdev -type f -perm -4000 -ls 2>/dev/null # 检查关键账户文件时间与属性 stat /etc/passwd /etc/shadow /etc/sudoers /root/.ssh/authorized_keys 2>/dev/null # 查看近期 root 进程执行记录,前提是已部署 auditd ausearch -ua 0 -ts recent -m EXECVE -i补充审计规则尚未完成批量升级时,可临时增加 sudo 执行审计,用于缩短暴露窗口内的调查盲区。auditd 规则只能提供留痕,不能阻止漏洞利用。# 临时规则,重启后失效 auditctl -w /usr/bin/sudo -p x -k sudo_exec # 某些系统中 sudoedit 是指向 sudo 的符号链接,先确认实际路径 readlink -f /usr/bin/sudoedit # 持久化规则 cat > /etc/audit/rules.d/50-sudo-exec.rules <<'EOF' -w /usr/bin/sudo -p x -k sudo_exec EOF augenrules --load ausearch -k sudo_exec -i审计规则上线前应评估日志量,尤其是多人运维机和自动化平台。sudoedit 通常通过 argv[0] 区分运行模式,调查 EXECVE 记录时不仅要看 exe 字段,也要检查 a0 参数是否为 sudoedit。修复步骤首选方案是从受信任的发行版仓库升级 sudo。升级前保持一个经过授权的 root 控制台会话,避免包管理或 sudo 配置异常造成远程失联。# Debian / Ubuntu apt-get update apt-get install --only-upgrade sudo # RHEL / Rocky / AlmaLinux / Fedora dnf upgrade sudo # 旧版 CentOS / RHEL yum update sudo # 升级后再次确认 sudo --version | head -n 12 dpkg-query -W sudo 2>/dev/null || rpm -q sudo若暂时无法升级,可在具备控制台 root 通道的维护窗口中移除 sudo 的 setuid 位,作为短时应急措施:# 执行前必须确认另有可用的 root 登录或控制台通道 chmod u-s /usr/bin/sudo stat -c '%A %a %U:%G %n' /usr/bin/sudo该措施会使正常 sudo 提权失效,可能影响自动化任务。完成软件包升级后,应通过重新安装或修复发行版软件包恢复正确权限,不建议脱离包管理器长期手工维护权限位。修复验证确认当前安装包已被发行版标记为修复 CVE-2021-3156。确认软件包来源未指向未知第三方仓库。确认 sudo 二进制校验结果没有非预期修改。确认 sudoers 配置语法正常,业务授权未被扩大。回看升级前后的 sudo、audit 和内核日志,确认不存在异常提权痕迹。# sudoers 配置检查 visudo -c # 查看启用的仓库与软件包来源 apt-cache policy sudo 2>/dev/null repoquery -i sudo 2>/dev/null # 检查升级时间附近的日志 journalctl --since '2 hours ago' | grep -Ei 'sudo|sudoedit|package|dnf|yum|apt'结论CVE-2021-3156 的关键风险在于它绕过了 sudoers 权限边界:本地账户是否被授予 sudo 权限并不是安全判断条件。排查时应围绕软件包补丁状态、setuid 条件、本地账户入口和审计日志建立证据链。修复应以发行版安全更新为准,动态利用验证只应在授权、隔离且可回滚的复现环境中进行。若日志中已经出现异常 sudo 崩溃或低权限账户后的 root 活动,应按主机失陷流程处置,而不是仅完成补丁升级。 服务器、云资产与权限边界梳理示意 漏洞成因、验证条件与修复闭环示意
15小时前15小时 这个漏洞排查时不要只比较 sudo --version,很多发行版会在版本号基本不变的情况下回补补丁。上游受影响范围大致为 1.8.2~1.8.31p2、1.9.0~1.9.5p1,但最终应以发行版安全公告和软件包修订号为准。 可以先确认实际二进制、版本及包来源: command -v sudo sudo --version | head -n 1 ls -l "$(command -v sudo)" readlink -f "$(command -v 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 / Alma rpm -q sudo rpm -q --changelog sudo | grep -i -m1 'CVE-2021-3156' dnf updateinfo info --cves CVE-2021-3156 2>/dev/null || \ yum updateinfo info --cves CVE-2021-3156 # SUSE rpm -q sudo zypper lp --cve CVE-2021-3156 # Arch pacman -Qi sudo | grep -E '^(Name|Version)' 需要注意的是,攻击者只要已经取得本地普通账号即可利用,并不要求该账号存在于 sudoers。因此“用户没有 sudo 权限”不能作为未受影响的依据。 修复优先使用发行版仓库提供的安全更新,不建议直接手工覆盖 /usr/bin/sudo: # Debian / Ubuntu apt-get update apt-get install --only-upgrade sudo # RHEL 系 dnf upgrade sudo # 老版本系统 yum update sudo # SUSE zypper update sudo # Arch pacman -Syu sudo 更新后重新查询包版本,并检查文件是否仍由包管理器维护: # Debian / Ubuntu dpkg -V sudo dpkg-query -W -f='${Version}\n' sudo # RPM 系 rpm -V sudo rpm -q sudo sudo 通常是短生命周期进程,升级后一般不需要重启系统;但应结束现有管理员会话并重新执行一次,确认调用的是已更新的文件。多台机器排查时,建议采集“发行版、系统版本、sudo 包完整版本、仓库来源”,而不是只收集上游版本号。 如果暂时无法升级,较直接的临时缓解方式是撤销 sudo 的 SUID 位: chmod u-s /usr/bin/sudo 这会导致普通用户完全无法通过 sudo 提权,执行前必须确保有可用的 root 控制台、带外管理或其他恢复通道。完成升级后,应通过重新安装软件包恢复正确权限,而不是凭经验手工设置: # Debian / Ubuntu apt-get --reinstall install sudo # RPM 系 dnf reinstall sudo 最后,单纯查看 sudo 日志不一定能判断是否被利用,因为该漏洞可能在正常策略校验前触发。若怀疑主机已失陷,应进一步核查补丁前后的异常本地登录、近期新增 SUID 文件、root 权限进程和持久化项: find / -xdev -type f -perm -4000 -printf '%TY-%Tm-%Td %TH:%TM %u %p\n' 2>/dev/null | sort awk -F: '$3 == 0 {print $1 ":" $6 ":" $7}' /etc/passwd systemctl list-unit-files --state=enabled find /etc/cron* /var/spool/cron -type f -mtime -30 -ls 2>/dev/null journalctl --since '30 days ago' _UID=0 2>/dev/null 不建议在生产机上直接运行公开 PoC 做验证;以厂商包状态、软件包修订号和完整性检查作为判定依据更稳妥。
创建帐户或登录后发表意见