cve-2021-3156的poc流程分析
字数 1607 2025-08-10 08:28:35

CVE-2021-3156 (Sudo堆溢出漏洞) POC流程分析

漏洞概述

CVE-2021-3156是Sudo程序中的一个堆缓冲区溢出漏洞,由Qualys安全团队发现并命名为"Baron Samedit"。该漏洞存在于Sudo的set_cmnd函数中,允许本地攻击者通过精心构造的参数在无需身份验证的情况下获得root权限。

前置知识

1. Linux动态链接库机制

  • LD_PRELOAD环境变量:允许用户在程序运行前预加载指定的共享库
  • 常用于PHP的bypass_disable_function攻击中
  • 攻击方式:
    • 通过设置LD_PRELOAD加载恶意动态链接库
    • 可以重写函数或使用__attribute__特殊函数直接执行恶意代码
  • 限制:glibc对setuid程序有验证,会禁用LD_PRELOAD加载

2. SUID文件特性

  • SUID (Set User ID)文件允许执行者以文件所有者权限运行
  • 典型例子:/usr/bin/sudo,普通用户执行时具有root权限
  • 安全限制:SUID程序运行时环境变量受到严格限制

漏洞原理分析

漏洞位置

漏洞存在于sudoers.so模块的set_cmnd函数中,该函数在处理命令行参数时存在堆缓冲区溢出。

关键漏洞代码行为

  1. set_cmnd函数中to变量分配的缓冲区大小有限(0x70字节)
  2. 处理转义字符时逻辑错误:
    • 当遇到\字符时,from指针会向后移动一位
    • 然后写入\x00to缓冲区
    • from指针再次增加,跳过后续字符
    • 导致可以写入超出分配缓冲区大小的数据

利用条件

  • 需要构造特定的命令行参数触发溢出
  • 溢出数据可以覆盖堆中的关键数据结构
  • 最终目标是修改service_user结构体,加载恶意动态链接库

POC流程详细分析

环境准备

  1. 下载与系统相同版本的sudo源码(示例使用sudo 1.8.21)
  2. 编译安装调试版本sudo:
    ./configure --enable-debug
    make
    make install
    
  3. 复制生成的可执行文件并设置SUID权限:
    cp /usr/bin/sudo /usr/bin/sudd
    chown root:root /usr/bin/sudd
    chmod u+s /usr/bin/sudd
    

调试过程

  1. 初始调试设置

    • hax.cexecve处设置断点
    • __libc_start_main设置断点跟踪子进程
    • 在源码310行设置断点
  2. 动态链接库加载分析

    • 使用_dl_open断点跟踪sudoers.so加载
    • 加载完成后,在set_cmnd函数设置断点
  3. 堆溢出观察

    • 观察to变量分配的0x70字节缓冲区
    • 后面跟随的是unsortedbin的chunk(调试版本布局)
    • 通过构造的转义字符序列可以溢出写入后续内存区域
  4. 关键数据结构修改

    • 使用find命令定位systemd字符串
    • 设置内存观察点(watch)跟踪修改
    • 确认service_user结构体被成功修改

利用技术细节

  1. service_user结构体攻击

    • 修改compat字段的名称
    • 确保修改后的名称不在database->library
    • 使ni->library->lib_handle为NULL
  2. 恶意库加载机制

    • nss_load_library函数检查ni->library->lib_handle
    • 如果为NULL,则触发__libc_dlopen加载库
    • 加载路径构造为libnss_X/P0P_SH3LLZ_ .so.2
  3. 提权完成

    • 恶意库中包含提权代码
    • 成功加载后获得root shell

防御措施

  1. 及时更新sudo到安全版本
  2. 限制不必要的SUID权限
  3. 使用Linux内核防护机制(如ASLR, SELinux)
  4. 监控异常sudo调用行为

总结

CVE-2021-3156通过精心构造的命令行参数触发sudo的堆溢出,修改关键数据结构导致恶意动态链接库加载,最终实现权限提升。该漏洞利用涉及Linux动态链接机制、堆内存管理和SUID特性等多个系统组件的深入理解。

CVE-2021-3156 (Sudo堆溢出漏洞) POC流程分析 漏洞概述 CVE-2021-3156是Sudo程序中的一个堆缓冲区溢出漏洞,由Qualys安全团队发现并命名为"Baron Samedit"。该漏洞存在于Sudo的set_ cmnd函数中,允许本地攻击者通过精心构造的参数在无需身份验证的情况下获得root权限。 前置知识 1. Linux动态链接库机制 LD_ PRELOAD环境变量 :允许用户在程序运行前预加载指定的共享库 常用于PHP的bypass_ disable_ function攻击中 攻击方式: 通过设置LD_ PRELOAD加载恶意动态链接库 可以重写函数或使用 __attribute__ 特殊函数直接执行恶意代码 限制 :glibc对setuid程序有验证,会禁用LD_ PRELOAD加载 2. SUID文件特性 SUID (Set User ID)文件允许执行者以文件所有者权限运行 典型例子:/usr/bin/sudo,普通用户执行时具有root权限 安全限制:SUID程序运行时环境变量受到严格限制 漏洞原理分析 漏洞位置 漏洞存在于 sudoers.so 模块的 set_cmnd 函数中,该函数在处理命令行参数时存在堆缓冲区溢出。 关键漏洞代码行为 set_cmnd 函数中 to 变量分配的缓冲区大小有限(0x70字节) 处理转义字符时逻辑错误: 当遇到 \ 字符时, from 指针会向后移动一位 然后写入 \x00 到 to 缓冲区 from 指针再次增加,跳过后续字符 导致可以写入超出分配缓冲区大小的数据 利用条件 需要构造特定的命令行参数触发溢出 溢出数据可以覆盖堆中的关键数据结构 最终目标是修改 service_user 结构体,加载恶意动态链接库 POC流程详细分析 环境准备 下载与系统相同版本的sudo源码(示例使用sudo 1.8.21) 编译安装调试版本sudo: 复制生成的可执行文件并设置SUID权限: 调试过程 初始调试设置 : 在 hax.c 的 execve 处设置断点 在 __libc_start_main 设置断点跟踪子进程 在源码310行设置断点 动态链接库加载分析 : 使用 _dl_open 断点跟踪 sudoers.so 加载 加载完成后,在 set_cmnd 函数设置断点 堆溢出观察 : 观察 to 变量分配的0x70字节缓冲区 后面跟随的是unsortedbin的chunk(调试版本布局) 通过构造的转义字符序列可以溢出写入后续内存区域 关键数据结构修改 : 使用 find 命令定位 systemd 字符串 设置内存观察点(watch)跟踪修改 确认 service_user 结构体被成功修改 利用技术细节 service_ user结构体攻击 : 修改 compat 字段的名称 确保修改后的名称不在 database->library 中 使 ni->library->lib_handle 为NULL 恶意库加载机制 : nss_load_library 函数检查 ni->library->lib_handle 如果为NULL,则触发 __libc_dlopen 加载库 加载路径构造为 libnss_X/P0P_SH3LLZ_ .so.2 提权完成 : 恶意库中包含提权代码 成功加载后获得root shell 防御措施 及时更新sudo到安全版本 限制不必要的SUID权限 使用Linux内核防护机制(如ASLR, SELinux) 监控异常sudo调用行为 总结 CVE-2021-3156通过精心构造的命令行参数触发sudo的堆溢出,修改关键数据结构导致恶意动态链接库加载,最终实现权限提升。该漏洞利用涉及Linux动态链接机制、堆内存管理和SUID特性等多个系统组件的深入理解。