CVE-2018-1000001 linux kernel
前置知识
一个名称空间将全局系统资源封装在一个抽象中,使其在名称空间内的进程中出现,它们有自己独立
的全局资源实例。对全局资源的更改在其他进程中是可见的,但其他进程是不可见的。名称空间的一
个用途是实现容器。
“mount point”:locations in the file hierarchy where file systems have been mounted to
"mounts":安装文件系统的集合/文件系统已安装到的文件层次结构中的位置集。
"to mount":将文件系统安装到文件层次结构中的操作。
Dos Attack
简称拒绝服务攻击, denial-of-service (DoS) attack
userns
SUID,SGID and Sticky Bit
SUID,SGID和Stiky Bits和对所有者/组/其他人的读/写/执行权限一样,都属于文件的属性
Stiky Bit:一旦有关程序被执行,它应当驻留在内存中,比如:当一个用户刚刚使用完一个
程序,另外一个用户想要启动相同程序时,不必再次重新初始化。
SUID Bit:此程序的SUID若被置为root,那么无论任何用户都能以root的权限运行该程序。
SGID Bit:和SUID类似
Introduction
漏洞成因:在应用程序编写完成后再改变文档会引入安全问题。
Linux kernel side
Linux 内核并不完全遵循POSIX规范。它更改了getcwd,但是此时glibc已经实现了
下面的文档某种程度上有矛盾
如果当前目录不在当前进程的root文件下(比如进程通过chroot设置了一个新的文件系统根目录)
从Linux2.6.36,将会返回"(unreachable)",非特权用户更改当前目录到另一个挂载命名空间
当遇到来自不可信任源的路径时,这些函数的调用者应当确保返回的路径以'/'或者'('开始。
getcwd遵循POSIX.1-2001,但POSIX.1-2001并没有明确如何处理buf为NULL的情况
文档明确指明了"unreachable"的使用,但是并不遵循POSIX规范。至少违反了POSIX 2004和2008
规范。而POSIX.1-2001并不能免费获得。根据IEEE Std 1003.1-2008对getcwd的定义:
getcwd()函数应将当前工作目录的绝对路径名放置在buf指向的数组中,并返回buf。路径名不包
含点或点,或符号链接。
似乎,由于Linux内核方面的接口规范的更改而导致的结果并没有得到所有受影响的各方的认可。
realpath()函数依赖于使用getcwd()来解析相对路径名。另外,manpage不反映底层getcwd()调用的更改。
Libc side
glibc依然假定getcwd将返回绝对路径:
realpath()拓展所有符号链接并解析,生成一个规范化的绝对路径名。
当解析一个相对路径,realpath会使用当前的工作目录。假设它以a/.开始,这个函数从getcwd文件
名称从一个斜线到前一个斜线的的../符号链接,它并不检查缓存区的边界。所以,在string缓存区
被用作创建规范化的绝对路径之前,可能会以一个斜线结尾。因此,用getcwd()返回
(ubreachable)/,来解析上面提到的链接名称,已经将指针移动到缓存区前,会更改缓存区前一个字节为'/',下一部分x将被复制到这个位置。
方法
为了实现提权,mount,unmount这类SUID程序,是最合适的目标:他们使用realpath处理函数路径
不会降权,也能被所有用户使用。选择unmount,因为它每次运行允许处理多个挂载点,从而多次遍
历问题代码,打败ASLR。