
CVE-2021-3156 (Baron Samedit) Report and Research
作者: IJ Baig
日期: 2026年7月7日
1.8.2 至 1.8.31p2,以及稳定版 1.9.0 至 1.9.5p1。1.9.5p1为安全分析此漏洞,易受攻击的 Sudo 版本已在隔离的非生产环境中编译。

Sudo 1.9.5p1 的源码已下载并在本地使用标准 make 工具编译。注意在本地目录中执行此操作,以避免覆盖主机系统原生的已修补 sudo 二进制文件。

构建确认: 编译完成后,执行了自定义二进制文件以确认正确构建了易受攻击的版本。


plugins/sudoers/sudoers.cset_cmnd()(位于 1.9.5p1 版本约第 864 行)
假设你有一个助手,其工作是在将单词列表放入新分配的存储箱(堆缓冲区)之前移除其中的转义字符(反斜杠)。该助手盲目地假设每个反斜杠总是后跟一个有效字符,因此每当看到反斜杠时,它就跳过它并复制下一个字符。
然而,程序在运行 sudoedit -s 时处理参数的方式存在一个缺陷。它允许用户混入一个恰好以单个反斜杠(\)结尾的单词,紧随其后的是不可见的单词结束标记(空终止符 \0)。
当助手的代码遇到这个尾部反斜杠时,它会跳过它并查看下一个字符——空终止符。if 语句的逻辑不但没有停止,反而迫使助手也跳过空终止符。循环继续执行,将接下来出现的任意越界内存复制到存储箱中。这种超出预期单词长度的持续复制会使指定缓冲区溢出,导致严重的基于堆的缓冲区溢出。
易受攻击的代码片段:
/* Unescape characters, skipping over backslashes */
for (to = user_args, av = NewArgv + 1; (from = *av); av++) {
while (*from) {
// VULNERABILITY: If from[0] is '\' and from[1] is '\0',
// the loop evaluates to true, increments 'from', skipping the null terminator.
if (from[0] == '\\' && !isspace((unsigned char)from[1]))
from++;
*to++ = *from++;
}
*to++ = ' ';
}
*--to = '\0';
Sudo 开发者在 1.9.5p2 版本中通过添加严格边界检查修复了此逻辑错误。现在代码在尝试取消转义之前,会明确确保反斜杠后面的字符不是空终止符。
补丁差异:
- if (from[0] == '\\' && !isspace((unsigned char)from[1]))
+ if (from[0] == '\\' && from[1] != '\0' && !isspace((unsigned char)from[1]))
为什么这能修复根因:
添加 from[1] != '\0' 可立即阻止越界读取。现在,如果代码在字符串最末尾遇到尾部反斜杠(意味着 from[1] 是空终止符),if 语句将判定为 false。指针不会过早递增,空终止符会被正确地作为字符串结尾处理,循环安全终止而不会导致堆溢出。
本次复现使用了由安全研究员 Worawit 开发的广受认可的 Python 漏洞利用脚本(具体为 exploit_nss.py 变体)。
在执行 PoC 之前,理解其机制至关重要。该脚本并非简单地使程序崩溃;它会精心编排高度精确的内存操作以获得代码执行能力。
以下是 PoC 操作的逐步分解:
.so)。该载荷旨在以 root 身份执行 /bin/sh。LC_ALL、LANG 和 TZ)。由于 Sudo 在启动时将环境变量加载到堆上,脚本会计算精确的大小,以将堆排列成可预测的布局。sudoedit -s 并传入以单个反斜杠结尾的命令行参数。这会触发第 2 节讨论的 off-by-one 漏洞,导致越界写入。service_user 结构体。该结构体由名称服务切换(NSS)用于查找系统信息。service_user 结构体被篡改为指向第 1 步编译的恶意 .so 库。当 Sudo 尝试查找用户权限时,它会盲目加载并执行攻击者的库,从而授予 root shell。首先,进行了基础崩溃测试,以证明漏洞存在而无需将其武器化。

接下来,针对易受攻击的二进制文件执行了完整的 Worawit exploit_nss.py 脚本。

为验证官方修复,对已修补的 Sudo 二进制文件执行了完全相同的 PoC 触发命令。
sudoedit -s '\' 2>&1 | grep -q "sudoedit:" && echo "Vulnerable" || echo "Not vulnerable"

Sudo 是我们服务器上使用的标准管理程序,在处理包含反斜杠的文本输入时存在严重缺陷。通过精心构造畸形命令,具有基本用户访问权限的攻击者可以诱使系统在其指定内存区域之外写入数据。这一失误使攻击者能够完全绕过安全控制,在无需密码的情况下获得机器的完全未授权管理权限。
挑战: 主要挑战之一是堆操作的脆弱性。针对特定操作系统版本的漏洞载荷常常在其他版本上失败,因为底层标准 C 库(glibc)以不同方式管理内存块。成功武器化此漏洞需要精确理解目标环境特有的内存对齐和环境变量布局(堆风水)。
经验教训: 从防御和安全运营的角度来看,这次深入分析强化了几个关键概念:
sudoedit -s 命令,可使 SOC 团队在补丁全面部署到基础设施之前检测到利用尝试。类似 CVE: CVE-2019-14287(Sudo 安全绕过)
同一 Sudo 代码库中的另一个著名漏洞具有类似的根因模式:对用户输入的不当解析和验证。在 CVE-2019-14287 中,Sudo 解析用户 ID(UID)方式中的逻辑缺陷允许攻击者通过指定用户 ID -1 或 4294967295 以 root 身份执行命令。
相似之处: 虽然 Baron Samedit(CVE-2021-3156)是内存损坏缺陷,而 CVE-2019-14287 是授权绕过,但两者在根本原因上都是初始参数解析逻辑的失败。这两个漏洞都源于 Sudo 在执行其核心特权功能之前,错误地信任并错误处理了边缘情况的命令行参数(尾部反斜杠与意外的整数回绕)。
安全与道德声明: 本报告中展示的所有漏洞利用和测试均完全在隔离的、经授权的本地虚拟机中进行。在此过程中未针对或接触任何生产系统或未经授权的网络。