【问题标题】:Understanding the access control setting `.userPresence` for keychain items了解钥匙串项目的访问控制设置`.userPresence`
【发布时间】:2021-12-13 13:45:01
【问题描述】:

上下文

我正在开发一个 iOS 应用程序,它应该受到本地身份验证的保护。用户必须在打开应用程序后使用指纹/密码/…解锁应用程序。当应用程序在前台运行时,应用程序应保持解锁状态。当应用解锁时,应用必须访问钥匙串中的多个项目(应用运行时可能会多次访问某些项目)。

使用 .userPresence 进行钥匙串访问控制

将钥匙串项目的访问控制设置为.userPresence 会在访问项目之前强制执行本地身份验证。但是,这并不真正适合我的用例,因为每次访问钥匙串中的项目时,用户都必须进行身份验证。

// storing keychain items with .userPresence access control
guard let accessControl = SecAccessControlCreateWithFlags(
    nil,
    kSecAttrAccessibleWhenUnlockedThisDeviceOnly,
    .userPresence,
    nil
) else {
    throw CommonError("Unable to create access control flags")
}

let query = [
    kSecClass: kSecClassGenericPassword,
    kSecAttrAccount: account,
    kSecAttrAccessControl: accessControl,
    kSecValueData: ...
] as [String: Any]

SecItemAdd(query as CFDictionary, nil)

为了适合我的用例,我可以自己实现本地身份验证并将钥匙串项存储为kSecAttrAccessible: kSecAttrAccessibleWhenUnlockedThisDeviceOnly(而不是.userPresence)。我担心,在没有.userPresence 的情况下存储钥匙串项目可能会导致安全风险。如果我自己实现本地身份验证并使用kSecAttrAccessible: kSecAttrAccessibleWhenUnlockedThisDeviceOnly 访问钥匙串项而不是使用.userPresence 进行访问控制,是否会有所不同?

// storing keychain items without access control
let query = [
    kSecClass: kSecClassGenericPassword,
    kSecAttrAccount: account,
    kSecAttrAccessible: kSecAttrAccessibleWhenUnlockedThisDeviceOnly,
    kSecValueData: ...
] as [String: Any]

SecItemAdd(query as CFDictionary, nil)

我找不到任何文章或官方资料来解释我的担忧。如果可以链接任何官方文档,或者甚至为我的用例提供更好的解决方案,我将不胜感激。

TL;DR

将钥匙串项的访问控制设置为.userPresence是否会以任何方式提高安全性,或者如果我自己实现本地身份验证并将钥匙串项存储为kSecAttrAccessible: kSecAttrAccessibleWhenUnlockedThisDeviceOnly是否没有区别?

感谢您的帮助!

【问题讨论】:

    标签: ios swift security keychain apple-cryptokit


    【解决方案1】:

    在越狱设备上,或者至少在未越狱设备上进行了足够的权限提升后,攻击者可以伪装成您的应用,以访问您的钥匙串项目。拥有.userPresence 可以提高安全性,即使在攻击者伪装成您的应用程序的情况下,钥匙串也会对您的钥匙串项目的使用强制执行本地身份验证,即,当攻击者尝试使用您的钥匙串时项目,本地身份验证将启动。 关于这种攻击是如何可能发生的线索,可以在越狱分析中找到,例如this talk。

    如果您自己实现了本地身份验证,例如,在您的应用程序中,那么攻击者可以完全绕过它,甚至不需要运行您的应用程序(在刚才描述的场景中)。就钥匙串而言,当攻击者请求访问您的钥匙串项时,您的应用正在请求访问您的钥匙串项。

    除此之外,攻击者可能会通过其他方式尝试绕过您实施的本地身份验证,例如,使用frida 之类的工具来篡改您已实施的逻辑。据我所知,当您使用.userPresence 时,更难篡改本地身份验证逻辑,因为这将由 iOS 而非您的应用程序逻辑控制。

    现在,即使.userPresence 强制执行本地身份验证,攻击者仍可能会在用户尝试访问您的钥匙串项目时尝试诱骗用户进行本地身份验证,但这是另一个讨论。至少,使用.userPresence,阻止本地身份验证发生应该比使用您自己的实现更难。

    好的,那么回到您在用例中可能考虑做的事情。可能有两种可能:

    1. 您可以在 GitHub 等上找到各种移动应用程序保护技术,例如,检测您的应用程序是否在越狱设备上运行,以及检测对您的应用程序的其他类型的篡改(并且有还提供此类功能的商业产品,甚至是安全存储加密材料的替代方法)。因此,如果您进行风险评估并认为此类技术可以充分防止在越狱设备上运行,那么结合此类技术,您自己实施本地身份验证的原始方法可能仍然是一个很好的解决方案。
    2. 出于安全原因,您可以改为考虑使用.userPresence,并重新检查您的应用程序流程和用户体验,例如,以减少需要执行这些加密/解密操作、批处理甚至显示某些内容的频率您的用户界面向用户解释为什么他们每次都需要进行本地身份验证。根据您应用的功能以及您对它的解释方式,如果您可以帮助用户了解他们为什么需要在执行本地身份验证时进行本地身份验证,也许他们甚至会对您的应用的安全性更有信心?

    【讨论】:

    • 非常感谢您的详细回复!例如,我想在钥匙串中存储一个密钥(用于加密/解密文件)。为了提高安全性,使用.userPresence 存储密钥是有意义的(正如您所解释的)。现在,如果每次文件被加密或解密(在应用程序运行时可能会发生多次)时,用户必须解锁钥匙串项(使用本地身份验证),这将是一个非常糟糕的用户体验。对于如何实施这样的事情(不降低安全性),您有任何最佳实践或建议吗?
    • 当然,我知道你来自哪里。首先,我知道人们之前曾就越狱设备上的钥匙串问题与苹果联系过,但正如我所听到的,苹果的态度是说用户不应该首先越狱他们的设备,即他们可能仅当此类攻击可以在非越狱设备上演示时才能增强其保护。其次,好的..我即将达到字符限制:我会将其他点添加到我的主要答案文本中。
    猜你喜欢
    • 1970-01-01
    • 2012-06-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-20
    • 2020-01-26
    • 1970-01-01
    • 2017-02-13
    相关资源
    最近更新 更多