5

我正在我们的 android 应用程序中实现 SSL 固定。我通过将 2 个证书(当前和备份)嵌入到应用程序中,将它们固定在客户端。

现在,我希望有一种机制来更新这些证书,而无需在证书过期或私钥被泄露的情况下推出应用程序升级。我该如何实施?

我看到的一种可能的解决方案是通过应用通知。我可以广播带有新证书的通知并将它们存储在客户端中。这种方法有什么问题还是有更好的方法?

4

1 回答 1

13

公钥固定

我正在我们的 android 应用程序中实现 SSL 固定。我通过将 2 个证书(当前和备份)嵌入到应用程序中,将它们固定在客户端。

如果您锁定公钥,则无需在每次在服务器中轮换证书时更新您的移动应用程序,一旦您将使用相同的公钥对其进行签名,您可以阅读文章Hands On Mobile APi Security: Pinning有关如何完成此操作的更多详细信息,请访问客户端连接:

对于网络,Android 客户端使用 OKHttp 库。如果我们的数字证书是由 Android 认可的 CA 签署的,则可以使用默认的信任管理器来验证证书。要固定连接,只需将主机名和证书公钥的散列添加到客户端 builder() 即可。有关示例,请参阅此 OKHttp 配方。具有相同主机名和公钥的所有证书都将匹配哈希,因此可以使用证书轮换等技术,而无需客户端更新。多个主机名 - 公钥元组也可以添加到客户端 builder()。

对于用于签署证书的私钥被泄露的情况,您最终会遇到您现在尝试解决的相同情况,即需要发布一个新的移动应用程序来更新您信任的内容。换句话说,公钥不再受信任,因此服务器必须轮换证书,并使用您使用移动应用程序发布的备份公钥签名的证书。这种方法将为您提供新版本的时间,该版本删除用于签署受损证书的公钥,而不会锁定您的所有用户。

您应该始终将备份私钥存储在不同的地方,这样如果一个被泄露,您就不会立即受到所有泄露,因为使用移动应用程序发布备份 pin 是没有用的。

不要这样做

现在,我希望有一种机制来更新这些证书,而无需在证书过期或私钥被泄露的情况下推出应用程序升级。我该如何实施?

不幸的是,处理泄露的私钥更安全的方法是发布一个不再信任它的新移动应用程序。您为更新证书而设计的任何远程解决方案都将为攻击者打开移动应用程序的大门,以替换您固定的证书。

所以我的建议是不要走这条路,因为你会比你想象的更容易把自己踢到脚上。

我看到的一种可能的解决方案是通过应用通知。我可以广播带有新证书的通知并将它们存储在客户端中。这种方法有什么问题还是有更好的方法?

虽然移动应用程序已固定连接,但它可以被绕过,因此可以执行中间人攻击,并从攻击者服务器检索新证书,而不是从您的服务器。请阅读文章The Problem with Pinning以获得更多关于绕过它的见解:

取消固定通过在应用程序运行时挂钩或拦截应用程序中的函数调用来工作。一旦被拦截,钩子框架就可以改变传入或传出函数的值。当您使用 HTTP 库来实现 pinning 时,该库调用的函数是众所周知的,因此人们编写了专门挂钩这些检查函数的模块,因此无论 TLS 握手中使用的实际证书如何,它们总是通过。iOS 也存在类似的方法。

虽然可以绕过证书固定,但仍然强烈建议使用它,因为安全性与防御层有关,你拥有的越多,就越难克服所有这些……如果你想到中世纪,这并不是什么新鲜事城堡,他们用这种方法建造的。

一种可能更好的方法

但您也要求更好的方法:

这种方法有什么问题还是有更好的方法?

如前所述,您应该锁定证书的公钥,以避免在轮换服务器证书时锁定客户端。

虽然我不能为您指出一个更好的方法来处理泄露的私钥,但我可以指出保护证书固定不被内省框架(如 xPosed 或 Frida)绕过,我们可以使用移动应用程序证明技术,这将证明真实性的移动应用程序。

弗里达

将您自己的脚本注入黑盒进程。挂钩任何功能、监视加密 API 或跟踪私有应用程序代码,无需源代码。编辑,点击保存,立即查看结果。所有这些都无需编译步骤或程序重新启动。

摆姿势

Xposed 是一个模块框架,可以在不触及任何 APK 的情况下改变系统和应用程序的行为。这很棒,因为这意味着模块可以在不同版本甚至 ROM 上工作而无需任何更改(只要原始代码没有太大更改)。它也很容易撤消。

在我们深入研究移动应用程序证明技术之前,我想先澄清开发人员之间的一个常见误解,即关于WHOWHAT调用 API 服务器。

访问 API 服务器的 WHO 和 WHAT 之间的区别

为了更好地理解WHOWHAT访问 API 服务器之间的区别,让我们使用这张图片:

