1

语境

我正在开发一个 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;博士

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

谢谢您的帮助!

4

1 回答 1

2

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

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

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

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

好的,所以回到你可能考虑在你的用例中做的事情。可能有两种可能:

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