Fuzz挖掘sudo提权漏洞:一次堆溢出如何逆向分析出提权思路
字数 2244 2025-08-29 22:41:10
Fuzz挖掘sudo提权漏洞:堆溢出分析与提权思路
一、文章概述
本文详细记录了从Fuzz测试发现sudo堆溢出漏洞到最终构造提权POC的全过程。重点分析了堆溢出漏洞的成因、NSS服务劫持提权原理以及利用setlocale进行堆布局的技术。通过逆向分析和动态调试,揭示了如何将CTF-Pwn中的堆利用技术应用于实际漏洞利用中。
二、sudo调研与Fuzz方式考察
sudo简介
sudo(superuser do)是Linux/Unix系统中常用的命令,允许普通用户以root权限执行命令。通过/etc/sudoers配置文件管理用户权限。
常规Fuzz的挑战
- 密码输入问题:sudo执行需要密码,自动化Fuzz会挂起
- 命令行参数处理:需要正确传递参数格式
- 参数控制难题:第一个参数(命令)需要精准控制
- 程序内部复杂性:sudo和sudoedit功能在同一程序中
AFL++命令行参数Fuzz
AFL++的argv_fuzz工具可对命令行参数进行模糊测试。使用方法:
- 包含头文件
#include "argv-fuzz-inl.h" - 在主函数开头使用宏:
AFL_INIT_ARGV():不保留argv[0]AFL_INIT_SET0("prog_name"):保留argv[0]
三、修改sudo源码与AFL++模糊测试
源码修改关键点
- Patch密码验证函数:
verify_user直接返回0 - 添加AFL++头文件并初始化参数
- 修改
sudo_mode为MODE_EDIT引导进入漏洞函数
Fuzz测试准备
- 准备种子样本:根据'\0'拆分参数
- 并行Fuzz配置:使用tmux创建多个AFL实例
- 编译开启Asan模式检测内存错误
四、崩溃样本分析与漏洞定位
漏洞位置
plugins/sudoers/sudoers.c的set_cmnd函数,868行堆溢出
漏洞成因
- 函数申请0x54大小堆块
- 处理参数时逻辑缺陷:遇到
\后非空格字符会跳过\x00检查 - 导致可以写入超出分配大小的数据
动态调试关键点
- 使用pwngdb定位溢出位置
- 观察
NewArgv内容确定堆块大小 - 分析拷贝逻辑缺陷
五、可利用性评估
sudo历史提权漏洞
| CVE编号 | 影响版本 | 漏洞描述 | 修复建议 |
|---|---|---|---|
| CVE-2019-14287 | <1.8.28 | UID解析错误导致权限绕过 | 升级至1.8.28+ |
| CVE-2021-3156 | 1.8.2-1.8.31p2, 1.9.0-1.9.5p1 | 堆缓冲区溢出 | 升级至1.9.5p2+ |
| CVE-2023-22809 | 1.8.0-1.9.12p1 | 任意文件读写 | 升级至1.9.12p2+ |
堆操作跟踪
通过gdb脚本跟踪malloc/realloc/calloc/free调用,筛选出关键堆操作函数:
find_editor()init_defaults()setlocale()tzset()
潜在提权手法
- NSS服务用户对象劫持
- Def_timestampdir路径竞态
- Userspecs对象覆盖
六、NSS劫持提权原理
NSS服务简介
Name Service Switch统一管理多种名称解析服务,通过/etc/nsswitch.conf配置查找顺序。
关键结构体
service_user:具体服务配置项name_database_entry:数据库配置项name_database:顶层管理结构
提权原理
- 覆盖
service_user->library->lib_handle为NULL - 触发
nss_new_service初始化 - 加载恶意so文件执行提权代码
堆块申请顺序
service_table(0x20)name_database_entry(0x20)service_user(0x40)
七、setlocale堆布局原理
核心机制
_nl_find_locale函数根据LC_*环境变量:
- 申请堆块存储区域设置数据
- 发现无效环境变量时释放所有已申请堆块
控制规则
- 堆块大小:
C.UTF-8@len,len=33→0x40,len=137→0xa0 - 释放顺序:按环境变量遍历顺序
- 确保构造:至少一个无效环境变量触发释放
环境变量示例
LC_CTYPE=C.UTF-8@AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
LC_NUMERIC=C.UTF-8@AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
LC_TIME=C.UTF-8@AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
LC_COLLATE=C.UTF-8@AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
LC_IDENTIFICATION=invalid_value
八、POC构造与利用
堆布局目标
- 使用setlocale构造3个0x40和1个0xa0空闲堆块
- 让目标chunk位于溢出chunk下方
- 确保重要结构体不被破坏
利用步骤
- 构造环境变量控制堆布局
- 触发漏洞覆盖
service_user结构 - 加载恶意so实现提权
关键payload
- 命令行参数:以
\结尾的特殊构造 - 环境变量:控制堆布局的LC_*变量
- 恶意so:使用
__attribute__构造函数自动执行
动态调试要点
- 观察tcachebin中堆块状态
- 确认
service_user结构被覆盖 - 验证恶意so加载过程
总结
本漏洞利用的关键在于:
- 理解sudo参数处理逻辑缺陷
- 掌握NSS服务加载机制
- 熟练使用setlocale进行精确堆布局
- 结合堆溢出与NSS劫持实现提权
这种从Fuzz发现到完整利用的分析方法,可以应用于其他类似堆漏洞的研究与利用。