实施和测试 iOS 数据保护

Posted

技术标签:

【中文标题】实施和测试 iOS 数据保护【英文标题】:Implementing and Testing iOS data protection 【发布时间】:2011-07-06 13:28:52 【问题描述】:

刚刚看到 209 届会议 - 保护来自 2010 年 WWDC 的应用程序数据。

主题演讲解释了很多事情,包括您可以为文件设置数据保护属性的方式(NSFileProtectionComplete、NSFileProtectionNone)以及如何确定哪种保护最适合您的情况。

我刚刚实现了它,但不知道如何测试安全性是否开启,有什么想法吗?

另外,我有一个 sql lite 数据库,需要不时在后台访问,这种数据保护方法似乎不够好..任何指导我通过最佳数据库保护的链接或教程? (找到了 sql 密码,但在进化的项目中添加有点重)

谢谢!

【问题讨论】:

我一直在想同样的问题——当设备被锁定时,我无法进入文件系统查看文件是否被加密(对越狱不感兴趣)。 我知道这是旧帖子,但我遇到了同样的问题。而且@Apple 文档没有帮助,例如,我在哪里发现模拟器不支持它。我也是 Swift 的新手(目前使用 Swift 4)。但无论如何,即使使用真实设备,我如何确认加密实际上正在发生?我确实实现了 applicationProtectedDataWillBecomeUnavailable 和 applicationProtectedDataDidBecomeAvailable 但是当我锁定/解锁我的设备时没有命中断点。还缺少其他东西。 【参考方案1】:

更新:ios 6 中,可能需要通过使用需要在 iOS 配置文件中的 App ID 上配置的权利来为您的应用程序提供数据保护。我还没有测试过,这是我能找到的最好的信息https://devforums.apple.com/message/707939#707939


我对此事的调查使我相信很难确定设备上是否启用了数据保护。

通过将NSFileProtectionKey文件属性设置为NSFileProtectionComplete来启用文件保护

例如,要创建一个受保护的文件,您可以运行如下代码:

[[NSFileManager defaultManager] createFileAtPath:[self filePath]
                                        contents:[@"super secret file contents" dataUsingEncoding:NSUTF8StringEncoding]
                                      attributes:[NSDictionary dictionaryWithObject:NSFileProtectionComplete
                                                                             forKey:NSFileProtectionKey]];

不幸的是,即使设备上未启用数据保护(或者如果代码在数据保护不可用的模拟器上运行),此代码也会正常执行。

更糟糕的是,无论文件是否受保护,都会设置NSFileProtectionComplete 属性。以下:

self.fileProtectionValue = [[[NSFileManager defaultManager] attributesOfItemAtPath:[self filePath]
                                                                             error:NULL] valueForKey:NSFileProtectionKey];

NSLog(@"file protection value: %@", self.fileProtectionValue);

无论是否启用数据保护,都会输出file protection value: NSFileProtectionComplete

我可以使用两种方法来发现文件保护是否按预期工作。不幸的是,这些方法都不适用于检测是否在现场的设备上启用了数据保护。

这两种方法的工作原理是,如果设备被锁定,则无法读取受保护的文件。

方法一涉及在设备锁定后使用计时器尝试读取文件,但同时您的应用程序继续运行:

[self performSelector:@selector(doReload) withObject:nil afterDelay:20];

- (void)doReload 

    NSLog(@"protected data available: %@",[[UIApplication sharedApplication] isProtectedDataAvailable] ? @"yes" : @"no");

    NSError *error;

    self.fileContents = [NSString stringWithContentsOfFile:[self filePath]
                                              encoding:NSUTF8StringEncoding
                                                 error:&error];

    NSLog(@"file contents: %@\nerror: %@", self.fileContents, error);

如果您运行上述代码并锁定受数据保护的设备,它将吐出:

protected data available: no
file contents: (null)
error: Error Domain=NSCocoaErrorDomain Code=257 "The operation couldn’t be completed. (Cocoa error 257.)" UserInfo=0x16e110 NSFilePath=/var/mobile/Applications/D71F1F1F-6C25-4848-BB1F-51539B47EC79/Documents/protected_file, NSUnderlyingError=0x16e010 "The operation couldn’t be completed. Operation not permitted"

20 秒的延迟是必要的,因为在启用数据保护的设备被锁定后,有 10 秒左右的宽限期,受保护的数据仍然可用。

第二种方法是在应用程序中创建一个受保护的文件,退出应用程序,锁定设备,等待 10 秒,然后使用 XCode 管理器下载应用程序的内容。这将产生一条错误消息,并且受保护的文件将为空。

如果上述任一测试未能按描述运行,则数据保护未启用,或者您的文件保护代码未正确实现。