中间人攻击

Intended Communication Channel 表示移动应用程序正按您的预期被合法用户使用,没有任何恶意,使用未经篡改的移动应用程序版本,并直接与 API 服务器通信而不会受到中间人的攻击。

实际渠道可能代表几种不同的场景,例如怀有恶意的合法用户可能正在使用重新打包的移动应用程序版本,黑客使用移动应用程序的正版版本,而中间人攻击它,以了解如何移动应用程序和 API 服务器之间的通信正在完成,以便能够自动攻击您的 API。许多其他情况也是可能的,但我们不会在这里一一列举。

我希望现在你可能已经知道为什么WHOWHAT不一样,但如果不是,一会儿就会清楚。

WHO是移动应用程序的用户,我们可以通过多种方式对其进行身份验证、授权和识别,例如使用 OpenID Connect 或 OAUTH2 流。

认证

通常,OAuth 代表资源所有者向客户端提供对服务器资源的“安全委托访问”。它指定了资源所有者授权第三方访问其服务器资源而不共享其凭据的过程。OAuth 专为与超文本传输​​协议 (HTTP) 一起使用而设计,本质上允许授权服务器在资源所有者的批准下将访问令牌颁发给第三方客户端。然后第三方使用访问令牌访问资源服务器托管的受保护资源。

OpenID 连接

OpenID Connect 1.0 是 OAuth 2.0 协议之上的简单身份层。它允许客户端根据授权服务器执行的身份验证验证最终用户的身份,并以可互操作和类似 REST 的方式获取有关最终​​用户的基本配置文件信息。

虽然用户身份验证可以让 API 服务器知道在使用 API,但它不能保证请求源自所期望的,即移动应用程序的原始版本。

现在我们需要一种方法来识别是什么在调用 API 服务器,而这里的事情变得比大多数开发人员想象的要复杂得多。什么是向 API 服务器发出请求的东西。它真的是移动应用程序的真实实例,还是机器人、自动脚本或攻击者使用 Postman 之类的工具手动探索 API 服务器?

令您惊讶的是,您最终可能会发现它可能是使用重新打包的移动应用程序版本或试图游戏化并利用应用程序提供的服务的自动化脚本的合法用户之一。

上面的文章摘自我写的一篇文章,题为为什么您的移动应用程序需要 API 密钥?,您可以在此处完整阅读,这是有关 API 密钥的系列文章中的第一篇。

移动应用证明

使用移动应用程序证明解决方案将使 API 服务器能够了解发送请求的内容,从而允许仅响应来自真正移动应用程序的请求,同时拒绝来自不安全来源的所有其他请求。

移动应用程序证明服务的作用是在运行时通过在后台运行 SDK 来保证您的移动应用程序没有被篡改或没有在有根设备中运行,该 SDK 将与在云中运行的服务进行通信以证明移动应用程序和设备的完整性正在运行。

成功证明移动应用程序完整性后,会发布一个短期 JWT 令牌,并使用只有云中的 API 服务器和移动应用程序证明服务知道的秘密进行签名。如果移动应用程序证明失败,JWT 令牌会使用 API 服务器不知道的秘密进行签名。

现在,应用程序必须在每个 API 调用中发送请求标头中的 JWT 令牌。这将允许 API 服务器仅在可以验证 JWT 令牌中的签名和过期时间时服务请求,并在验证失败时拒绝它们。

一旦移动应用程序不知道移动应用程序证明服务使用的秘密,即使应用程序被篡改、在有根设备中运行或通过正中间人攻击的目标。

因此,该解决方案适用于没有误报的正检测模型,因此不会阻止合法用户,同时阻止坏人。

移动应用证明服务已经作为Approov(我在这里工作)的 SAAS 解决方案存在,它为多个平台提供 SDK,包括 iOS、Android、React Native 等。集成还需要对 API 服务器代码进行小检查,以验证云服务发布的 JWT 令牌。此检查对于 API 服务器能够决定服务哪些请求和拒绝哪些请求是必要的。

结论

因此,我建议您切换到通过公钥固定证书,如果您想防止证书固定被绕过以及其他威胁,那么您应该设计自己的移动应用程序证明解决方案或使用准备好即插即用的解决方案玩。

所以最后,为了保护您的移动应用程序和 API 服务器,必须根据您要保护的内容的价值和该类型数据的法律要求来选择使用的解决方案,例如欧洲的 GDPR 法规.

你想加倍努力吗?

OWASP 移动安全项目 - 十大风险

OWASP 移动安全项目是一个集中资源,旨在为开发人员和安全团队提供构建和维护安全移动应用程序所需的资源。通过该项目,我们的目标是对移动安全风险进行分类并提供开发控制以减少其影响或被利用的可能性。

于 2019-05-20T10:33:52.220 回答