Index
应用程序外没有存储敏感数据
描述
为了确保正确存储敏感数据(如用户凭据、会话令牌和 PII),敏感数据不得存储在应用程序容器或系统凭据存储之外。
敏感数据可能会通过不安全的 IPC 机制暴露,或者无意中泄露到云存储、备份或键盘缓存。因此,在发生移动设备丢失或被盗的风险时,必须考虑物理访问场景。
建议
iOS
在 iOS 上,开发人员可以利用 iOS 数据保护 API 来保护敏感数据。该 API 依靠 Secure Enclave Processor (SEP) 提供安全的加密处理和密钥管理。
可以为文件分配一个保护类,该类提供不同级别的保护:
-
完全保护 (
NSFileProtectionComplete):从用户密码和设备 UID 派生的密钥保护此保护类密钥。在设备锁定后不久,派生密钥会从内存中擦除,从而使数据无法访问,直到用户解锁设备。 -
除非打开否则保护 (
NSFileProtectionCompleteUnlessOpen):此保护类类似于完全保护,但是如果在解锁时打开了文件,则即使用户锁定了设备,应用程序也可以继续访问该文件。例如,当在后台下载邮件附件时,将使用此保护类。 -
受保护直到首次用户身份验证 (
NSFileProtectionCompleteUntilFirstUserAuthentication):用户在启动后首次解锁设备时即可访问该文件。即使随后用户锁定设备且保护类密钥未从内存中删除,也可以访问它。 -
无保护 (
NSFileProtectionNone):此保护类的密钥仅受 UID 保护。保护类密钥存储在“Effaceable Storage”(可擦除存储)中,这是 iOS 设备上闪存的一个区域,允许存储少量数据。这种保护类是为了快速远程擦除(立即删除类密钥,这会使数据无法访问)而存在的。
除 NSFileProtectionNone 之外的所有保护类密钥均使用从设备 UID 和用户密码派生的密钥进行加密。
因此,解密只能在设备本身上进行,并且需要正确的密码。
自 iOS 7 起,默认数据保护类为“受保护直到首次用户身份验证”。
Keychain(钥匙串)还可以存储少量数据,如加密密钥和会话令牌。访问钥匙串是使用自定义 API 完成的,例如:
SecItemAddSecItemUpdateSecItemCopyMatchingSecItemDelete
存储在 Keychain 中的数据通过类似于用于文件加密的类结构来保护。添加到 Keychain 的项被编码为二进制 plist,并在 Galois/Counter Mode (GCM) 下使用每项 128 位 AES 密钥进行加密。请注意,较大的数据块不应直接保存在 Keychain 中——这就是数据保护 API 的目的。您可以通过在调用 SecItemAdd 或 SecItemUpdate 时设置 kSecAttrAccessible 密钥来配置 Keychain 项的数据保护。
以下可配置的 kSecAttrAccessible 辅助功能值 是 Keychain 数据保护类:
kSecAttrAccessibleAlways:无论设备是否锁定,都可以始终访问 Keychain 项中的数据。kSecAttrAccessibleAlwaysThisDeviceOnly:无论设备是否锁定,都可以始终访问 Keychain 项中的数据。该数据不会包含在 iCloud 或本地备份中。kSecAttrAccessibleAfterFirstUnlock:重新启动后,在用户解锁设备之前无法访问 Keychain 项中的数据。kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly:重新启动后,在设备被用户解锁一次之前无法访问 Keychain 项中的数据。具有此属性的项不会迁移到新设备。因此,从不同设备的备份中恢复后,这些项将不存在。kSecAttrAccessibleWhenUnlocked:仅当用户解锁设备时才能访问 Keychain 项中的数据。kSecAttrAccessibleWhenUnlockedThisDeviceOnly:仅当用户解锁设备时才能访问 Keychain 项中的数据。该数据不会包含在 iCloud 或本地备份中。kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly:仅当设备已解锁时才能访问 Keychain 中的数据。只有在设备上设置了密码时,此保护类才可用。该数据不会包含在 iCloud 或本地备份中。
AccessControlFlags 定义了用户可以验证密钥的机制 (SecAccessControlCreateFlags):
kSecAccessControlDevicePasscode:通过密码访问该项。kSecAccessControlBiometryAny:通过 Touch ID 注册的指纹之一访问该项。添加或删除指纹不会使该项无效。kSecAccessControlBiometryCurrentSet:通过 Touch ID 注册的指纹之一访问该项。添加或删除指纹_将_使该项无效。kSecAccessControlUserPresence:通过注册的指纹之一(使用 Touch ID)或默认使用密码来访问该项。
Android
在 Android 上,开发人员可以利用多种功能来存储数据,例如 Shared Preferences、SQLite、内部和外部存储,但也可能通过日志记录、备份、缓存等机制泄露数据。
Shared Preference 是一种常用的数据存储 API,可以声明为对所有人可读的权限。不安全地使用 Shared Preferences API 可能会暴露数据。
SQLite 是存储数据的另一种常见形式,且未加密。开发人员必须首选提供更高数据隐私的加密替代方案,例如 SQLCipher。
默认情况下内部存储是容器化的,设备上的其他应用程序无法访问。但是,可以设置不安全模式 MODE_WORLD_READABLE 和 MODE_WORLD_WRITEABLE,这两个模式均已弃用。
外部存储对所有人可读,不得用于存储敏感数据。需要注意的是,存储在应用程序容器 /data/data/<package-name> 之外的数据在卸载应用程序时不会被删除。
Android KeyStore 和 KeyChain 提供安全的数据存储。KeyStore 使用公钥创建加密机密来加密数据。KeyChain 用于存储系统范围的私钥,需要用户设置 PIN 码或密码。
链接
标准
- HIPAA_CONTROLS:
- SECURITY251
- SECURITY212
- SECURITY213