-
-
[分享]CVE-2021-3156漏洞分析:从sudo堆溢出到提权的技术剖析
-
发表于: 2025-12-6 10:49 415
-
概述
2021年1月,一个影响近十年所有Linux发行版的严重本地提权漏洞被发现,该漏洞被分配编号CVE-2021-3156,因其利用方式被安全社区称为“Baron Samedit”。该漏洞允许任何非特权用户在默认配置的Linux系统上获得root权限,影响了从Ubuntu、Debian到CentOS、RedHat等主流发行版。
漏洞基本信息
CVE编号:CVE-2021-3156
漏洞类型:基于堆的缓冲区溢出
影响范围:sudo 1.8.2 - 1.8.31p2, 1.9.0 - 1.9.5p1
CVSS评分:7.8(高危)
发现者:Qualys安全研究团队
技术背景:sudo与参数解析
sudo是Linux/Unix系统中用于临时提升权限的核心工具,它允许授权用户以root身份执行命令。在执行过程中,sudo需要对用户输入的命令参数进行解析和处理。
漏洞存在于sudoers策略插件中,具体位置在sudoers.so模块的set_cmnd()函数。该函数负责将命令行参数复制到堆缓冲区中,用于日志记录和策略匹配。
漏洞原理分析
1. 根本原因
漏洞的核心问题在于命令行参数解析时的逻辑错误。当sudo以特殊模式(-s或-i选项)运行时,它会在参数后添加反斜杠转义,但错误地判断了何时需要添加转义。
关键代码段(简化):
c
复制下载
// 漏洞代码逻辑for (size = 0, av = NewArgv + 1; *av; av++) {
size += strlen(*av) + 1;
if (size >= cmnd_size) {
cmnd_size += 8192;
user_cmnd = realloc(user_cmnd, cmnd_size);
}
// 错误:没有正确检查转义条件
for (from = *av; *from; from++) {
if (from[0] == '\\' && !isspace(from[1]))
continue; // 错误逻辑:跳过而不复制反斜杠
*user_cmnd++ = *from;
}
*user_cmnd++ = ' ';}2. 触发条件
要触发漏洞,需要满足:
sudo以
-s(启动shell)或-i(模拟初始登录)选项运行命令行参数以单个反斜杠
\结尾该反斜杠后跟空白字符(空格、制表符等)
例如:
bash
复制下载
sudo -s '\' `perl -e 'print "A" x 1000'`
3. 溢出机制
当遇到上述情况时:
解析器看到反斜杠加空白字符的组合
它错误地认为需要跳过反斜杠而不复制
但缓冲区指针仍向前移动,导致写入位置计算错误
后续复制操作会超出分配的堆缓冲区边界
漏洞利用技术分析
堆布局与内存破坏
堆风水(Heap Feng Shui):
攻击者通过控制分配和释放操作,精心布局堆内存
目标是在
user_cmnd缓冲区后放置敏感数据或控制结构溢出目标:
c
复制下载
struct service_user { char *name; char *library; int free_name;};通过覆盖
service_user结构,可以控制library指针,实现任意代码执行利用步骤:
a. 通过多次分配和释放操作塑造堆布局
b. 触发缓冲区溢出,覆盖相邻的service_user结构
c. 将library指针指向攻击者控制的路径
d. 触发nss_load_library()调用,加载恶意库
e. 恶意库的构造函数以root权限执行
实际利用的限制与挑战
ASLR绕过:需要信息泄露或部分覆盖技术
堆分配随机性:现代glibc的堆分配具有一定随机性
大小限制:溢出数据量受命令行长度限制
修复方案分析
官方补丁
sudo项目发布了1.9.5p2版本修复此漏洞,主要修改包括:
正确转义处理:
c
复制下载
// 修复后的逻辑for (size = 0, av = NewArgv + 1; *av; av++) {
size += strlen(*av) + 1;
if (size >= cmnd_size) {
cmnd_size += 8192;
user_cmnd = realloc(user_cmnd, cmnd_size);
}
// 修复:正确处理所有情况
for (from = *av; *from; from++) {
if (from[0] == '\\' && !isspace((unsigned char)from[1])) {
if (from[1] != '\0') {
// 复制反斜杠
*user_cmnd++ = *from;
}
} else {
*user_cmnd++ = *from;
}
}
*user_cmnd++ = ' ';}边界检查增强:
添加更严格的缓冲区边界检查
改进大小计算逻辑
临时缓解措施
在补丁可用前,系统管理员可以采用以下缓解措施:
删除sudo的setuid位:
bash
复制下载
chmod 0755 /usr/bin/sudo
但这会破坏sudo的正常功能
限制sudo使用:
bash
复制下载
# 在/etc/sudoers中添加Defaults !use_pty
使用sudo的noexec功能:
bash
复制下载
# 限制shell执行admin ALL=(ALL) ALL, !/bin/bash, !/bin/sh
漏洞影响与启示
影响评估
广泛性:影响2011年以来几乎所有Linux发行版
严重性:本地提权,无需用户交互
隐蔽性:漏洞存在于核心系统工具中
安全启示
输入验证的重要性:即使是信任边界内的工具也需要严格的输入验证
最小权限原则:sudo这样的特权工具应尽量减少攻击面
代码审计的必要性:关键安全工具的代码需要定期审计
深度防御:即使单个漏洞被利用,其他安全机制应能提供保护
检测与响应
漏洞检测:
bash
复制下载
# 简单的检测脚本sudoedit -s '\' `perl -e 'print "A" x 100'` 2>&1 | grep -q "malloc" && echo "VULNERABLE"
入侵检测:
监控异常的sudo使用模式
检查/etc/ld.so.preload等文件的变化
使用审计子系统记录所有sudo调用
总结
CVE-2021-3156是一个典型的逻辑漏洞导致的缓冲区溢出案例,它展示了几个重要安全原则:
边界检查失败:即使是最成熟的工具也可能存在基本的缓冲区处理错误
路径组合触发:多个条件组合才能触发的漏洞可能长期潜伏
权限提升影响:系统核心工具的漏洞影响尤为严重
这个漏洞也提醒我们,安全是一个持续的过程,即使是被广泛使用和审计的工具也可能存在严重的安全问题。定期的更新、深度防御策略和持续的安全监控是维护系统安全的关键措施。
参考资料
Qualys安全公告(2021年1月)
sudo项目官方安全公告
各Linux发行版安全公告
MITRE CVE数据库条目
相关技术分析文章和漏洞利用代码分析