这个漏洞是在5.30号正式公布的,国内有很多文章有关于该漏洞的预警,也就是介绍下影响范围,版本之类的信息,而且基本都是一份的各种转载。在freebuf上有一个比较详细的介绍,但是也主要是以翻译为主,并未讲的很透彻。
eb8K9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8Y4N6%4N6#2)9J5k6h3k6J5k6h3g2T1N6h3k6Q4x3X3g2U0L8$3#2Q4x3V1k6$3N6h3I4K6i4K6u0r3x3e0x3$3x3e0f1$3i4K6u0W2K9s2c8E0L8l9`.`.
因此准备对这个漏洞进行分析,并依据github上公布的PoC对该漏洞复现。
主要解决两个问题:
1. 造成该漏洞的原因是什么? 补丁如何修补
2. 利用该漏洞能够达到怎样的效果
漏洞成因与补丁修复
原因是在Linux执行sudo操作的时候,需要获取进程的tty设备号,而获取的地方是在/proc/[pid]/stat文件下。stat文件的详细描述在9c4K9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8X3u0D9L8$3N6Q4x3X3g2U0M7$3c8F1i4K6u0W2L8X3g2@1i4K6u0r3j5%4W2T1k6i4u0@1j5h3&6Q4x3V1k6S2M7Y4c8A6j5$3I4W2i4K6u0r3k6r3g2@1j5h3W2D9M7#2)9J5c8U0M7#2z5e0j5$3x3K6x3`. 这篇博客中有很详细的描述。
其中我们比较关心的是两点,一是这里面的值都是一项一项的,并且每一项都是使用空格进行分隔开。
二是第二项表示 应用程序(进程)的名字,是用小括号包含,并且允许空格的存在;第七项是tty_nr,就是前面提到需要获取的tty设备号。
漏洞成因就在获取tty设备号的时候:
48dK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6T1N6h3N6*7K9h3I4D9j5g2)9J5k6i4u0W2k6r3S2S2N6q4)9J5k6h3y4G2L8g2)9J5c8X3q4@1N6r3q4U0K9r3#2W2L8Y4c8Q4x3X3g2U0k6$3W2Q4x3@1k6A6k6q4)9K6c8o6p5J5z5o6t1I4x3o6W2Q4x3X3t1`.(补丁前后对比的代码)
使用的函数为get_process_ttyname,关键代码如下:
基本流程为从 stat文件下读取一行(tty设备号在第一行),然后按照空格取值,当遇到第七个空格的时候,那么前面那个记录的cp指针指向的就是tty设备号了,然后将其拿出来即可获取。而成功的前提在于前面只有用于分隔的空格,项中是没有空格的,而第二项的进程名中是允许包含空格的,而这一项是我们可以控制的。
所以我们可以通过给第二项添加空格,来控制第七项的值,因此我们能够随意控制tty设备号。这是第一个问题点所在。
所以对应的补丁就修补了查询方式:
主要的添加代码,在对第七项的查询时,通过进程名项使用小括号包着的特点,从')'往后开始查询。
看到前面链接中的代码,其实还补了另外一处:
这就和后面的利用有关系了,获取设备号后处理流程,当获取到一个不为0的设备号后,即认为是存在tty设备的,此时将调用sudo_ttyname_dev函数依据设备号去搜索指定的设备名。搜索顺序是首先在search_devs数组中包含的路径下搜索,若不存在,将在/dev路径下进行广度优先搜索。详细可见:558K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6p5K9i4y4@1M7X3!0@1k6h3y4Z5i4K6u0r3M7%4g2V1L8#2)9J5c8X3u0D9L8$3u0Q4x3V1k6E0j5i4y4@1k6i4u0Q4x3V1k6K6M7X3y4Q4x3V1k6@1N6s2W2F1j5h3#2W2i4K6u0W2j5H3`.`. 的sudo_ttyname_dev(dev_t rdev)函数,代码比较简单。
我在centos 7上查看了dev文件夹下的权限情况。
其中 shm和mqueue文件夹是普通用户可写,那么也就意味着当我们设置为一个不存在的tty设备号的时候,通过对/dev文件夹进行搜索时,能够触碰到我们自己创建的文件。
所以第二个修补位置就是添加了两个忽视搜索的路径,即shm和mqueue文件夹不放置在搜索路径下。
漏洞影响和复现
freebuf上给的标题为
SELinux曝新安全漏洞:用户执行sudo命令可获取root权限
其实很多时候不是很明确sudo和root之间的区别,尤其是在ubuntu上默认用户安装的时候,sudo之后的用户基本上和root是一个权限。
但是在包含SELinux的Linux系统中,sudo获取的权限和root的差异很明显,尤其是在使用centos的时候差异很明显。
详细可以参考:8a0K9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8Y4N6%4N6#2)9J5k6h3A6T1y4e0q4Q4x3X3g2F1k6i4c8Q4x3V1k6x3d9f1&6g2h3r3A6A6M7$3S2#2i4K6u0r3x3e0t1%4x3e0y4Q4x3X3g2Z5N6r3#2D9
简单描述为,普通用户使用sudo执行命令流程是当前用户切换到root,然后以root的身份执行命令,执行完成后再次回到当前用户。
权限问题:普通用户的sudo权限是root给定的,root决定普通用户能够使用sudo执行哪些操作。具体的设置在/etc/sudoers文件下,如添加一条
那么centos用户能够执行sudo,但是只能执行sum命令
废话少说了,入正题:漏洞效果怎样?
因为是通过sudo命令对get_process_ttyname函数执行的,因此利用该漏洞前提是能够拿到一个用户的sudo权限,而在使用了SELinux的系统中,会将标准输入输出(stdout, stderr, stdin)信息写入到文件之中,这个文件是当前进程所对应的虚拟终端的文件。(使用sudo -r unconfined_r能够触发)(这里因为不是很了解,描述比较模糊,详细可参考SELinux的一些处理)。
因此当我们能够控制这个文件,就能够控制对任意文件的写入,因为这个写入操作也是在root权限下,所以能够对敏感文件写入,如/etc/sudoers。
所以该漏洞的利用效果为,能够将一个拥有sudo权限的用户提升到root权限。
因为github找到了PoC,能够实现任意文件的写入,并且也测试成功,因此将依据该PoC来介绍下如何提权。
f14K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6U0x3r3b7K6P5U0y4J5x3q4)9J5c8Y4y4#2k6r3!0Q4x3X3c8o6g2V1g2Q4x3X3b7J5x3o6p5%4i4K6u0V1x3e0l9H3x3o6x3$3y4#2)9J5c8X3u0D9L8$3u0Q4x3V1k6E0j5i4y4@1k6i4u0Q4x3V1k6K6N6h3c8G2M7s2N6F1i4K6u0W2j5H3`.`.
首先是创建一下符号链接了,先看第二个,第一个的作用将在后面描述。因为将/dev/shm/_tmp/ 34873 链接到sudo了,所以执行它的时候也会调用漏洞函数get_process_ttyname,使用execlp执行,那么就能够把我们的34873写入到第七项tty设备号中了,下次获取的时候就是通过34873来调用sudo_ttyname_dev来查询了,因为这个是我们写入的一个不存在的tty设备号,那么在search_devs[]数组指定的路径中是找不到的,因此需要去/dev文件夹下搜索,此时添加一个消息反馈,当搜索到我们创建的文件夹/dev/shm/_tmp的时候给予消息,即
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课