间歇性和临时性 iOS 钥匙串故障

2024-01-08

我们有一个应用程序严重依赖于能够使用 iOS 访问用户的会话令牌Keychain。当我们的应用程序打开时,首先检查的是令牌是否可用 - 如果不可用,我们会向用户显示登录屏幕。我们不为此使用任何第三方库,并使用Keychain's SecItemAdd() / SecItemCopyMatching()直接使用以下选项:

  • kSecClassGenericPassword
  • kSecAttrAccessibleAlwaysThisDeviceOnly

在正常使用过程中,我们几乎没有看到任何问题。

问题

我们有用户报告说,打开他们的应用程序后,他们会看到登录屏幕(建议Keychain找不到值),当他们实际上登录时。我们发现在这种情况下,我们发现杀死并重新启动应用程序后,用户恢复正常(会话被发现于Keychain)。一旦发现这一点,我们尝试添加指数退避来继续查询钥匙串,认为它可能只在前几秒钟不可用。这并没有奏效,并向我们证明了这一点钥匙串似乎在整个应用程序启动会话中不可用。我们无法重现此问题。它似乎间歇性地发生。

经过进一步调查,我们发现用户通常收到过VoIP 推送在出现此问题之前。我们仍然无法可靠地重现这个问题,但经过调试,发现我们的Keychain.session被发现是nil当收到这些推送时(我们也依赖它),这是在用户打开他们的应用程序以查看他们伪“注销”之前。

We use PushKit https://developer.apple.com/documentation/pushkit and PKPushRegistry https://developer.apple.com/documentation/pushkit/pkpushregistry为了做VoIP 推送 https://developer.apple.com/library/archive/documentation/Performance/Conceptual/EnergyGuide-iOS/OptimizeVoIP.html。这要求我们的应用程序启用“后台模式:IP 语音”。我们按照 Apple 文档的建议使用所有这些。这是一个示例:

func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, for type: PKPushType) {
    guard let _ = Keychain.session else {
        print("Session token not available")
        return
    }
    handle(notification: payload.dictionaryPayload)
}

这段代码依赖于Keychain.session收到 VoIP 推送后立即可用。如前所述,我们已经看到过它不可用的情况,因此该函数会注销并简单地返回。

我也发现了这个相关的苹果论坛帖子 https://forums.developer.apple.com/thread/26168,表明这可能是一个 iOS 错误。

有人可以帮助我们解决这个问题吗?任何帮助将不胜感激。即使这实际上是一个 iOS 错误,我们也愿意采取解决方法。


我认为这个话题长期以来一直让 iOS 开发社区变得疯狂。我读过太多关于此的文章和帖子,以至于我都数不清了。

所以,我也在处理这个问题,根据 @naqi 的回答,我开始朝这个方向前进,我可能已经找到了一个可行的解决方案。

假设:

当应用程序由于任何原因而被暂停时,似乎会发生此问题(例如,应用程序长时间处于后台并且由于内存压力,操作系统将其发送为暂停状态,或者应用程序处于后台并且用户升级到商店的新版本或自动应用程序更新可以做到这一点)。我不再完全确定暂停意味着什么,但我强烈怀疑应用程序可能会恢复/唤醒,而不会实际显示在屏幕上(由于 bg 任务,但不一定)。 苹果开发者论坛上的一位苹果员工勇敢地回复说“尝试在addDidFinishLaunchingWithOptions and appDidBecomeActive“。除了这里的疯狂之外,阅读该评论让我想到也许当应用程序恢复时它会触发addDidFinishLaunchingWithOptions但当然不是appDidBecomeActive(因为它可能不会由用户恢复,而是从操作系统在后台处理的任何类型的事件中恢复,我们可能没有控制似乎,或任何其他功能,如 bg 任务或静默推送通知等)。

额外信息:

根据我在网上找到的一篇相当古老的渗透测试文章(https://resources.infosecinstitute.com/iphone-penetration-testing-3/ https://resources.infosecinstitute.com/iphone-penetration-testing-3/)查询钥匙串实际上会将查询寻址到另一个名为securityd在设备上运行,它神奇地安排查询并将其执行到钥匙串数据库,最后将内容返回到请求应用程序,假设在钥匙串数据库上完成查询时应用程序仍然存在。这让我认为,如果这仍然是正确的,这样的过程可能会陷入某种“DDoS”攻击,您的应用程序(或者可能是所有正在执行的应用程序?不清楚它实际上是如何工作的)执行太多查询。这可能会导致误报,例如 secItemNotFound 或类似错误。再次强调,由于没有人证实这一点,因此将其作为我个人的考虑。

Approach:

从@Naqi 的回答中,我可以排除第 2,3 点和第 4 点,将第 1 点保留为唯一仍然有效的理由。话虽如此,我决定将任何处理钥匙串的 CRUD 操作从addDidFinishLaunchingWithOptions to appDidBecomeActive,通过处理其中的应用程序设置指令(无论您的应用程序需要什么),以确保挂起/恢复操作的最终后台事件根本不会影响钥匙串,因为appDidBecomeActive除非用户实际使应用程序打开并显示在屏幕上,否则不会被调用。当然,这应该只在应用程序启动时发生,因此您可以在中使用布尔标志或类似的信号量方法appDidBecomeActive以确保您的设置逻辑仅执行一次。

结合上面的方法,在App Delegate中我还显式地实现了application(shouldSaveApplicationState:)通过返回false and application(shouldRestoreApplicationState:仍在返回false(尽管我认为默认情况下应该已经这样了)。这可能不一定有用,但也值得尝试。

总而言之,在一些随机无法访问钥匙串的受影响设备上,几周以来似乎不再发生这种情况,并且考虑到这种情况在某些设备上几乎每 2/3 天就会发生一次,我认为这可能至少会减弱该问题。

我可以说,受监控的设备都具有不同的配置,是否安装了大量应用程序,存储内存几乎已满或未满,大量应用程序处于背景状态或根本没有,任何外形规格和不同的 iOS 版本。未启用钥匙串备份到云,并且钥匙串上的项目属性至少为kSecAttrAccessibleWhenUnlockedThisDeviceOnly

开放点未完全验证:按说对钥匙串的访问应该是线程安全的,但我发现网络上的不同线程相互矛盾。也许这会以某种方式影响你的逻辑并导致意外的状态

(如果您成功阅读到这里,恭喜您:) )

希望这有助于进一步了解 iOS 中的钥匙串悲剧是怎么回事

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

间歇性和临时性 iOS 钥匙串故障 的相关文章

随机推荐

  • 空值powershell数组

    我有一个奇怪的问题 这是我的 CSV Serveur Carte Cordon IP Mac Vmnic Vmnic mac Connect Port Dexter eth1 405 172 16 5 117 00 24 e8 36 36
  • 是否可以使用 CSS 在边距之外添加边框?

    我很确定已经有人问过这个问题了 但我在谷歌或这里找不到它 我只是好奇 CSS 在这方面的局限性 是否可以使用 CSS 在边距之外添加元素的边框 基本上 我希望将边框放置在边距之外 而不是填充之外 我了解盒子模型在 CSS 中的工作原理 因此
  • Looper如何知道将消息发送给Handler?

    问题是 我告诉我的线程使用mHandler为了Looper 谢谢 我正在使用下面的代码 class LooperThread extends Thread public Handler mHandler public void run Lo
  • 如何使用 TFS 离线工作

    我们的 TFS 服务器目前存在一些临时连接问题 因此 VS 没有响应 导致 50 多名开发人员无法工作 如果出现此类问题 是否可以将 TFS 切换到离线模式 看到这个参考 http msdn microsoft com en us libr
  • 如何在 AWS Amplify/AppSync React 应用程序中正确处理未经身份验证的用户和请求?

    我很难弄清楚如何在使用 AWS Amplify 和 AWS AppSync 的 React 应用程序中处理未经身份验证的用户 似乎大多数文档建议将整个应用程序包装起来withAuthenticatorHOC 来自aws amplify re
  • Bootstrap 手风琴,单击时滚动到活动(打开)手风琴的顶部?

    我正在使用 Bootstrap 制作一个响应式网站 它包含带有大量文本的手风琴 当您读到底部并单击下一个手风琴时 大量文本被折叠 我留在页面底部 我发现这个有用的代码Bootstrap 手风琴滚动到活动面板标题的顶部 https stack
  • 从 IE 获取用户名,以针对 LDAP 进行身份验证

    用户将仅使用 IE 并且在 IE 中 如果他们登录到域控制器 则可以在没有提示的情况下传递他们的凭据 我想知道的是 我该如何获取他们的用户名 我认为这可以解决问题 SERVER auth user 但没有运气 像这样您可以在 PHP 中获取
  • Angular 2+ - 检查 Pipe 是否返回原始列表的空子集

    我有一个要迭代的字符串列表 但我希望能够使用搜索词过滤它们 像这样 div item div 我的问题是 如何检查管道是否返回列表的空子集 换句话说 如果没有任何字符串与搜索词匹配 我想显示一条消息 没有匹配项 div No matches
  • 加载时淡入延迟

    我偶然发现了一些非常好的东西 我想在即将到来的项目中使用 这是加载时的动画不透明度 或者您可以将其称为淡入 我想知道你是否可以将一些元素链接在一起 例如 3 element2仅在以下时间开始element1完成了 并且element3当没有
  • 在 Ubuntu 18.04 上安装 Ruby 2.3.x 在安装过程结束时导致错误

    我最近将系统更新到了 Ubuntu 18 04 LTS 从那时起 Ruby 版本似乎已经更新到了 2 5 问题是 当尝试部署使用 Capistrano 的项目时 它现在会抱怨找不到 Ruby 2 3 运行时尝试安装的版本rvm instal
  • 将 Docker-Machine 与 Amazon EC2 集成

    我正在阅读这篇文章 它向我展示了如何在 amazon ec2 之上配置我的 docker VM https docs docker com machine drivers aws https docs docker com machine
  • 在打字稿模块内扩展全局类型(例如“Window”)

    如果您使用打字稿编写并且不使用模块 则可以扩展全局Window目的 例如 这样编译 interface Window myCounter number window myCounter window myCounter 0 window m
  • 我不知道如何让我的玩家在接触敌人时死亡

    就像标题所说 我不知道如何让我的玩家在敌人接触他时死亡 我已经查过了 但我仍然无法弄清楚这一点 有什么想法吗 跳过下一部分 希望我在这里放更多东西 但显然没有说到重点 ulahtluihliukhrefluijaheuflhawuleifh
  • 实例化一个 TypeVar 类型

    作为一名 C 程序员 以下代码对我来说似乎很自然 但它无法运行 from typing import TypeVar Generic List NewType TPopMember TypeVar TPopMember Population
  • 在嵌入式 x86 程序集中使用数组?

    我有一个方法 C 它返回一个字符并采用一个字符数组作为其参数 我第一次搞乱汇编 只是试图返回 dl 寄存器中数组的第一个字符 这是我到目前为止所拥有的 char returnFirstChar char arrayOfLetters cha
  • PHP DOM:更改现有 DOMDocument 的文档类型

    创建 DOMDocument 时DOMImplementation createDocument http www php net manual en domimplementation createdocument php 您可以指定文档
  • Python - 如果不是带有 0.0 的语句

    我有一个关于if not中的声明Python 2 7 我写了一些代码并使用了if not声明 在我编写的代码的一部分中 我引用了一个函数 其中包含if not语句来确定是否输入了可选关键字 它工作正常 除了当0 0是关键字的值 我明白这是因
  • 导航栏大标题 - 动画问题

    我在导航栏上使用大标题 当我点击一个单元格进入下一个控制器时 大标题有一个奇怪的动画 如下面的 gif 所示 它不会立即消失 我尝试了以下解决方案 但没有任何结果 https www morningswiftui com blog fix
  • p:fileUpload required =“true”并且自定义验证器不起作用[重复]

    这个问题在这里已经有答案了 自从required的属性
  • 间歇性和临时性 iOS 钥匙串故障

    我们有一个应用程序严重依赖于能够使用 iOS 访问用户的会话令牌Keychain 当我们的应用程序打开时 首先检查的是令牌是否可用 如果不可用 我们会向用户显示登录屏幕 我们不为此使用任何第三方库 并使用Keychain s SecItem