MIntegral SDK是一款流行的移动应用程序,广告SDK在AppStore中被1200多个应用程序使用,据行业专家估计,每月的下载量超过3亿次。
MIntegral SDK是封闭源代码的。下面的研究是在可以从GitHub下载的SDK版本6.3.5.0(用于x86Arch)上进行的。
我们发现集成IOS SDK版本5.5.1及更高版本包含导致信息泄漏的恶意功能。简而言之,SDK是在监视用户的链接点击,以及受影响的应用程序中的网络活动。即使开发者或广告中介平台没有启用SDK,也会发生间谍活动。
目前,恶意行为似乎仅限于iOS版的SDK。我们还没有在Android版本的SDK中发现恶意代码的证据。
MIntegral SDK在运行时使用一种称为方法切换(Method Swizzling)的技术来替换UIApplication openURL和SKStoreProductViewController loadProductWithParameters方法的实现,并且它还注册了一个自定义的NSURLProtocol类。
这些钩子用于通过发送有关HTTP请求、打开的URL和他们在应用程序内单击的App Store链接的所有信息来监视应用程序用户。
HTTP请求头和URL本身可能包含敏感数据,但与IDFA(广告商标识符)一起,这些数据允许MIntegral执行广告归属欺诈。
为了将他们的应用程序货币化,开发商通常会安装广告平台。广告平台从广告商那里获得收入,每次安装发生在用户点击他们的广告之后。开发商在他们的AP中使用多个广告平台的情况并不少见。因此,为了确定哪个广告平台应该接收针对该安装的给定属性,每次点击都被注册到属性提供商,即移动测量平台(MMP)。
下图显示了MIntegral中的恶意功能是如何工作的。在本例中,用户点击了来自“另一个平台”的广告。但是,由于MIntegral具有拦截应用程序打开的所有URL的能力,它可以向属性提供者执行额外的请求,假装点击实际上发生在他们的广告中。整个过程如下所示:
用户点击由非MIntegral广告网络提供的应用内广告中的链接,以安装来自应用商店的新应用。
通过方法切换将代码注入到iOS事件处理程序中截获点击事件后,MIntegral会将点击数据记录到他们的服务器上。
当属性提供程序尝试将安装事件与注册的单击通知进行匹配时,它会找到两个匹配的事件。使用最后接触属性模型,MIntegral点击通知被给予属性,并且来自另一个广告网络的点击通知被拒绝。
Snyk与一家主要的属性提供商合作,确认MIntegral正在使用点击数据生成错误点击通知。通过他们的调查,提供商能够证明,虚假点击通知正在生成,并导致将广告点击错误归因于MIntegral。
为了演示攻击,我们设置了一个演示应用程序,它将显示恶意的openURL钩子的运行情况。我们使用调试代理来拦截所有网络流量。
启动应用程序后,我们立即在代理中看到来自MIntegral SDK的几个请求:
来自https://setting.rayjump.com/setting的响应是一个具有许多不同选项的JSON对象。下表描述了我们研究中最有趣的领域。
单击打开example.com的按钮后,我们可以看到另外两个请求。正如我们预期的那样,第一个是对https://example.com,的GET请求。第二个是对https://n.systemlog.me/log.的POST请求。
请求的正文看起来像是Base64编码的。但实际上,它不是Base64编码的字符串。Mintergral SDK实现了自己的编解码逻辑,可以在+[MTGBase base64DecodeString:]和+[MTGBase base64CleverDecodeString:]中找到。请注意,MTGBase不会在SDK的公共标头中公开,也不会对开发人员开放。
负载中包含大量数据,包括IDFA、IDFV、OS版本、用户代理等。但是,它还包含一个名为“聪明”的字段,该字段也是经过编码的。我们可以使用base64DecodeString进行解码:
[{';cn';:';ViewController';,';u';:';https://example.com?foo=bar&;x=y';,';NID';:0,';type';:';3';,';Mn';:';openURLWithOptions:';,';trc';:';[";2|awesomegame|0x0000000104102f18-[ViewController openURLWithOptions:]+152";,";3|UIKitCore|0x00007fff49326c1d-[UIApplication sendAction:to:from:forEvent:]+83";,";4|UIKitCore|0x00007fff48cd5baa-[UIKitCore|0x00007fff48cd5baa-[UIApplication sendAction:to:from:forEvent:],";4|UIKitCore|0x00007fff48cd5baa-。
如您所见,它包含URL、堆栈跟踪和一些附加信息,如控制器和方法名。
如前所述-MIntegral SDK是封闭源代码的。我们将介绍适用于x86体系结构的版本6.3.5.0。
该二进制文件是包含多个其他二进制文件的MACHO可执行文件。我们感兴趣的代码位于_CXX_CXX_OperationPKTask.o中。
查看类,我们看到+[_CXX_CXX_OperationPKTask load],它在运行时添加类时自动执行。也就是说,如果SDK是通过CocoaPods安装的,无论开发者是否真正使用SDK,恶意逻辑都会被初始化。
Load方法执行一系列调用,这些调用将我们引向_cxxwebk_init_vw。此方法检查是否启用了反调试保护标志,并在标志设置为false或调试被禁用时初始化挂钩。
挂钩的初始化取决于上述设置请求。在下表中,我们可以看到响应JSON字段和MTGSetting类之间的关系:
以下截图中的逻辑在_cxxwebkmCouitineapo方法中实现,如果启用了相关标志,则从_cxxwebk_init_vw调用该方法。
然后他们定义一个代码块,该代码块调用_cxxwebkmCouitineapo_block_Invoke_2,然后调用原始的openURL。
OpenURL:Options:CompletionHandler:Method几乎也会发生同样的情况,只是它们会在执行此操作之前检查系统版本(该处理程序最早是在iOS10中引入的)。
在这一点上,我们已经看到了钩子是如何应用的。接下来,我们将查看挂钩本身的实现(_CxxwebkmCouitineapo_Block_Invoke_2)。
实际上,实现位于_cxxwebkmcoulsz方法中。在那里,我们可以看到另一个反调试检查调用,然后它检查__mc_notfyInHouse标志,如果该标志为1,则不执行任何操作。
这样做是为了忽略用户在MIntegral服务广告上点击的所有营销URL。在下面的截图+[MTGBase mtgOpenURL:Options:CompletionHandler:]中可以看到相关逻辑:
下一段代码显示,它们还序列化回溯数据,并将其泄漏到它们发送给https://n.systemlog.me/log.的有效负载中。
我们可以在+[_CXX_CXX_OperationPKTask_CXX_cm_LOG_WARNINGS:TO:INS:]调用中设置断点。您可以在下一个屏幕截图中看到调用参数:
另一个有趣的函数是_nsh_id_by_cc,它似乎负责识别竞争对手的SDK。相关逻辑如下图所示:
返回到+[_CXX_CXX_OperationPKTask_CXX_cm_LOG_WARNINGS:TO:INS:],在通过+[MTGBase base64EncodeString:]对有效负载进行编码后,它会创建一个新的代码块并使用_Dispatch_Async来调用它。
它导致了一系列带有附加有效负载转换的调用,并以-[_MC_ApiManager AFRequestWithUrl:paras:Success:Failure:]结束,它从MTGSetting(缺省情况下为https://n.systemlog.me/log)发出POST请求到集合DomainUrl。
SKStoreProductViewController是一个视图控制器,它提供用户可以从App Store购买媒体的页面。
我们没有深入钩子实现的技术细节,而是将下面的代码片段添加到演示应用程序中:
-(IBAction)openSKStoreProductViewController:(id)sender{SKStoreProductViewController*StoreViewController=[[SKStoreProductViewController Alalloc]init];[StoreViewController setDelegate:Self];NSDictionary*ProductParams=@{SKStoreProductParameterITunesItemIdentifier:[NSN number WithInt:1234567890]};[StoreViewController loadProductWithParameters:ProductParams Complete Block:NIL];}
结果,我们看到一个对https://n.systemlog.me/log的POST请求,下一个有效负载在“聪明”字段中:
[{';CN';:';UIApplication';,';Mn';:';sendAction:to:from:forEvent:';,';NID';:0,';aid';:';{";id";:1234567890}';,';type';:';2';,:';[";2|UIKitCore|0x00007fff49326c1d-[UIApplication sendAction:to:forEvent:]+83";,";3|UIKitCore|0x00007fff48cd5baa-[UIControl sendAction:to:forEvent:]+223";,";4|UIKitCore|0x00007ff:24}]。
NSURLProtocol类允许开发人员重新定义Apple的URL加载系统的操作方式。MIntegral SDK注册了NSURLProtocol的恶意实现,该协议可以远程配置为拦截应用程序发出的任何传出请求,并跟踪URL和HTTP标头(包括Authorization标头)。
对于应用程序开发人员来说,这意味着API令牌、cookie和基本身份验证头可能会由MIntegral收集。
要了解SDK是如何激活该部分恶意代码的,我们必须回顾_cxxwebk_init_vw。
上面的屏幕截图显示应该启用cud标志,并且cudl数组不应该为空才能激活钩子。
在我们的研究中,我们添加了以下代码片段来验证恶意代码收集了哪些数据:
-(IBAction)httpRequestWithURLSession:(id)sender{NSURLSessionConfiguration*sConf=[NSURLSessionConfiguration defaultSessionConfiguration];sConf.HTTPAdditionalHeaders=@{@";授权";:@";Basic YWRtaW46YWRtaW4K";};NSURLSession*Session=[NSURLSession Session WithConfiguration:sSURLSession*Session=[NSURLSession Session WithConfiguration:sSURLSession*Session=[NSURLSession Session WithConfiguration:s。Post";;NSURLSessionDataTask*task=[session dataTaskWithRequest:req];[任务恢复];}
结果,我们看到一个发送到https://n.systemlog.me/log的POST请求,在“聪明”字段中包含以下有效负载:
[{';CN';:';';,';u';:';https://example.com/get-secret-data';,';Mn';:';';NID';:0,';hhf';:';{";授权";:";Basic YWRtaW46YWRtaW4K";,";内容长度";:";7";}';,';类型';:';1';,';hm';:';POST';}]。
在请求中,我们可以看到URL和授权头。虽然不包括请求正文,但标头通常包含敏感数据。这些数据甚至可能包括个人身份信息。例如,如果API使用JWT令牌,则电子邮件或用户名可以存储在令牌内。
在研究期间,我们观察到MIntegral开发人员用来隐藏他们SDK的恶意行为的许多有趣的技术。正如我们所看到的,它们只在特定区域的特定应用程序上激活钩子,这使得恶意代码在那里停留了一年多而没有受到任何关注。
说到时间线,恶意SDK的第一个版本(5.5.1)是在2019年7月17日发布的。我们发现所有后续版本都包含相同的恶意功能。
许多流行的应用程序都受到此SDK恶意活动的影响。我们希望,这项研究揭示了这种情况,将推动对广告商网络进行更严格的审查和隐私控制。