由于在将机密信息写入磁盘之前,我没有找到任何方法来验证应用程序中是否启用了数据保护,因此我向 Apple 提交了功能增强请求,以便能够将应用程序标记为需要数据保护被启用。 (rdar://10167256)

Apple 确实通过其移动设备管理 (MDM) API 提供了一个解决方案,该 API 与第三方服务器相结合,可用于强制执行要求在设备上启用数据保护的政策。

【讨论】:

我已经尝试实现 doReload 方法(有延迟),但直到设备再次解锁并且数据可用时才会调用它。如何确保它在后台被调用? 有关如何在使用启用了数据保护的权利文件时测试文件保护是否启用的更多信息?【参考方案2】:

您可以使用iExplorer 应用程序来检测您的文件是否已加密。 iExplorer 可让您浏览 iPhone/iPad 的文件系统,并打开文件(当然您的设备必须插入 Mac)。

当设备被锁定时,无法正确读取文件。

【讨论】:

我要补充一点,您需要确保您的设备未在 XCode 管理器中启用为开发人员设备。因此,您需要右键单击它并忽略它。重新启动手机可能也是个好主意,我按住电源和主页按钮直到得到苹果标志。之后,当设备被锁定并且您尝试从 iExplorer 中提取文件时,该文件的操作将静默失败(您不会收到错误消息,但不会提取任何文件) @FerasArabiat :如何确保该设备未在 Xcode 7 中作为开发人员设备启用?当我在“设备”窗口中单击鼠标右键时,我没有看到忽略选项。另外,如果设备没有在 Xcode 中配置为开发设备,不管它是否加密,它不应该不显示任何数据吗? @EmbCoder,我认为它已在 XCode 6 中删除...我对此不是 100% 肯定,因为我自己没有尝试过,但苹果文档说明如下: 1. 连接设备到您的 Mac。 2. 在 Xcode 中,选择 Window > Devices,然后选择 Devices 下的设备。 3. 在设备窗口的左下角,单击操作按钮(添加按钮右侧的齿轮图标) 4. 从弹出菜单中取消选择“在运行目标菜单中显示”。 @EmbCoder,你可以在这里找到更多细节:developer.apple.com/library/ios/documentation/IDEs/Conceptual/… 您能否在使用 iExplorer 推送到设备的调试应用程序上进行测试?我将我的权利文件设置为 FileProtectComplete,但是如果我锁定设备 iExplorer 仍然可以看到所有文件。【参考方案3】:

来自NSFileManager 类文档:

文件以加密格式存储在磁盘上,在设备锁定或启动时无法读取或写入。

设置文件属性时只需传递常量。

当使用 writeToFile:options:error: 方法将 NSData 对象的内容写入磁盘时,请包含 NSDataWritingFileProtectionComplete 选项。

使用 NSFileManager 的 setAttributes:ofItemAtPath:error: 方法将 NSFileProtectionKey 属性(带有 NSFileProtectionComplete 值)添加到现有文件中

http://developer.apple.com/iphone/library/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/StandardBehaviors/StandardBehaviors.html

编辑(确定受保护文件的可用性)

只有在设备解锁时才能访问受保护的文件。由于应用程序可能会在设备锁定时继续运行,因此您的代码应准备好处理受保护文件随时变得不可用的可能性。 UIKit 框架提供了跟踪当前是否启用数据保护的方法。

*

  Use applicationProtectedDataWillBecomeUnavailable: and applicationProtectedDataDidBecomeAvailable: methods and use them to track changes to the availability of protected data.
*

  An application can register for the UIApplicationProtectedDataWillBecomeUnavailable and UIApplicationProtectedDataDidBecomeAvailable notifications.
*

  The protectedDataAvailable property of the shared UIApplication object indicates whether protected files are currently accessible. 

任何使用受保护文件的应用程序都应实现应用程序委托方法。当调用 applicationProtectedDataWillBecomeUnavailable: 方法时,您的应用程序应立即关闭任何受保护的文件并避免再次使用它们,直到调用 applicationProtectedDataDidBecomeAvailable: 方法。在受保护文件不可用时访问受保护文件的任何尝试都将失败。

验证越狱设备上的文件保护

更进一步,如果您想测试精确文件的文件保护,那么您需要一个越狱设备。为此,以下是(非详细)步骤:

1) 越狱iOS设备

2) 通过 Cydia 安装 Open SSH(这是从该设备远程访问文件所必需的)(https://cydia.saurik.com/openssh.html)

3) 从您的计算机(使用 Mac 客户端或终端)以 root 用户身份登录到您的设备。

要查找应用目录和文件的位置,有多种方法。要么你可以

grep 应用程序的进程(例如ps ax | grep YourAppName) - 确保应用程序正在设备上运行以获取进程详细信息。它应该提供应用程序包的位置 或者,您也可以使用您感兴趣的find 搜索特定文件。例如。 find / -type f -name YouAppName.sqlite。它应该提供设备上的文件位置。

当手机被密码锁定时,您可以从这里尝试查看文件是否真的可以访问;或不。 - 您只需运行cat YouAppName.sqlite 即可查看内容是否可访问。 ia f 文件受保护,它应该显示

不允许操作

错误; else if 会显示文件的内容。

同样,如果您真的想检查单个文件的文件保护,则需要这样做。如果权利和功能设置正确,验证权利应该足以保护文件。

