首页
社区
课程
招聘
[分享]CVE-2021-3156漏洞分析:从sudo堆溢出到提权的技术剖析
发表于: 2025-12-6 10:49 415

[分享]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. 溢出机制

当遇到上述情况时:

  1. 解析器看到反斜杠加空白字符的组合

  2. 它错误地认为需要跳过反斜杠而不复制

  3. 但缓冲区指针仍向前移动,导致写入位置计算错误

  4. 后续复制操作会超出分配的堆缓冲区边界

漏洞利用技术分析

堆布局与内存破坏

  1. 堆风水(Heap Feng Shui)

    • 攻击者通过控制分配和释放操作,精心布局堆内存

    • 目标是在user_cmnd缓冲区后放置敏感数据或控制结构

  2. 溢出目标

    c

    复制下载

    struct service_user {
        char *name;
        char *library;
        int free_name;};

    通过覆盖service_user结构,可以控制library指针,实现任意代码执行

  3. 利用步骤
    a. 通过多次分配和释放操作塑造堆布局
    b. 触发缓冲区溢出,覆盖相邻的service_user结构
    c. 将library指针指向攻击者控制的路径
    d. 触发nss_load_library()调用,加载恶意库
    e. 恶意库的构造函数以root权限执行

实际利用的限制与挑战

  1. ASLR绕过:需要信息泄露或部分覆盖技术

  2. 堆分配随机性:现代glibc的堆分配具有一定随机性

  3. 大小限制:溢出数据量受命令行长度限制

修复方案分析

官方补丁

sudo项目发布了1.9.5p2版本修复此漏洞,主要修改包括:

  1. 正确转义处理

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++ = ' ';}
  1. 边界检查增强

    • 添加更严格的缓冲区边界检查

    • 改进大小计算逻辑

临时缓解措施

在补丁可用前,系统管理员可以采用以下缓解措施:

  1. 删除sudo的setuid位

    bash

    复制下载

    chmod 0755 /usr/bin/sudo

    但这会破坏sudo的正常功能

  2. 限制sudo使用

    bash

    复制下载

    # 在/etc/sudoers中添加Defaults !use_pty
  3. 使用sudo的noexec功能

    bash

    复制下载

    # 限制shell执行admin ALL=(ALL) ALL, !/bin/bash, !/bin/sh

漏洞影响与启示

影响评估

  1. 广泛性:影响2011年以来几乎所有Linux发行版

  2. 严重性:本地提权,无需用户交互

  3. 隐蔽性:漏洞存在于核心系统工具中

安全启示

  1. 输入验证的重要性:即使是信任边界内的工具也需要严格的输入验证

  2. 最小权限原则:sudo这样的特权工具应尽量减少攻击面

  3. 代码审计的必要性:关键安全工具的代码需要定期审计

  4. 深度防御:即使单个漏洞被利用,其他安全机制应能提供保护

检测与响应

  1. 漏洞检测

    bash

    复制下载

    # 简单的检测脚本sudoedit -s '\' `perl -e 'print "A" x 100'` 2>&1 | grep -q "malloc" && echo "VULNERABLE"
  2. 入侵检测

    • 监控异常的sudo使用模式

    • 检查/etc/ld.so.preload等文件的变化

    • 使用审计子系统记录所有sudo调用

总结

CVE-2021-3156是一个典型的逻辑漏洞导致的缓冲区溢出案例,它展示了几个重要安全原则:

  1. 边界检查失败:即使是最成熟的工具也可能存在基本的缓冲区处理错误

  2. 路径组合触发:多个条件组合才能触发的漏洞可能长期潜伏

  3. 权限提升影响:系统核心工具的漏洞影响尤为严重

这个漏洞也提醒我们,安全是一个持续的过程,即使是被广泛使用和审计的工具也可能存在严重的安全问题。定期的更新、深度防御策略和持续的安全监控是维护系统安全的关键措施。

参考资料

  1. Qualys安全公告(2021年1月)

  2. sudo项目官方安全公告

  3. 各Linux发行版安全公告

  4. MITRE CVE数据库条目

  5. 相关技术分析文章和漏洞利用代码分析



[培训]Windows内核深度攻防:从Hook技术到Rootkit实战!

收藏
免费 0
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回