实施和测试 iOS 数据保护

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5155789/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 19:04:24  来源:igfitidea点击:

Implementing and Testing iOS data protection

iphoneobjective-csecurityiosdata-protection

提问by Omer

Just saw the Session 209 - Securing Application Data from de 2010 WWDC.

刚刚看到了 2010 年 WWDC 会议 209 - 保护应用程序数据。

The keynote explains a lot of things, including the way you can set data protection attributes to your files (NSFileProtectionComplete, NSFileProtectionNone) and how to decide which protection is best for your case.

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

I just implemented it, but can't figure out how to test if the security is on, any ideas?

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

In addition, I have a sql lite database that needs to be accessed in background from time to time, and this method of data protection seems to be not good enough.. any link or tutorial that guide me through the best db protection? (found sql cipher but is kinda heavy to add in a evoluted project)

另外,我有一个sql lite数据库需要不时在后台访问,而这种数据保护方法似乎还不够好..有什么链接或教程可以指导我完成最好的db保护吗?(找到了 sql 密码,但在进化的项目中添加有点繁重)

Thanks!

谢谢!

回答by Josh Vickery

Update:With iOS 6 it's supposedly possible to require data protection for your application by using an entitlement that needs to be configured on the App ID in the iOS provisioning profile. I haven't tested this yet, and this is the best information I could find on it https://devforums.apple.com/message/707939#707939

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



My investigations into this matter lead me to believe that it is very difficult to determine if data protection is enabled on a device.

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

File protection is enabled by setting the NSFileProtectionKeyfile attribute to NSFileProtectionComplete

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

For example, to create a protected file you could run code like:

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

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

Unfortunately this code will execute without error even if Data Protection is not enabled on the device (or if the code is run on the Simulator where Data Protection is not available).

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

Worse, the NSFileProtectionCompleteattribute will be be set regardless of whether the file is protected or not. The following:

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

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

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

will spit out file protection value: NSFileProtectionCompleteno matter whether Data Protection is enabled or not.

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

There are two methods that I've been able to use to discover if File Protection is working as expected. Unfortunately neither of these methods are suitable for detecting if Data Protection is enabled on a device in the field.

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

Both methods work on the idea that a protected file can not be read if the device is locked.

这两种方法都基于这样的想法:如果设备被锁定,则无法读取受保护的文件。

Method one involves using a timer to attempt to read the file after the device is locked, but while your application continues to run:

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

[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);
}

If you run the above code and lock a data protected device it will spit out:

如果你运行上面的代码并锁定一个受数据保护的设备,它会吐出:

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"}

The 20 second delay is necessary because there is a 10 second or so grace period where protected data is still available after a Data Protection enabled device is locked.

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

The second method is to create a protected file in an application, exit the application, lock the device, wait 10 seconds, and then use the XCode organizer to download the contents of the application. This will produce an error message and the protected file will be empty.

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

If either of the above tests fail to behave as described then Data Protection is either not enable, or your File Protection code was not implemented correctly.

如果上述测试中的任何一个未能按所述进行,则数据保护未启用,或者您的文件保护代码未正确实施。

Because I've not found any way to verify within the application that Data Protection is enabled before I write confidential information to disk, I've filed a feature enhancement request with Apple to be able to mark an application as requiring Data Protection to be enabled. (rdar://10167256)

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

Apple does offer a solution to this through their Mobile Device Management (MDM) APIs, which combined with a third party server can be used to enforce policies that require Data Protection to be enabled on devices.

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

回答by XGouchet

You can use the iExplorerapp to detect if your files are encrypted. iExplorer lets you browse the filesystem of your iPhone/iPad, and open the file (of course your device must be plugged into your Mac).

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

When the device is locked, the files can't be read correctly.

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

回答by iHS

From the NSFileManagerclass doc:

NSFileManager类文档:

The file is stored in an encrypted format on disk and cannot be read from or written to while the device is locked or booting.

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

You just pass the constant when you set the file attributes.

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

When writing the contents of an NSData object to disk using the writeToFile:options:error: method, include the NSDataWritingFileProtectionComplete option.

Use the setAttributes:ofItemAtPath:error: method of NSFileManager to add the NSFileProtectionKey attribute (with the NSFileProtectionComplete value) to an existing file

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

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

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

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

EDIT (Determining the Availability of Protected Files)

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

A protected file is accessible only when a device is unlocked. Because applications may continue running while a device is locked, your code should be prepared to handle the possibility of protected files becoming unavailable at any time. The UIKit framework provides ways to track whether data protection is currently enabled.

只有在设备解锁时才能访问受保护的文件。由于应用程序可能会在设备锁定时继续运行,因此您的代码应准备好处理受保护文件随时不可用的可能性。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. 

Any application that works with protected files should implement the application delegate methods. When the applicationProtectedDataWillBecomeUnavailable: method is called, your application should immediately close any protected files and refrain from using them again until the applicationProtectedDataDidBecomeAvailable: method is called. Any attempts to access the protected files while they are unavailable will fail.

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

Verifying file protection on jailbroken devices

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

To step further, if you would like to test the file protection of exact file, then you would need a jailbroken device. For that, here are the (non-detailed) steps:

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

1) Jailbreak an iOS device

