Linux sudo漏洞(CVE-2017-1000367)复现和利用思路分析
漏洞背景
在今年5.30日linux sudo被爆出存在安全漏洞,sudo版本是1.8.20以及之前的版本都有可能会受到漏洞的影响,在开启selinux的情况和普通用户在sudoer者中,可以使普通用户造成覆盖任意文件,造成权限的提升。
漏洞分析
出现漏洞主要在sudo中的/src/ttyname.c中的
char *get_proccess_ttyname()函数中,这个函数功能获取终端名称,会有多种方式获取终端名称,而此次漏洞是出现在根据读取/proc/pid/stat的方式先获取设备号,然后根据设备号获取设备名的函数中,如图所示:
从网上下了一个漏洞版本的1.8.18版本sudo源码,分析char *get_proccess_ttyname()函数的整体的执行流程。
然后看一下读取/proc/pid/stat处的代码:
可以看出是按照空格来区分来读取信息,也就是读取第7个空格之前的信息,也就是第7段的信息,百度了以下发现第7段的信息如果是非0的话就是代表设备号。
[root@localhost ~]# cat /proc/6873/stat
6873 (a.out) R 6723 6873 6723 34819 6873 8388608 77 0 0 0 41958 31 0 0 25 0 3 0 5882654 1409024 56
这里面的第7项也就是34819就是当前终端的设备号,第2项a.out就是进程名字。
这里在回顾一下源代码中获取设备号的逻辑是判断有7个空格取空格前一项也就是第7项数据,第二项是进程的名字,漏洞就出现在这里,进程名字是我们可以可控的,那么如果进程名字里面出现空格的话,还能获取到正确的设备名么,当然就是不能,那么进程名是可变的,我们就可以通过构造带有空格的进程名字来伪装设备号,例如进程名字。 “34873“那么我们获取到的设备号就是34873。
那么根据上面的代码的分析流程可以看出,34873的设备号就是不存在的,那么如果我们创建一个软连接为
“34873 ”链接到/usr/bin/sudo下,当我执行这个软连接时,就会调用到sudo本身的get_proccess_ttyname
函数中,因为这个时候在/proc/pid/stat 的进程名字是“34873 ”所以获取到的设备号就是34873这个我们自己伪造的设备号,但是这时大家都在想了,我们伪造了一个假的设备号有什么用么?因为get_proccess_ttyname的获取是如果找不到这个设备号对应的设备名称那么就是返回空,那么如果后续的官方的伪装成任意文件的设备终端就不了了之了,那么我们应该根据这个可以伪装任意设备号的漏洞来一步一步的把当前的设备名字伪装成任意文件呢?
这里我们在看以下查找设备名字的流程,根据设备号先在几个指定的目录下去遍历例如 /dev/pts /dev/pt等目录进行遍历用stat函数获取设备号,看是否相同,下图所示
因为这个设备号对应的设备名字是不存在的所以在这几个指定的目录下是找不到的,那么如果找不到的话,函数就是会从/dev下遍历所有目录,除了几个设置忽略的目录:
忽略的目录
就是除了这几个目录,最后一次会遍历所有的文件去查找设备名,这个时候漏洞的另外一个关键的点出来了,可以看/dev目录下有两个特殊目录,一个是/dev/shm,一个是/dev/mqueue,因为有的系统没有/dev/mqueue,所以我就看一下/dev/shm的这个文件夹:
可以看出这个文件夹普通用户是有写权限的,就是说明普通用户可以随便改里面的内容,那么我们是不是就可以当遍历到/dev/shnm/目录下的时候,我们创建一个软连接例如/dev/shnm/_tty的一个软连接,使这个软连接指向一个设备号为我们伪造的34873的设备号,那么我们是不是就是可以获取到设备名称了,它就是软连接的名称/dev/shnm/_tty,因为这个软连接我们是可以控制的,我们可以把这个软连接在get_proccess_ttyname函数返回后,我们可以把这个软连接重新链接到任意的文件,例如一些私密的文件/etc/passwd等。
这个时候我们已经获取了一个假的软连接,这个软连接可以指向任何文件位置,那么我们如何使造成往文件中写内容呢,这里看以下官网的漏洞分析:
大概意思就是,在一个selinux开启的系统上,sudo进程会通过这个relabel_tty()这个函数以O_RDWR读写方式打开复制一份的sudo终端设备文件,并把输入流,输出流,错误流写入到设备终端文件中去。
漏洞背景
在今年5.30日linux sudo被爆出存在安全漏洞,sudo版本是1.8.20以及之前的版本都有可能会受到漏洞的影响,在开启selinux的情况和普通用户在sudoer者中,可以使普通用户造成覆盖任意文件,造成权限的提升。
漏洞分析
出现漏洞主要在sudo中的/src/ttyname.c中的
char *get_proccess_ttyname()函数中,这个函数功能获取终端名称,会有多种方式获取终端名称,而此次漏洞是出现在根据读取/proc/pid/stat的方式先获取设备号,然后根据设备号获取设备名的函数中,如图所示:
从网上下了一个漏洞版本的1.8.18版本sudo源码,分析char *get_proccess_ttyname()函数的整体的执行流程。
然后看一下读取/proc/pid/stat处的代码:
无奈人生安全网
可以看出是按照空格来区分来读取信息,也就是读取第7个空格之前的信息,也就是第7段的信息,百度了以下发现第7段的信息如果是非0的话就是代表设备号。
[root@localhost ~]# cat /proc/6873/stat
6873 (a.out) R 6723 6873 6723 34819 6873 8388608 77 0 0 0 41958 31 0 0 25 0 3 0 5882654 1409024 56
这里面的第7项也就是34819就是当前终端的设备号,第2项a.out就是进程名字。
这里在回顾一下源代码中获取设备号的逻辑是判断有7个空格取空格前一项也就是第7项数据,第二项是进程的名字,漏洞就出现在这里,进程名字是我们可以可控的,那么如果进程名字里面出现空格的话,还能获取到正确的设备名么,当然就是不能,那么进程名是可变的,我们就可以通过构造带有空格的进程名字来伪装设备号,例如进程名字。 “34873“那么我们获取到的设备号就是34873。
那么根据上面的代码的分析流程可以看出,34873的设备号就是不存在的,那么如果我们创建一个软连接为
“34873 ”链接到/usr/bin/sudo下,当我执行这个软连接时,就会调用到sudo本身的get_proccess_ttyname
函数中,因为这个时候在/proc/pid/stat 的进程名字是“34873 ”所以获取到的设备号就是34873这个我们自己伪造的设备号,但是这时大家都在想了,我们伪造了一个假的设备号有什么用么?因为get_proccess_ttyname的获取是如果找不到这个设备号对应的设备名称那么就是返回空,那么如果后续的官方的伪装成任意文件的设备终端就不了了之了,那么我们应该根据这个可以伪装任意设备号的漏洞来一步一步的把当前的设备名字伪装成任意文件呢?
这里我们在看以下查找设备名字的流程,根据设备号先在几个指定的目录下去遍历例如 /dev/pts /dev/pt等目录进行遍历用stat函数获取设备号,看是否相同,下图所示
因为这个设备号对应的设备名字是不存在的所以在这几个指定的目录下是找不到的,那么如果找不到的话,函数就是会从/dev下遍历所有目录,除了几个设置忽略的目录: www.wnhack.com
忽略的目录
就是除了这几个目录,最后一次会遍历所有的文件去查找设备名,这个时候漏洞的另外一个关键的点出来了,可以看/dev目录下有两个特殊目录,一个是/dev/shm,一个是/dev/mqueue,因为有的系统没有/dev/mqueue,所以我就看一下/dev/shm的这个文件夹:
可以看出这个文件夹普通用户是有写权限的,就是说明普通用户可以随便改里面的内容,那么我们是不是就可以当遍历到/dev/shnm/目录下的时候,我们创建一个软连接例如/dev/shnm/_tty的一个软连接,使这个软连接指向一个设备号为我们伪造的34873的设备号,那么我们是不是就是可以获取到设备名称了,它就是软连接的名称/dev/shnm/_tty,因为这个软连接我们是可以控制的,我们可以把这个软连接在get_proccess_ttyname函数返回后,我们可以把这个软连接重新链接到任意的文件,例如一些私密的文件/etc/passwd等。 无奈人生安全网
这个时候我们已经获取了一个假的软连接,这个软连接可以指向任何文件位置,那么我们如何使造成往文件中写内容呢,这里看以下官网的漏洞分析:
大概意思就是,在一个selinux开启的系统上,sudo进程会通过这个relabel_tty()这个函数以O_RDWR读写方式打开复制一份的sudo终端设备文件,并把输入流,输出流,错误流写入到设备终端文件中去。
本文来自无奈人生安全网