系统文件管理行为漏洞导致本地提权
一、前言 近期,符号链接在本地提权利用中的比重逐渐增加。无论是macOS、Windows、Linux操作系统,还是其第三方安装的应用程序,都可能使用符号链接。越是底层的函数调用,开发者越需要关注相关漏洞模式及函数参数传递的安全性。 一个漏洞的产生通常是由于在使用API函数时未充分考虑潜在的漏洞模式。如果在执行过程中存在恶意行为对这些函数进行修改,防护措施不严格会导致执行流程走向错误的分支,最终被攻击者利用。下面将以open和rename两个基础函数为例,介绍多个相关漏洞。 二、函数介绍 2.1 OPEN函数 open函数是C语言中的一个基础函数,主要用于打开文件并返回一个文件描述符。其他函数可以通过这个文件描述符对文件或目录进行读写操作。其函数原型如下: #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> int open(const char *pathname, int flags); int open(const char *pathname, int flags, mode_t mode); open函数存在三个参数: mode: 可以在调用时省略第三个参数mode,在创建新文件的时候,会通过此参数修改新文件的文件属性; pathname: 用于一个指向文件或者文件夹的路径,可以为绝对路径也可以为相对路径; flag: 作为open函数最重要的一环,参数flag能赋予的值有各种,不同的flag字段代表着不同的功能。 2.2 RENAME函数 rename函数作为C语言中的一个基础函数,主要用于处理文件或目录的移动和重命名。该函数不会修改文件或目录的属性。其函数原型如下: #include <stdio.h> int rename(const char *oldpath, const char *newpath); rename函数只有两个参数,一个是指向旧文件的字符串指针,另一个是指向想要修改后的新文件字符串指针。无论是哪一个参数,它都不会去检测访问路径是否是符号链接,即目录是通过符号链接访问的依旧会执行。反之,若是指向的最终文件/目录是符号链接,rename不会对其访问,只有在访问过程中的目录路径属于符号链接时才会进入。 三、行为检测与漏洞分析 通常,对于系统调用号的检测,在Linux上有成熟的方法。在macOS上,也有专门用于监控文件行为的系统命令fs_usage。fs_usage可以实时监听系统用户态上对文件的各种操作行为,包括文件状态获取、读写操作以及页面交换等。通过使用fs_usage,开发者和安全研究人员能够详细地跟踪和分析文件相关的系统活动,从而更好地理解和诊断文件操作中的问题。 如上图所示,可以配合grep命令获取对应进程的相关行为。通过该命令,可以简化对文件流处理的追踪,直接从所执行的系统行为或系统调用中定位到具体的代码。 对于编程语言而言,它们提供了许多封装好的API函数。在Objective-C和Swift中,也有相当多的函数底层实现可以进行分析。这些封装好的API函数不仅简化了开发过程,还为开发者提供了强大的功能。通过对这些底层实现的分析,可以更好地理解其工作原理,并在必要时进行优化或调试。 此处编写一个使用moveItemAtPath:toPath:函数的示例代码,并为rename函数设置断点。通过这种方式,可以发现最终实现也会调用rename函数。 3.1 CVE-2020-9900 文件写入自定义目录 在macOS系统中,后台存在一个以root权限启动的进程,即CrashReporter。该进程负责收集系统各种崩溃报告和日志,并将其存放于/Library/Logs/DiagnosticReports和~/Library/Logs/DiagnosticReports目录中。这两个目录的所属用户是_analyticsusers,而默认用户通常属于admin用户组,因此默认用户拥有读写上述两个目录的权限。 如上图所示,系统会根据报告生成的时间和进程名等字段,将崩溃报告存放于指定目录中。在这些目录中,存在一个名为Retired的子目录。报告的存放时间是有期限的,当报告超过这个期限时,另一个以root权限启动的进程SubmitDiagInfo会将旧报告移动到Retired目录中。由于SubmitDiagInfo同样是以root权限运行的进程,在没有沙箱等安全规则干扰的情况下,它在访问相关root权限的目录或文件时不会因为权限不足而受到限制。 fmyy@Macbook_M1 DiagnosticReports % ps -ef |grep SubmitDiagInfo 0 1043 1 0 一10上午 ?? 0:03....