【漏洞分析】sudo堆溢出漏洞分析(CVE-2021-3156)

访客3年前黑客文章474

  本文译自:

  2021年1月26日,sudo被曝存在一个“新”漏洞,但是实际上这个漏洞可能已经存在10年了。该漏洞可以使攻击者通过堆缓冲区溢出来进行权限提升。但是漏洞发布并没有exploit/POC,笔者所以决定自己构建一个。

  脆弱性

  简要介绍该漏洞,本质上攻击者可以通过在给sudo的任何argv或env参数的末尾插入一个反斜杠来让堆溢出,从而导致参数超出范围,来看一下简化版本的代码片段。

  

  之一个for循环中,正在遍历每个参数,并使用strlen判断其大小(加上空终止符),现在我们假设有空字符串“AAAA\”(\是一个字符),大小为5,并且加上这是唯一的参数,仅分配5个字节。

  在下一部分中,我们将有一个用于参数的外部for循环和一个将所有参数的内容复制到单个缓冲区user_args中的内部循环,本质上是将所有参数串联在一起。

  考虑与前面相同的字符串“AAAA\”,当[0]=='\'成立时,进入if并从from++递增,因为它指向空终止符,所以导致递增。之后,我们使用下一条语句*to++=*from++;继续循环。复制空终止符,复制字节,最终产出界限。

  之所以会发生这种情况,是因为它希望每个\后面都有一个元字符,作者提出了一种巧妙的绕过 *** ,使它容易溢出。如果您想知道为什么以及进入该块时我们最终在参数中只有\的原因,请阅读本文。

  通过使用符号链接sudoedit到sudo,我们可以做到这一点:

  

  溢出的属性

  作者陈述了有关此溢出的3个重要属性,这些属性使其非常强大。

  首先,最简单的就是控制user_args的分配大小,因此选择sudo参数的数量和时间属性。

  其次,控制溢出区域的内容。可以通过使用提供的环境变量来实现。环境变量实际上存储在最后一个参数传递给sudoedit之后,这意味着如果我们执行env -i'A=BBBB'sudoedit -s'CCCCCCCCCCCCCCCC',我们会将C插入到user_args缓冲区中,而A=BBBB将紧随其后插入到边界区域。请注意,块大小应与0x10大小保持一致,例如env -i'A=BB'sudoedit-s'CCCCBBBBBBBB'仅填充缓冲区。

  如果密切关注串联块中的内部循环,您可能会注意到可以多次利用它。通过用\结束环境变量,可以再次跳到下一个环境变量。那为什么要那样?因为随着from++的增加,在以下to++=*from++上指向空终止符的指针,它将插入该空终止符。这能够在不结束溢出的情况下插入0x0,从而使该溢出功能极为强大。

  作者的例子:

  env -i'AA=a ''B=b ''C=c ''D=d ''E=e ''F=f'sudoedit-s'1234567890123456789012 '

  这样最终会在缓冲区中结束:

  

  因此,我们将不讨论堆块的正向(fd)或反向(bk)指针的含义,因为我们仅在使用内存中进行利用。

  之一个大小是后续块的大小。它等于给malloc的0x10+参数,因为还需要本身和对齐/以前大小的空间。

  下一个大小是连续的块大小。

  fd和bk分别指向此释放块链接列表中的下一个和上一个块的指针。这仅适用于释放的块。否则,malloc的调用者可以使用这个空间。

  关于空终止符插入,这里需要注意的一点是,我认为原稿中缺少的是,我们也可以插入多个连续的空字节。

  首先要了解的是,环境变量不必以SOMETHING=SOMETHING_more的形式出现。与其他所有内容一样,这些只是字符数组,我们可以在C语言中使用它们。例如:

  

  在这里,我们使用execve在完全控制环境变量的情况下执行过程。在内部for循环中,我们在””\””处插入if语句,并通过from++反斜杠跳过一个字符,然后仅将null插入到下一个“\”,然后在a中插入两个null字节。

  开发

  尽管作者在本文中提到了3个可能的目标,但我们仅涵盖第二个目标。

  原因:

  与之一种选择相反,它们没有暴力破解,在之一种选择中,它们部分溢出了以暴力破解击败ASLR的函数指针。

  他们说,他们成功地在3个操作系统上成功做到了这一点,而其他两个操作系统都只有一个。

  在第二个选项中,我们尝试溢出到存储在堆中的service_user结构中。

  

  nss_load_library在溢出加载新的动态链接库后,libc中经常使用此结构,我们可以使文件名溢出,然后控制要加载的库。然后,我们可以针对我们可以 *** 的将以root特权运行的非特权库为目标。

  该函数如下所示:

  

  此功能的目标是点击ni->library->lib_handle=__libc_dlopen(shlib_name)加载一个我们控制的新库。

  这里有两件事要注意,之一件事是本文提到的。如果ni->library不为NULL,我们将在ni->library->lib_handle中使用该指针,并且由于ASLR是一个X子,因此我们无法预测没有泄漏的有效指针。幸运的是,此结构存在一个初始情况,如果该结构为null,则可以通过ni->library=nss_new_service来设置它,现在,多个空字节写入就派上用场了!

  然后,我们只需要将此结构完全溢出到其名称字段,即可将其更改为我们控制的非特权库。

  第二个挑战是我们拥有下一个指针struct service_user * next;。在结构内部形成一个链表,当加载发生时将遍历该链表。因此,如果我们在过程中意外溢出另一个service_user结构,则当我们因fx A溢出而导致错误时,就将编写垃圾指针。可以通过在该位置插入空字节来避免这种情况,但这会带来另一个问题,现在断开链表,并且可以从列表中完全删除目标结构,而在整个内存空间中都没有指向它的指针。

  这意味着我们必须定位到分配区域之后的链表中的之一个结构。事实证明,这是要克服的更大挑战,因为您可以想象这需要对堆分配进行很好的控制。

  在本文中,它们service_user以systemd我们绝对无法定位的名称为目标。因此,我们在分配之前设置了一个断点来检查链表。然后,我们搜索systemd并向后遍历该列表,直到找到靠近我们的分配的之一个service_user为止。(结合A的一些反复试验,以了解其崩溃的结构))

  在这里,我service_user在内存中显示了不同的名称,并在vmmaps下面显示了相同的名称。如图所示,第二个vmmap对应于systemd,其偏移量为距堆基0x47e0。这显然是一个问题,因为我们service_user在列表0x4790之前的列表中看到了另一个,而两个结构之间只有0x50的空间,所以两个结构之间只有0的空间。这使得不可能针对这一目标,但是我们可以只选择之前的目标。但是,为什么不针对其他一些fx某些0x2000结构呢?好吧……您根本无法进行那么早的分配。

  

  堆修饰

  那么,如何在接近目标的内存区域分配内存呢?因此,这篇文章中的任务似乎并不明确,听起来好像他们“蛮力”尝试了很多,直到解决方案崩溃。如果不正确,请随时与我们的团队联系。

  无论如何,我们都不希望尝试各种不同的分配方式。但是,他们确实提到了在我们控制大小的sudo进程中尽早进行分配的巧妙 *** 。

  此技巧利用了以下事实:setlocale被称为之一件事,并且它们声明:在154行的setlocale()中,我们malloc()ate和free()几个LC环境变量(LC_CTYPE,LC_MESSAGES,LC_TIME等),从而在sudo堆的开始处创建了小洞(空闲的fast或tcache块)

  这是一个巧妙的技巧,我们通过打破setlocale和以下所有免费代码来研究此大小,以检查将要释放的大小块。

  之一个有趣的测试:

  

  第二个有趣的测试:

  

  现在,实际上第二个被分配并在setlocale内不久之后再次释放。这使我相信它比之一个更加不可靠(可能是因为它同样稳定)。

  但是有趣的是,我们没有发现本文所期望的其他LC变量中的其他自由变量,这很可能是libc依赖的,或者我完全不在本地使用。

  这意味着我们只有这个分配可以使用。令人遗憾的是,现在可以使用的malloc更少了,但同时也限制了搜索空间。

  现在,您还记得我说过的关于前向和后向指针的事情,我们应该不在乎。是的..现在我们需要这些知识。因此,这里介绍了世界上最快的垃圾箱介绍。

  实际上,释放的块并不存储在单个链表中,而是分成多个链表,这些链表按边上的块大小排序。更糟糕的是,我们提供了5种不同的列表:

  tcache适用于大小从0x20到0x408的超快速分配

  fast bins也是从0x20到0x80的超快速分配

   *** all bins比tcache和fastbins大的小分配

  large bins大的可变大小的块

  unsorted bin一个包含尚未分类到其他箱中的块的箱

  我们将仅关注tcache和fast bins,因为其他箱中的数据块可能会合并,这意味着连续的数据块可以合并为一个更大的数据块,这使得以后很难预测垃圾箱的状态。在这两类箱中,块大小每0x10增量存在一个箱。(bin==链表)

  现在,我们要使用LC_MESSAGE分配一个块,并在setlocale中再次释放它,以使该块可在以后执行溢出时使用。这样,我们就可以在堆上获得更大的块。

  我不希望在我的分配之前释放的容器中的块,而当我们进行最终的溢出分配时,容器中的块仍然存在,因为它们可能来自sudo中的其他位置。

  因此,在setlocale的末尾和最后的分配之前中断,让我对sudo期间使用了哪些bin有了一个了解。请注意,这并不能说明所有分配情况,实际上与分配情况相去甚远,因此仍会涉及一些反复试验。

  我试图说明搜索空间,我们将首先尝试:

  

  现在,这是一个粗略的计划,我没有完全坚持下去。

  经过令人惊讶的几次尝试之后,我们就在溢出分配之前将这一块可用了:

  

  上面的是我们的分配,下面是目标字符串mymachine。仅相隔0x4790-0x4370==0x420字节。不错,这似乎可行。

  现在,我们只需要使用null进行溢出,直到命中该结构并重新组合具有ni-library null和另一个名称的相同结构即可。

  

  我们首先通过如下设置args来进行分配,以匹配之前找到的大小。以前面所述的分配取决于提供给sudoedit的之一个参数的长度。我们将尝试将此大小与LC_MESSAGE释放的块进行匹配。[核对原件]

  char *args[] = {

  "/usr/bin/sudoedit",

  "-s",

  "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBAAAAAAAAAAAAAAAA\",

  NULL

  }; //B and A's to match the chunk size we want freed in thebeginning

  然后,我们创建一长串环境变量以放入null并以伪造的service_user结构结尾:

  char *extra_args[] = {

  "\\",

  "\\",

  "\\",

  "\\",

  "\\",

  "\\",

  "\\",

  "\\",

  "\\",

  "\\",

  "\\",

  "\\",

  "\\",

  "\\",

  "\\",

  "\\",

  "\\",

  "\\",

  "\\",

  "\\",

  "\\",

  "\x01\\",

  "\\",

  "\\",

  "\x01\\",

  "\\",

  "\\",

  "\\",

  "\\",

  "\\",

  "\\",

  "\\",

  "\\",

  "\\",

  "\\",

  "\\",

  "\\",

  "\\",

  "\\",

  "\\",

  "\\",

  "\\",

  "\\",

  "\\",

  "\\",

  "\\",

  "\\",

  "X/X\\",

  "a",

  "LC_MESSAGES=C.UTF-8@AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",

  NULL,

  };

  然后,nss_load_library中的_st***y序列将基于上面的X/X\arg创建路径libnss_X/X.so.2:

  

  现在我们只需要创建一个简单的库即可加载。我们只是创建一个带有初始化函数设置ID(不确定是否需要)的小型库,并执行/bin/sh并在nss_load_library中的ld_open时生成根shell。使用gcc-Os-Wall-Wextra-fPIC-sharednss.c-oX.so.2进行编译。

  

  看到这个我真高兴!!

  

  shell终于弹出了

  

  结论

  最终的利用是100%可靠的,并且可以在我的环境中使用libc2.32启用ASLR,这在ubuntu 20.10中也可以找到,并且可能很容易在许多发行版中进行了重新设计。由于许多系统仍然容易受到攻击,我们目前尚未发布最终的利用代码。感谢所有参与发现此漏洞并加以利用的研究人员。

  参考链接

  

  

  

