适用于iOS的OWASP:M1-平台使用不正确,第1部分

此故事描述了iOS开发人员如何应对OWASP Mobile Top 10 2016中的M1类别漏洞。该类别涵盖了平台功能的滥用或平台安全控件的使用失败。 在第1部分中,我们将介绍Apple提供的加密工具以及iOS的其他一些与隐私相关的功能。

文件数据保护

Secure Enclave — A7和更高版本处理器中的协处理器,使用加密的内存和硬件随机数生成器为数据保护密钥管理和Touch ID提供加密操作。

UID —唯一标识符,融合到处理器和Secure Enclave中的AES 256位密钥,对于每个设备都是唯一的。 允许将数据绑定到设备。

文件系统上的所有文件均受数据保护技术保护(可用于文件和数据库API,包括NSFileManager,CoreData,NSData和SQLite):

  1. 每次在数据分区上创建文件时,Data Protection都会创建一个新的256位密钥(“每个文件”密钥),并将其提供给硬件AES引擎以对该文件进行加密。
  2. 每个文件密钥都用几个Data Protection类密钥之一包装(在Secure Enclave中),并与数据保护类的表示法一起存储在文件的元数据中。
  3. 所有文件的元数据都使用文件系统密钥加密,该文件系统密钥是在首次安装iOS或用户擦除设备后创建的。 删除此密钥,用户可以使所有文件不可解密。
  4. 数据保护类密钥受UID保护,对于某些类,还受用户密码保护

文件密钥永远不会暴露给处理器。 它们仅在跨系统运行时才用AES引擎和Secure Enclave已知的临时密钥包装。

应在项目设置(包括在权利中)中启用“文件数据保护”,但是默认情况下,对于所有应用程序,所有数据都会被加密,直到首次解锁。

钥匙串数据保护

iOS钥匙串 -存储在文件系统上的SQLite数据库,用于处理密码和其他简短但敏感的数据位。

securityd守护程序根据其“ keychain-access-groups”,“ application-identifier”和“ application-group”权利来确定每个应用程序可以访问哪些钥匙串项目。 从iOS9开始,钥匙串密码数据一直保存在Secure Enclave中(在iPhone 5S和更高版本上)。

钥匙串中有五组项目:通用密码,Internet密码,身份,证书和密钥。

除其他字段外,每个钥匙串项目均包含:

  1. 钥匙串组访问(kSecAttrAccessGroup) 允许开发人员的应用访问设备上共享的钥匙串项目; 应用程序必须共享可以在权利中设置的相同捆绑包种子ID。
  2. 数据保护等级 (kSecAttrAccessible) —下一节将详细介绍。
  3. iCloud钥匙串(kSecAttrSynchronizable)-允许用户在iOS设备和Mac计算机之间安全地同步其钥匙串项目,而无需将该信息暴露给Apple。 默认情况下,第三方应用添加的钥匙串项目不会同步。 该值应与兼容的数据保护类一起使用(一个不带… ThisDeviceOnly后缀)。
  4. 管理元数据,例如创建上次更新的时间戳,版本号,使用保护类密钥包装的每个项目密钥,
  5. SHA-1散列的属性(例如帐户和服务器名称)用于查询项目而不解密每个项目
  6. 描述该项目的属性字典,该项目被编码为二进制plist并使用逐项密钥加密

“如果有人偷了您的设备,他们将能够读取钥匙串的内容。 通常,这是通过执行临时越狱并提取密钥来完成的。 使用kSecAttrAccessibleAfterFirstUnlock通常可以防止这种情况,因为执行越狱通常需要重新启动。 但是,通过代码执行攻击(例如利用Wi-Fi驱动程序中的错误的人进行攻击),可以在设备仍在运行时对其进行访问。 在这种情况下,将需要使用kSecAttrAccessibleWhenUnlocked来防止密钥被泄露,这意味着攻击者将需要确定用户的密码来提取机密。”

David Thiel,“ iOS应用程序安全性”,2016年。

NSFileProtectionComplete / kSecAttrAccessibleWhenUnlocked(默认值) :类密钥受从密码和UID派生的密钥保护。 用户锁定设备后不久,将丢弃已解密的类密钥,从而使所有数据都无法访问,直到用户解锁设备为止。

NSFileProtectionCompleteUnlessOpen :设备锁定时,可能需要写入一些文件。 一个很好的例子是在后台下载邮件附件。 通过使用非对称椭圆曲线密码术可以实现此行为。

NSFileProtectionCompleteUntilFirstUserAuthentication(default) :当设备锁定时,不会从内存中删除类密钥。 保护数据免受涉及重新启动的攻击。 所有第三方应用程序数据的默认类。 kSecAttrAccessibleAfterFirstUnlock :用于在后台更新期间需要访问的钥匙串项目。