1) 越狱 iOS 设备

2) Install Open SSH via Cydia (This is required to remotely access files from that device) (https://cydia.saurik.com/openssh.html)

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

3) Login from your computer (using Mac client or Terminal) as a root user to your device.

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

To find location of your app's directories and files, there are various ways. Either you can

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

  • grepthe process of an app (Such as ps ax | grep YourAppName) - Make sure app is running on device to get the process details. It should give the location of app bundles
  • Alternatively, you can also search specific file using findyou are interested in. For eg. find / -type f -name YouAppName.sqlite. It should give file location on the device.
  • grep应用程序的进程(例如ps ax | grep YourAppName) - 确保应用程序正在设备上运行以获取进程详细信息。它应该给出应用程序包的位置
  • 或者,您也可以使用find您感兴趣的特定文件进行搜索。例如。find / -type f -name YouAppName.sqlite. 它应该提供设备上的文件位置。

From here, you can try to see if the file is really accessible or not, when phone is locked with a passcode; or not. - You can simply run cat YouAppName.sqliteto see if contents are accessible. Ia f file is protected, it should show

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

Operation not permitted

不允许操作

error; else if would show contents of file.

错误; 否则如果会显示文件的内容。

Again, this is required if you'd really like to check file protection of an individual file. If entitlements and capabilities are set properly, verifying entitlements should be enough for fileprotection.

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

On a side node, file explorer tools such as iExplorer don't help much in verification of FileProtection, because such tools require a device to be in "trusted" mode, so they have permissions to access the content of your device/apps.

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

Good luck!

祝你好运!

回答by Declan McKenna

Testing can be done within Xcode:

测试可以在 Xcode 中完成:

  1. Delete and reinstall your app
  2. On your iOS device go to Settings > Passcode and ensure 'Require Passcode' is set to 'Immediately'
  3. Lock your phone and wait 20 seconds
  4. On Xcode go to Window > Devices
  5. Select the app you'd like to test
  6. Click the settings cog and choose 'download container'
  7. Right click the downloaded .xcappdata file and select 'show package contents'. Anything you can view here has not been encrypted by NSFileProtectionComplete
  8. Unlock your phone and repeat steps 3-6. Files that previously did not appear that you can now view were successfully encrypted.
  1. 删除并重新安装您的应用
  2. 在您的 iOS 设备上,转到“设置”>“密码”并确保“需要密码”设置为“立即”
  3. 锁定手机并等待 20 秒
  4. 在 Xcode 上转到窗口 > 设备
  5. 选择您要测试的应用
  6. 单击设置齿轮并选择“下载容器”
  7. 右键单击下载的 .xcappdata 文件并选择“显示包内容”。您可以在此处查看的任何内容均未经过加密NSFileProtectionComplete
  8. 解锁手机并重复步骤 3-6。以前没有出现但现在可以查看的文件已成功加密。

enter image description here

在此处输入图片说明

回答by quellish

File protection can be enabled on a per-file or per-directory basis, or can be enabled for the whole application (using entitlements and the provisioning profile). To determine if a file or directory is protected, check the filesystem attributes for the data protection key. This should be valid even it's a parent directory that was set to be protected:

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

- (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;
}

To determine if the protected content is available, UIApplication provides a method for querying the protection state, isProtectedDataAvailable. Using it with the above method would allow you to determine wether a particular file or directory is available:

为了确定受保护的内容是否可用,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;
}

回答by moliveira

I don't think you can test Data Protection with computer-based tools and a non-jailbroken iPhone anymore - maybe you could in the past. Please see my answer here for an updated method for testing Data Protection: https://stackoverflow.com/a/40044841/1165843

我认为您不能再使用基于计算机的工具和未越狱的 iPhone 来测试数据保护——也许过去您可以。有关测试数据保护的更新方法,请在此处查看我的回答:https: //stackoverflow.com/a/40044841/1165843

回答by maggix

For a complete testing I would suggest using tools such as iDB ( https://github.com/dmayer/idb) for performing pentesting on your iOS app, as described in this guide. Also relevant for you may be this Cheat Sheet for iOS security testing.

对于完整的测试,我建议使用 iDB ( https://github.com/dmayer/idb)等工具在您的 iOS 应用程序上执行渗透测试,如本指南中所述。同样与您相关的可能是此 iOS 安全测试备忘单。