如何实现sudo提权漏洞CVE-2021-3156的利用及分析,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。
0x01 漏洞背景
sudo程序存在一个高危安全漏洞,漏洞编号为CVE-2021-3156,非root用户可通过执行“sudoedit -s”和以单个'\'
结尾的命令行参数利用漏洞,获取root权限。
该漏洞NVD的打分为 CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H,最终得分为7.8分。
漏洞影响范围为:
sudo 1.8.2-1.8.31p2
sudo 1.9.0-1.9.5p1
0x02 漏洞成因及利用说明
sudo sudoers.c源文件中的set_cmnd()
函数在拷贝参数时,由于错误处理'\',造成堆写越界的问题,攻击者可通过控制参数和环境变量向特定堆地址之后的内存中写入任意长度的数据,其中包括'\0'。
该漏洞存在多种利用方式,常见利用方式包括:
1、通过堆溢出覆盖
process_hooks_getenv
中sudo_hook_entry
结构体的函数指针,进而通过execve()`函数执行代码得到root权限。2、通过堆溢出覆盖glibc
nss_load_library()
函数ni
结构体,进而通过__libc_dlopen()
加载恶意动态库,执行代码得到root权限。
由于不同版本的环境上执行时,堆内存分布不同,发生溢出的缓冲区大小、溢出长度、环境变量等参数需要模糊测试或暴力破解等方式得到,本文分析的是第二种利用方式。
0x03 漏洞调试分析
使用execve()函数执行系统中的/usr/bin/sudoedit,并将payload通过参数变量char *sudo_argv[]
和环境变量char *sudo_envp[]
进行传递。(这里使用execve()
的目的是为了便于控制执行时的env环境变量。)
execve("/usr/bin/sudoedit", sudoargv, sudoenvp);
char *sudo_argv[]
和char *sudo_envp[]
值分别如下。
sudo.c的main()
函数先调用paese_args()
解析运行状态并转义特殊字符,然后调用set_cmnd()
函数。set_cmnd()
函数存在堆溢出漏洞,可向堆中写入任意长的数据。
main()
函数首先调用parse_args.c中的parse_args()
函数。
main(int argc, char *argv[], char *envp[]) { ,,,int nargc,,好的,,status =, 0; ,,,char * * nargv,, * * env_add; ,,,sudo_mode =, parse_args(命令行参数个数,argv,,, nargc,,, nargv,,,设置,,,env_add); … }
该函数处理如下。
1,根据用户执行命令及相关参数对<代码>模式代码>及<代码>标记代码>标志位进行赋值。
2,根据<代码>模式代码>及<代码>标记代码>标志位的值,判断是否需要对<代码> & # 39;\ & # 39;代码>等特殊字符进行转义。
3,对参数数量变量<代码> int nargc> 代码以及参数指针变量<代码> char * * nargv 代码>进行赋值。
4,将<代码>模式|旗帜> 代码的计算结果作为返回值赋给主函数的<代码> sudo_mode> 代码变量。
引用>攻击者执行<强> sudoedit (- s shell)文件>强命令时,<代码> parse_args() 代码>函数会判断用户命令行输入的执行文件名<代码> char * progname> 代码是否为* *“sudoedit" <强>字符串,如果是则将<代码> int模式> 代码变量置为强> MODE_EDIT * *(该宏为<强> 0 x02 强>),然后使用<代码>开关()代码>语句判断参数是否包含* * & # 39;s # 39; <>强,如果是则将<代码> int旗帜> 代码变量置为强> MODE_SHELL * *(该宏为<强> 0 x20000 强>)。
# define default_valid_flags (MODE_BACKGROUND | MODE_PRESERVE_ENV | MODE_RESET_HOME | MODE_LOGIN_SHELL | MODE_NONINTERACTIVE | MODE_SHELL) int 命令行参数个数,parse_args (int char * * argv,, int * nargc,, char * * * nargv, ,,,struct sudo_settings * * settingsp, char * * * env_addp) { ,,,struct environment extra_env; ,,,int mode =, 0; ,,,int flags =, 0; ,,,int valid_flags =, DEFAULT_VALID_FLAGS; … ,,,if (4, proglen 的在,,,,,比较字符串(时间+ progname proglen 作用;4,“edit"),==, 0), { 时间=progname “sudoedit"; 时间=mode MODE_EDIT; sudo_settings [ARG_SUDOEDIT] .value =,“true"; ,,,} … ,,,if ((=ch getopt_long (argv,命令行参数个数,还以为,short_opts, long_opts,, NULL)), !=, 1), { ,,,switch (ch), { ,,,,case & # 39; & # 39;: ,,,sudo_settings [ARG_USER_SHELL] .value =,“true"; ,,,集(旗帜,MODE_SHELL); ,,,休息; ,,,} … }如何实现sudo提权漏洞cve - 2021 - 3156的利用及分析