NSFileProtectionNone / kSecAttrAccessibleAlways :类密钥仅受UID保护。 仅提供快速的远程擦除。 八卦,它计划在iOS9中被弃用,但目前(12月16日)它仍然存在。

kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly的行为与kSecAttrAccessibleWhenUnlocked相同,但仅在设备配置了密码后才可用。 它不包含在任何备份中。 如果密码被删除或重置,则这些物品将永远不会被解密!

其他钥匙串类具有…ThisDeviceOnly副本,当在备份期间从设备复制时,该副本始终受UID保护,如果将其还原到其他设备,将使其无效。

在存储数据时,请使用限制性最强的保护类,该保护类仍然允许您的应用程序正常运行。 为防止钥匙串项目通过iTunes备份或iCloud钥匙串暴露,请使用…ThisDeviceOnly保护类之一。

钥匙包

文件和钥匙串数据保护类的密钥都在密钥包中收集和管理。 iOS使用以下五个密钥包:

  1. 用户钥匙包是正常操作中使用包装的类密钥的地方
    设备的存储。 No Protection类中的二进制plist,但是其内容使用密钥加密,并在每次用户更改密码时重新生成。
  2. 设备密钥包用于存储包装的类密钥,这些类密钥用于配置为共享使用的设备特定数据。
  3. 当iTunes进行加密备份并将其存储在设备备份到的计算机上时,将创建备份密钥包 。 使用一组新密钥创建一个新的密钥袋,并将备份的数据( …ThisDeviceOnly密钥链项目除外)重新加密为这些新密钥。 密钥袋受iTunes中设置的密码保护(可能会尝试强行攻击)。 如果是未加密的备份 ,则无论文件的数据保护类别如何,都不会对文件进行加密,但是密钥链仍受UID派生的密钥保护,并且此类备份只能在同一设备上使用。 因此,只有设置了备份密码,钥匙串项目才会迁移到新设备。
  4. 托管密钥包用于iTunes同步和MDM。
  5. iCloud Backup钥匙包类似于备份钥匙包。 对于除No Protection之外的所有Data Protection类,将从设备读取加密的数据并将其发送到iCloud。 相应的类密钥受iCloud密钥保护。

访问Safari保存的密码

iOS应用可以与Safari保存的钥匙串项目进行交互,以使用API​​自动填充密码:

  • SecRequestSharedWebCredential
  • SecAddSharedWebCredential

仅在应用程序开发人员和网站管理员均已批准并且用户已同意的情况下,才授予访问权限。 应用程序开发人员通过在其应用程序中包含权利来表达访问Safari保存的密码的意图。 权利列出了关联网站的标准域名。 网站必须在其服务器上放置一个文件,列出他们已批准的应用程序的唯一应用程序标识符。 安装具有com.apple.developer.associated-domains权利的应用程序后,iOS会向列出的每个网站发出TLS请求,以请求文件/ apple-app-site-association。 如果文件列出了要安装的应用程序的应用程序标识符,则iOS会将网站和应用程序标记为具有可信任的关系。 仅在具有可信赖的关系的情况下,对这两个API的调用才会向用户提示,该用户必须同意才能将任何密码发布到应用,更新或删除密码。

LocalAuthentication.framework与钥匙串服务访问控制

触摸ID —指纹感应系统。 仅与Secure Enclave一起使用,而不备份到任何地方。

第三方应用程序可以使用系统API要求用户使用Touch ID(如果允许这种回退,则可以输入密码)进行身份验证。 仅通知应用验证是否成功。

有两种方法可以从应用程序强制用户通过Touch ID(或密码)身份验证,但是从用户的角度来看,它们是相同的:将显示系统样式的UI,开发人员确实指定了提示字符串来描述为什么要求用户进行身份验证。 所有带有密码或指纹的操作将由Secure Enclave执行。

第一种方法, LocalAuthentication.framework ,提供了一种从具有指定安全策略的用户请求身份验证的简便方法。

LocalAuthentication.framework提供了一种快速的方法来验证设备是否支持Touch ID并准备就绪,并向用户显示身份验证对话框并评估其提供的指纹或密码是否匹配。

更严格,更底层的方法:将项保存到“钥匙串”时,“钥匙串访问控制”对象可以包含在SecItemAdd查询中。 仅当用户通过身份验证后,才会从钥匙串返回商品。 访问控制属性kSecAttrAccessControl与kSecAttrAccessible属性互斥:

当通过一组SecAccessControlCreateWithFlags属性将数据存储到钥匙串时,可以指定钥匙串访问控制 。 该代码不使用任何包装,您可以看到所有Unmanaged内存,指针和C函数的详细程度。
然后,要访问存储的数据,只需查询Keychain的密钥即可。 (可选)可以指定提示字符串。 钥匙串服务将向用户显示身份验证对话框,并根据是否提供了合适的指纹或匹配的密码返回数据或零。