*原创作者:熊猫正正
OSX是苹果公司为Mac系列产品开发的专属操作系统,是第一个基于FreeBSD系统采用面向对象操作系统。
从OSX V10.0-V10.8版本开始,OSX系统的代号都是以大型猫科动物为代号,可能老乔也是猫科动物的爱好者吧(我也是猫科动物的忠实爱好者,哈哈),OSX系统的演化如下:
2001Mac OSX 10.0 Cheeta 猎豹
2001Mac OSX 10.1 Puma 美洲狮
2002Mac OSX 10.2 Jaguar 美州豹
2002Mac OSX 10.3 Panther 黑豹
2005Mac OSX 10.4 Tiger 虎
2006Mac OSX 10.5 Leopard 豹
2009Mac OSX 10.6 Snow Leopard 雪豹
2010Mac OSX 10.7 Lion 狮
2012Mac OSX 10.8 Mountain Lion 美洲狮
2013Mac OSX 10.9 Mavericks (美国加州景点名)
2014Mac OSX 10.10 Yosemite 优胜美地(推出了全新的扁平化界面)
2015Mac OSX 10.11 EI Capitan 国家级公园里一块花岗岩名字
从上面可以看出苹果为操作系统取的名字还是挺有趣的,我从Mavericks系统开始,一直使用苹果系统,到现在也有三年多的使用经验了,个人感觉苹果系统还是蛮方便的,这次WWDC 2015苹果给带来的OSX EI Capitan系统,一出来,我就立马更新了自己的MBP
这次改变也还蛮大的,对整个系统性能都做了提升,下面我从一个安全人员的角度出发,去分析一下,OSX EI Capitan里一个非常重要的安全特性:SIP(SystemIntegrity Protection)系统完整性保护
刚升级完系统之后,我在进行一个操作的时候,遇到了一些问题,主要就是提示系统权限不足,但当我提升到sudo以后,还是提示:Operation not permitted,当时我就挺郁闷,啥情况,我sudo失败了?后面google了一下,才发现,原来OSX EI Capitan中增加了一个SIP功能,不管你是不是su,都会阻止你在系统目录下进行操作……
当时唯一的想法就是,这个东西能关不?怎么关?还是Google……找到了如下的方法:
(1)重启OSX系统,然后按住Command+R
(2)出现界面之后,选择Utilities menu中Terminal
(3)在Terminal中输入csrutil disable关闭SIP(csrutil enable打开SIP)
(4)重启reboot OSX
这个方法在我之前介绍《OSX内核调试技术分享》这篇文章中也提到过(链接),其实网上关闭SIP也都是这个,千篇一律吧(网上的文章一大抄,呵呵),如果大家对OSX安全不感兴趣,只想解结这个问题,那到这里就可以了,但作为一个安全研究员,对各种安全系统研究是我们的兴趣和职责所在,如果你对SIP感兴趣,可以继续望下看!
SIP全名System Integrity Protection(系统完整性保护),它是为了保护系统进程,文件,文档不被其它进程修改,不管是否为root user,SIP技术主要分为文件系统保护,运行时保护,内核扩展签名,文件系统保护主要是通过沙盒机制限制root权限,运行时保护,主要就是保护关键进程无法被进程代码注入,挂调试器以及内核调试等,内核扩展签名,所有的第三方kext必须被安装到/Library/Extensions,并强制使用签名。
Apple提供的官方文档中,我们可以找到OSX SIP的工作原理( 下载地址 )。文档中说明了苹果的新OSX系统,采用了如下的OSX Security Model:
这种安全模式削减了之前root权限,同时通过沙箱默认保护系统,提供不能被根自动入侵的配置机制,我们可以通过命令行工具,查看被保护的目录,如图:
从图中可以看出标志有restricted的为系统限制目录,这些目录是在系统启动的时候,通过OSX新的安全模型被定义的,之后不管用户是否使用root权限都无法对这些目录进行操作,查看目录中的文件信息,也可以看到文件同样被标记为restricted,如下图:
SIP同时也保护驱动程序,我们之前使用第三方驱动的时候,可以通过kext-dev-mode=1来加载第三方驱动程序,SIP强制要求我们把第三方驱动程序放到/Library/Extensions目录下,并且停用了kext-dev-modeboot-arg这个启动项,我们可以查看这个目录下的kext,发现没有restricted,但是系统目录下的kext是被restricted的,具体有哪些目录和文件或驱动被保护,从/System/Library/Sandbox目录中,我们可以看到rootless.conf,这是rootless的配置文件,主要用于说明哪些目录,程序,以及符号链接被保护,如下图所示:
这个文件说明了OSX系统中被SIP保护的整体配置信息,其实SIP机制就是苹果通过分层的安全机制,在底层设置一个rootless配置文件,然后在系统中,对配置文件中的信息增加一个限制标志项,这种标志信息不可复制,系统默认配置的,存在这个标志的信息,苹果统一通过底层沙箱进行保护,不用去额外权限大小,这样也削减了root在OSX中的权限大小
俗话说的好:有防必有攻,总有方法可以破解SIP,要研究破解SIP的原理,我们要从哪里入手呢?就从国外网站上提供的这个方法入手吧,如何?上面讲到要关闭OSX,必须要在Recovery OS模式下进行这个命令操作(是不是就是Windows的安全模式),为什么要这样呢?这里我们先不到Recovery OS模式下操作这个工具,如下所示:
工具的帮助里写的很清楚了,Only available inRecovery OS,如果我们直接运行,会得到如下结果:
通过上面的帮助,我们可以通过这个工具,查看当前SIP的状态,如图所示:
我们现在要分析csrutil程序,很简单,从/usr/bin中拷贝csrutil到ida中,程序比较小,从下图中我们可以看出csrutil主要是设置IODeviceTree:/options项里的内容,我们主要看两个函数,一个是Clear SIP的函数,如下:
还有一个就是设置SIP的函数,可以enable/disable SIP,主要是通过传入不同的参数进行设置,如下所示:
从上面可以看出,csrutil主要通过设置IODeviceTree:/options里的值来修改sip的设置,使用工具ioreg来查看IODeviceTree:/options里面到底有哪些值,命令行:ioreg -l -p IODeviceTree,在没有关闭SIP的情况下,得到如下所示:
其实可以看出,它和我们用nvram得到的系统启动项是一样的,大家可以自己试下,命令行:
nvram -xp,它主要是得到系统的启动项值,各个启动项值,大家可以自行查资料进行参考
我们从反编译csrutil程序中可以发现,它是通过设置csr-data或csr-active-config这两项来打开/关闭SIP的,我们关闭了SIP,然后再Recovery OS的模式下,使用工具iosreg,来得到的IODeviceTree:/options的值,如下截图:
里面的csr-active-config的值被设置为<77000000>,这样我们就关闭了SIP,但是为什么我们在IODeviceTree:/options里设置csr-active-config的值之后,我们就关闭了SIP呢?
其实我们能过IODeviceTree:/options的值可以看出这里就是操作系统的启动选项,当操作系统启动选项中存在csr-active-config的值的时候,我们就关闭了SIP,好在我们的OSX是开源的项目,我们不用通过反编译OSX Kernel来找答案,从 apple的网站 下载OSX系统源码,然后找csr相关的源代码,很快我们可以找到,如下两个代码 csr.h(xnu/bsd/sys/csr.h),csr.c(xnu/bsd/kern/kern_csr.c)
,查看kern_csr.c的源代码,我们找到如下函数:
在系统启动的时候,有一个Syscall的过程(可以参考,这里有一个csrctl函数,就是Syscall的入口函数,函数代码如下:
里面有一个syscall_csr_check函数和syscall_csr_get_active_config,其实就是检测系统启动项,当系统启动项中存在csr-active-config或csr-data时候,查看如下函数:
当mask为零的时候rootless enforcement就是被启动了,当系统启动项中存在csr-active-config时,rootless就是被关闭的,将会返回EPERM
上面为什么要把值设为<77000000>,我们可以从csr.h的头文件中找到答案,如下图所示:
当BootArgs Flag为”kBootArgsFlagCSRBoot”时,系统为RecoveryOS模式,然后通过设置Rootless Configuration flags来达到关闭SIP相关保护的目的,当值为0×77(1110111)的时候,整个rootless将关闭各种文件保护,以及运行时保护等。
这样基本上我们就把上面是如何关闭SIP的原理搞清楚了,前几天我在Github上正好也看到了一位国外牛人,写了个关于SIP exploit( 源代码链接 ),我们这里也来分析一下这个exploit的原理,先gitclone代码,然后我们查看里面的代码,代码也写的很简单,我大致分析一下,从main函数开始看起,前面通过不同的参数返回不同的status,然后再map osx kernel文件(/System/Library/Kernels/kernel),如下所示:
然后通过OSKextCopyLoadedKextInfo函数得到内核空间的地址,如图所示:
再通过ROP技术,调用kernel中的csr_set_allow_all的函数,并通过得到的不同的status值,传入不同的参数,实现打开/关闭SIP的目的,代码如下:
(对于ROP技术不熟的朋友,可以参考,阿里少年博士写的 几篇ROP文章 ,写的很好。
当我们调用disable的时候,status=1,然后通过ROP调用csr_set_allow_all函数,就可以关闭SIP,IDA反编译kernel文件,然后查找csr_set_allow_all如下:
这样就可以关闭SIP了,为什么呢?我们看到这个csr_set_allow_all函数是不是很熟悉,不错,就是我们之前在kern_csr.c中看到的函数,如下图所示:
当我们调用csr_allow_all,并通过传入参数status=1的时候,csr_allow_all的值等于1,再往上看,如下代码:
当csr_init初始化的时候,如果csr_allow_all=1,那么系统启动的时候就自动关闭了SIP了,是不是好好玩!
这样关于OSX EICapitan系统中SIP里的一些东西,我们就分析到这里了,里面其实可能还有很多可以挖掘的地方,需要我们去挖掘,说不定可以找出更多的exploits出来,关于OSX/IOS系统的安全问题,可能在未来会有越来越多的人一起研究!
心灵鸡汤就不说了,最后说一句自己一直喜欢的一句话,那就是星爷说的:做人如果没有梦想,那和一条咸鱼有什么区别?不管你是否有钱,地位是否高,梦想是每个人都应该有的,不管它大不大,我们都在坚守着自己应该坚守的东西,努力做好自己的事!
路漫漫其修远兮 吾将上下而求索,非常欢迎对这方面感兴趣的朋友跟我交流学习!
* 本文作者:熊猫正正,本文属FreeBuf原创奖励计划,未经许可禁止转载