首页
社区
课程
招聘
[原创]cve-2021-3156-sudo堆溢出简单分析
发表于: 2021-1-27 19:13 15055

[原创]cve-2021-3156-sudo堆溢出简单分析

2021-1-27 19:13
15055

本文作者博客

首先从github下载代码

编译

调试(请以root方式执行gdb

gdb加载执行后进程会crash,这时候就可以对有漏洞的源码位置下断点,因为漏洞代码貌似是动态加载的,直接下断点下不到,crash之后就可以下了

断点命令

调试用poc

漏洞位于 set_cmnd 函数中,关键代码如下

进入该函数时NewArgv的结构如下

首先会计算 NewArgv 1-2 两个参数的长度 2 + 13 = 15 .

因此user_args分配的内存大小为 15 字节

然后会把 NewArgv 1-2 的数据拷贝到user_args里面。

拷贝过程中如果 from[0]\,且 from[1] 不是空格就会from++

所以在处理NewArgv[1]时,from[0] 就是 \from[1]\x00 ,会通过这个判断让 from++ ,然后后面会再次from++.

之后from就指向了NewArgv[1]字符串\x00后面一个字符的位置,我们看看调试时NewArgv[1]后面是什么

可以看到NewArgv[1] (0x5c 0x00)后面紧跟着的是NewArgv[2]( 0x31 0x31 ...),所以此时 from 执行的就是 NewArgv[2] 的开头

从而会再次进入while循环把NewArgv[2]拷贝到user_args

然后处理NewArgv[2]再次把NewArgv[2]拷贝到user_args

因此最终结果就是 NewArgv[2] 被拷贝了两次,实际的写入数据长度为26字节

这个漏洞是一个堆溢出,不过写的数据需要是非\x00,如果user_args分配的内存比较小(比如15字节)的话,其后面是unsorted bin,如果分配的比较大的话(使用原始的poc)其后面跟的是top chunk,感觉都不是很好利用。

感觉需要花一些时间捋一捋代码的逻辑,看看有没有什么其他的想法。

此外到达漏洞代码的poc构造过程也很精彩,这部分可以去 发布漏洞的博客 查看

写了些gdb插件的代码,可以用来查看堆布局里面的已释放块和未释放块的信息

图片描述

图中带 FREE_CHUNK 是处于释放状态的块
其他的是还没有释放的,展开chunk里面是这个块分配时的调用栈

对于没有释放块的调用栈可以通过让 gef 加载 heaptrace.py 的日志来实现

使用这个插件便于我们查看发送堆溢出时前后的堆块布局信息,以便找到合适溢出的堆对象。

https://www.cnblogs.com/hac425/p/14336484.html
https://www.cnblogs.com/hac425/p/14336484.html
https://github.com/sudo-project/sudo/archive/SUDO_1_9_5p1.tar.gz
https://github.com/sudo-project/sudo/archive/SUDO_1_9_5p1.tar.gz
tar xf sudo-SUDO_1_9_5p1.tar.gz
cd sudo-SUDO_1_9_5p1/
mkdir build
cd build/
../configure --enable-env-debug
make -j
sudo make install
tar xf sudo-SUDO_1_9_5p1.tar.gz
cd sudo-SUDO_1_9_5p1/
mkdir build
cd build/
../configure --enable-env-debug
make -j
sudo make install
gdb --args sudoedit -s '\' `perl -e 'print "A" x 65536'`
gdb --args sudoedit -s '\' `perl -e 'print "A" x 65536'`
 
b ../../../plugins/sudoers/sudoers.c:964
b ../../../plugins/sudoers/sudoers.c:978
b ../../../plugins/sudoers/sudoers.c:964
b ../../../plugins/sudoers/sudoers.c:978
sudoedit -s '\' 112233445566
sudoedit -s '\' 112233445566
/* Alloc and build up user_args. */
for (size = 0, av = NewArgv + 1; *av; av++)
size += strlen(*av) + 1;
if (size == 0 || (user_args = malloc(size)) == NULL) {
 
if (ISSET(sudo_mode, MODE_SHELL|MODE_LOGIN_SHELL)) {
 
for (to = user_args, av = NewArgv + 1; (from = *av); av++) {
    while (*from) {
    if (from[0] == '\\' && !isspace((unsigned char)from[1]))  // 关键逻辑!!!
        from++;
    *to++ = *from++;
    }
    *to++ = ' ';
}
*--to = '\0';
}
/* Alloc and build up user_args. */
for (size = 0, av = NewArgv + 1; *av; av++)
size += strlen(*av) + 1;
if (size == 0 || (user_args = malloc(size)) == NULL) {

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

最后于 2021-1-31 17:27 被暗香沉浮编辑 ,原因:
收藏
免费 3
支持
分享
最新回复 (16)
雪    币: 261
活跃值: (83)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
2
相当棒,有能力的话,能不能写一个可用的exp,我有一个本地的服务器,恰好存在这个漏洞,我想好好研究一下。你的这篇文章对有语言障碍的我很有帮助,谢谢。
还请分享或制作一个exploit。
2021-1-27 19:17
0
雪    币: 261
活跃值: (83)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
3
https://blog.csdn.net/m0_46163918/article/details/113251618
在这个位置看到了一个gif,这个exploit.c是相当的渴望啊。当然,我会仔细品读您的分析。
2021-1-27 19:18
0
雪    币: 261
活跃值: (83)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
4
对于这句"Sudo 1.8.2到1.8.31p2和1.9.0到1.9.5p1均会受到影响",我这儿的情况是:
我ubuntu 20.04 64bit 中sudo的版本是1.8.31  ,这是我刚刚查询的,这个版本不存在影响。
但是在ubuntu 18.04.5 LTS 64bit上,就存在了,其sudo的版本是1.8.21p2
2021-1-27 21:30
0
雪    币: 261
活跃值: (83)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
5

"b ../../../plugins/sudoers/sudoers.c:964
b ../../../plugins/sudoers/sudoers.c:978"

-----------------------------------------------------------------------

请教一下大牛,这两句是怎么下得断点?

当“gdb --args sudoedit -s '\' `perl -e 'print "A" x 65536'`”后回车,那么接下来怎么做呢?即b 命令后面该怎么写?

最后于 2021-1-27 21:48 被hacker一疒亻编辑 ,原因:
2021-1-27 21:46
0
雪    币: 379
活跃值: (1986)
能力值: ( LV8,RANK:140 )
在线值:
发帖
回帖
粉丝
6
hacker一疒亻 "b ../../../plugins/sudoers/sudoers.c:964b ../../../plugins/sudoers/sudoe ...
你先 gdb --args xxx 回车后,然后输入run 命令
2021-1-27 21:55
0
雪    币: 379
活跃值: (1986)
能力值: ( LV8,RANK:140 )
在线值:
发帖
回帖
粉丝
7
hacker一疒亻 "b ../../../plugins/sudoers/sudoers.c:964b ../../../plugins/sudoers/sudoe ...
进程会崩溃,然后这个时候gdb才可以下断点,这里是源码断点,所以你要先按前面说源码编译安装sudo
2021-1-27 21:56
0
雪    币: 3641
活跃值: (2458)
能力值: ( LV8,RANK:125 )
在线值:
发帖
回帖
粉丝
8
https://packetstormsecurity.com/files/161160/Sudo-Heap-Based-Buffer-Overflow.html
给了三种方式
2021-1-28 11:15
0
雪    币: 5317
活跃值: (3348)
能力值: ( LV9,RANK:250 )
在线值:
发帖
回帖
粉丝
9
围观,不知楼主用工具什么来分析代码
2021-1-28 15:15
0
雪    币: 5317
活跃值: (3348)
能力值: ( LV9,RANK:250 )
在线值:
发帖
回帖
粉丝
10

原文https://blog.qualys.com/vulnerabilities-research/2021/01/26/cve-2021-3156-heap-based-buffer-overflow-in-sudo-baron-samedit
给出的 env -i 'AA=a\' 'B=b\' 'C=c\' 'D=d\' 'E=e\' 'F=f' sudoedit -s '1234567890123456789012\' 能覆盖fd和BK是什么原理 

最后于 2021-1-28 17:00 被苏啊树编辑 ,原因:
2021-1-28 15:16
0
雪    币: 15565
活跃值: (16922)
能力值: (RANK:730 )
在线值:
发帖
回帖
粉丝
11
苏啊树 围观,不知楼主用工具什么来分析代码
gdb直接调试+源码阅读,就可以了
2021-1-28 15:29
0
雪    币: 379
活跃值: (1986)
能力值: ( LV8,RANK:140 )
在线值:
发帖
回帖
粉丝
12
vscode
2021-1-28 15:40
0
雪    币: 379
活跃值: (1986)
能力值: ( LV8,RANK:140 )
在线值:
发帖
回帖
粉丝
13
阳春 https://packetstormsecurity.com/files/161160/Sudo-Heap-Based-Buffer-Overflow.html 给了三种方式
他们这思路骚呀,通过fuzz来探测可能用于利用的堆布局
2021-1-28 15:55
0
雪    币: 261
活跃值: (83)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
14
@阳春  这篇文章强烈需要翻译    这里的exp怎么要是能直接写成一个C文件就好了,直接阅读代码比较容易
2021-1-28 16:05
0
雪    币: 261
活跃值: (83)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
15
暗香沉浮 他们这思路骚呀,通过fuzz来探测可能用于利用的堆布局
大牛   不是很懂   可否“续帖”或“开新帖”,把这个exp说清楚?    真得很想认真学一学  
2021-1-28 16:27
0
雪    币: 261
活跃值: (83)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
16
暗香沉浮 进程会崩溃,然后这个时候gdb才可以下断点,这里是源码断点,所以你要先按前面说源码编译安装sudo

@暗香沉浮
1、我现在的sudo版本是1.8.21,如果我源码编译安装1.9.5p1,那我系统的sudo就变成了1.9.5p1版本了吧?

2、我就用现在系统默认的1.8.21来进行调试也可以吧?那我怎么调试呢?  即 gdb --args........,然后run,然后b,这个break断点怎么下?

3、你说得那个fuzz法来探测可用的堆.....这个文章能用程序员的思维翻译分享一下么?


最后于 2021-1-29 19:43 被hacker一疒亻编辑 ,原因:
2021-1-29 19:39
0
雪    币: 180
活跃值: (407)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
tql
2021-2-8 14:48
1
游客
登录 | 注册 方可回帖
返回
//