在侧节点上,文件浏览器工具(例如 iExplorer)在验证 FileProtection 方面没有多大帮助,因为此类工具要求设备处于“受信任”模式,因此它们有权访问您设备的内容/应用程序。

祝你好运!

【讨论】:

好的.. 但是我如何测试保护?我的意思是,我想做一些事情来告诉我该文件是受保护的 @Omer - 你能想出一种方法来测试它吗?我已经尝试了 2 天,我在这里用代码发布了我的问题:***.com/questions/39151959/… 老实说,这个问题有点老了,我记不太清了。但我最终做的是使用一些软件,如 iExplorer,并尝试从手机访问 de 文件。受保护时,会列出文件,但大小为 0 字节,您应该无法打开它们。你试过这样的事情吗? @EmbCoder 基本上是这个答案***.com/a/10385450/219777【参考方案4】:

可以在 Xcode 中进行测试:

    删除并重新安装您的应用 在您的 iOS 设备上,转到“设置”>“密码”并确保“需要密码”设置为“立即” 锁定您的手机并等待 20 秒 在 Xcode 上,转到“窗口”>“设备” 选择您要测试的应用 点击设置齿轮并选择“下载容器” 右键单击下载的 .xcappdata 文件并选择“显示包内容”。您可以在此处查看的任何内容都没有被NSFileProtectionComplete 加密 解锁手机并重复步骤 3-6。以前无法查看但现在可以查看的文件已成功加密。

【讨论】:

您的意思是文件不会显示在列表中吗?或者它们会显示在列表中,但是当尝试在任何类型的查看器中打开它们时会显示加密值? @EmbCoder 他们不会出现在列表中。大概是因为您的操作系统将无法读取它们。 您可能还需要进入您的应用程序以创建一些在全新安装时不会出现的文件。 我总是看到列出的文件。我正在尝试加密 Core Data 中的一个非常简单的实体,该实体在应用程序启动时创建并在用户登录后填充。它运行良好,但加密不起作用。我将 NSPersistentStoreFileProtectionKey 设置为 NSFileProtectionComplete 以实现此目的。我把我的代码放在这里:***.com/questions/39151959/…【参考方案5】:

文件保护可以在每个文件或每个目录的基础上启用,也可以为整个应用程序启用(使用权利和配置文件)。要确定文件或目录是否受保护,请检查数据保护密钥的文件系统属性。即使它是设置为受保护的父目录,这也应该是有效的:

- (BOOL) isProtectedItemAtURL:(NSURL *)URL 
    BOOL            result                      = YES;
    NSDictionary    *attributes                 = nil;
    NSString        *protectionAttributeValue   = nil;
    NSFileManager   *fileManager                = nil;

    fileManager = [[NSFileManager alloc] init];
    attributes = [fileManager attributesOfItemAtPath:[URL path] error:&error];
    if (attributes != nil)
        protectionAttributeValue = [attributes valueForKey:NSFileProtectionKey];
        if ((protectionAttributeValue == nil) || [protectionAttributeValue isEqualToString:NSFileProtectionNone])
            result = NO;
        
     else 
        // handle the error
    
    return result;

为了确定受保护的内容是否可用,UIApplication 提供了一种查询保护状态的方法,isProtectedDataAvailable。将它与上述方法一起使用可以让您确定特定文件或目录是否可用:

- (BOOL) isItemAtURLAvailable:(NSURL *)URL 
    BOOL            result                      = NO;

    if ([self isProtectedItemAtURL:URL])
        // Item is protected
        if ([[UIApplication sharedApplication] isProtectedDataAvailable])
            // Protected content is available
            result = YES;
        
     else 
        result = YES;
    

    return result;

【讨论】:

我试图这样做,但[attributes valueForKey:NSFileProtectionKey] 总是给我 nil,我猜这个属性无法使用 fileManager 检索。 好的,NSFileProtectionKey 只能在设备上检索。它不适用于模拟器。 @MichalCichon 不应该这样,请提交雷达【参考方案6】:

我认为您无法再使用基于计算机的工具和未越狱的 iPhone 来测试数据保护 - 也许您过去可以。请在此处查看我的答案以获取测试数据保护的更新方法:https://***.com/a/40044841/1165843

【讨论】:

你说得对,今天有点恐慌,因为在检查 NSDataProtectionComplete 是否加密 plist 时,我意识到当连接到 XCode>Devices 时我可以看到我的应用程序容器中的所有内容。以前不是这种情况。【参考方案7】:

对于完整的测试,我建议使用 iDB (https://github.com/dmayer/idb) 等工具在您的 iOS 应用程序上执行渗透测试,如 in this guide 所述。 与您相关的可能还有this Cheat Sheet for iOS security testing.

【讨论】:

以上是关于实施和测试 iOS 数据保护的主要内容,如果未能解决你的问题,请参考以下文章

iOS的iTunes备份探究

国内个人隐私保护安全法规实施里程碑

核心数据和数据保护

组织为什么要实施网络安全等级保护

iOS 数据保护不适用于已安装的应用程序

有没有办法保护谷歌云端点原型数据存储?