相关文章

顶级黑客联系方式(有谁知道黑客联系方式)

顶级黑客联系方式(有谁知道黑客联系方式)

本文导读目录: 1、有谁知道他是谁???急。 2、世界上顶级黑客有哪些哦? 3、谁知道中国顶尖黑客的排名? 4、世界顶级黑客有哪些? 5、世界第一黑客 6、中国有顶级黑客么? 有...

寻504个车次航班同行乘客怎么回事?504个车次航班完整名单一览

寻504个车次航班同行乘客怎么回事?504个车次航班完整名单一览

紧急扩散!急寻504个车次航班同行乘客。提醒:同乘人员返家后暂不要外出,居家封闭隔离观察。发现异常者请立即就近到指定发热门诊就诊!...

迈入认知商业时代!看IBM如何为汽车信息化精准定位

每日要闻2017年中国汽车CIO峰会在对百余位汽车企业CIO展开书面问卷调查后,分析出近两年为数众多的汽车厂商在进行企业数字化转型过程中,都在部署物联网、云计算、大数据分析、移动办公等解决方案,同时指...

TFBOYS七周年线上演唱会门票在哪买 TFBOYS七周年线上演唱会门票多少钱

2020年三小只的七周年巡回演唱将采用网上的方式,但是也還是要买票才可以收看的哦,网上巡回演唱的益处便是大家都能购到门票费啦。那麼TFBOYS七周年网上演唱会票在哪买、TFBOYS七周年网上演唱会票要...

世卫组织专家表示 全哆啦a梦h球70%人口接种疫苗才能保证

  本报讯 世界卫生组织首席科学家苏米娅·斯瓦米纳坦11月11日指出,如果目前正处于研发最后阶段的新冠病毒疫苗最终成功,全世界约70%人口接种疫苗才能确保大流行的结束。   斯瓦米纳坦和世卫组织免疫...

qq技术交流,找黑客盗微信号骗局,找黑客找回密码

拜访一下看看有没有解析。 在道有道的官网上,介绍了其广告SDK的展现办法包含插屏广告、Banner广告和运用引荐广告。 -l list available modules意图地IP地址和域名在传输的...