从服务器端验证 android 应用程序的完整性

信息安全 安卓 电子签名 正直 木马 篡改
2021-08-31 08:53:26

我有连接到我的服务器并进行在线交易(通过 Internet/USSD/SMS)的 android 应用程序(移动银行),我想确保这些客户端没有被篡改并且是我分发的原始客户端。

请记住,并非我的所有客户都通过 google play 下载该应用程序,其中一些使用 3rd 方市场或从其他地方下载 apk。

有没有办法可以在服务器端验证应用程序的完整性(使用校验和或签名),以确保它没有被篡改。(例如没有在应用程序中植入木马然后重新分发)

对于建议的解决方案:

  • 它们是否可以在所有 3 个通信渠道(SMS/USSD/Internet)上实施,或者解决方案是否为一个/某些渠道专有?

(我正在寻找本页中提到的技术:https ://samsclass.info/android/chase.htm ):

Chase 的服务器在连接到他们的服务器时不会检查他们的 Android 应用程序的完整性。因此很容易修改应用程序,添加执行恶意操作的木马代码。可以诱骗人们使用木马应用程序的攻击者可以利用它们。

此漏洞不会影响使用 Google Play 商店正版应用程序的用户。它只会伤害那些被骗从网站、电子邮件等安装修改过的应用程序的人。

4个回答

使用安卓安全网这就是 Android Pay 自我验证的方式。

基本流程是:

  • 您的服务器会生成一个随机数并将其发送到客户端应用程序。
  • 该应用通过 Google Play 服务发送带有 nonce 的验证请求。
  • SafetyNet 验证本地设备未修改并通过CTS
  • Google 签名的响应(“证明”)会返回到您的应用,其中包含通过/失败结果以及有关您应用的 APK(哈希和签名证书)的信息。
  • 您的应用程序将证明发送到您的服务器。
  • 您的服务器验证 nonce 和 APK 签名,然后将证明提交到 Google 服务器进行验证。Google 检查证明签名并告诉您它是否真实。

如果通过了,您可以相当确信用户正在未修改的系统上运行您的应用程序的正版版本。该应用程序应在启动时获得一个证明,并将其与每个事务请求一起发送到您的服务器。

但是请注意,这意味着:

  • 已植根手机的用户将无法通过这些检查
  • 已安装自定义或第三方 ROM/固件/操作系统(例如 Cyanogen)的用户将无法通过这些检查
  • 无法访问 Google Play 服务的用户(例如亚马逊设备、中国人)将不会通过这些检查

...因此将无法使用您的应用程序。您的公司需要就这些限制(以及随之而来的不安用户)是否可以接受做出商业决策。

最后,意识到这不是一个完全密封的解决方案通过 root 访问权限和 Xposed,可以修改 SafetyNet 库以欺骗 Google 的服务器,告诉他们“正确”的答案以获得 Google 签署的验证通过结果。实际上,SafetyNet 只是移动了球门柱,让恶意行为者更难对付。由于这些检查最终必须在您无法控制的设备上运行,因此设计一个完全安全的系统确实是不可能的。

在此处阅读有关 SafetyNet 内部如何工作的出色分析。

服务器唯一可以可靠地确定设备的是它对服务器的行为(接收到的数据,以及在什么时间模式下)。假设攻击者了解并控制影响行为的所有元素,则攻击者可以创建恶意克隆,而服务器永远不会知道。

所以,从技术上讲,这是不可能的。除非您使用设备硬件的支持,否则整数 APK 文件足以创建恶意克隆(反编译很容易,proguard 对有经验的逆向工程师没有多大帮助)。

正如@CodesInChaos@OrenMilman在评论中提到的那样:

您可以在该行为中包含攻击者很难掌握的元素,例如 TPM/TEE 并实施远程证明。假设 TPM 没有漏洞(这不太可能,但我们只是假设)这确实是一个解决方案。此外,没有威胁模型,安全性毫无意义。因此,如果您的威胁模型排除了具有全职奉献精神、大量资金以及可能访问 0-day 的攻击者,您可以认为这种机制是安全的。
我不知道哪些 android 设备有 TPM 并支持这样的措施;我将把这项研究留给其他人修改这个答案。

我参加聚会有点晚了,但我想我可以添加一些有用的见解。

有没有办法可以在服务器端验证应用程序的完整性(使用校验和或签名),以确保它没有被篡改。(例如没有在应用程序中植入木马然后重新分发)

为了您的应用程序和 API 服务器之间的最终安全,您应该使用移动应用程序完整性证明服务以及 SafetyNet 解决方案 OAUTH2 服务。同样重要的是使用证书固定来保护 API 服务器和移动应用程序之间的通信通道,如本系列关于移动 API 技术的文章中所述。

移动应用程序完整性证明服务的作用是通过使用集成在您的应用程序中的 SDK 和在云中运行的服务来保证您的应用程序在运行时没有被篡改或没有在有根设备中运行。

成功证明应用程序完整性后,将颁发 JWT 令牌并使用只有您的应用程序的 API 服务器和云中的移动应用程序完整性证明服务知道的秘密进行签名。

如果 App Integrity Attestation 失败,JWT 会使用 API 服务器不知道的秘密进行签名。

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

一旦应用程序不知道移动应用程序完整性证明服务使用的秘密,即使应用程序被篡改、在有根设备中运行或通过作为中间人攻击的目标。这就是此类服务与 SafetyNet 解决方案相关的亮点所在。

您可以在 Approov 中找到这样的服务,该服务具有适用于包括 Android 在内的多个平台的 SDK。集成还需要对 API 服务器代码进行小检查,以验证 JWT 令牌,以保护自己免受欺诈性使用。

请记住,并非我的所有客户都通过 google play 下载该应用程序,其中一些使用 3rd 方市场或从其他地方下载 apk。

通过使用像Approov这样的移动 API 完整性证明服务,应用程序的安装位置无关紧要。

我有连接到我的服务器并进行在线交易(通过 Internet/USSD/SMS)的 android 应用程序(移动银行),我想确保这些客户端没有被篡改并且是我分发的原始客户端。

对于建议的解决方案:

它们是否可以在所有 3 个通信渠道(SMS/USSD/Internet)上实施,或者解决方案是否为一个/某些渠道专有?

因此,假设您的应用程序直接与第三方服务对话,那么我建议您将该责任委托给 API 服务器,这将防止代表您未经授权使用您的第三方服务,一旦它现在只提供来自移动设备的真实请求通过完整性挑战的应用程序。

安全网

SafetyNet Attestation API 可帮助您评估运行应用的 Android 环境的安全性和兼容性。您可以使用此 API 来分析已安装您的应用的设备。

OAUTH2

OAuth 2.0 授权框架使第三方应用程序能够通过编排资源所有者和 HTTP 服务之间的批准交互来代表资源所有者获得对 HTTP 服务的有限访问权限,或者通过允许第三方应用程序代表自己获得访问权。此规范替换并废弃了 RFC 5849 中描述的 OAuth 1.0 协议。

证书固定

固定是将主机与其预期的 X509 证书或公钥相关联的过程。一旦知道或看到主机的证书或公钥,证书或公钥就与主机相关联或“固定”到主机。如果可以接受多个证书或公钥,则程序会保存一个 pinset(取自 Jon Larimer 和 Kenny Root Google I/O talk)。在这种情况下,广告身份必须与 pinset 中的元素之一匹配。

智威汤逊令牌

基于令牌的身份验证

JSON Web 令牌是一种开放的行业标准 RFC 7519 方法,用于在两方之间安全地表示声明。

免责声明:我在 Approov 工作。

这个问题是手机游戏出于收入原因必须解决的问题,据我所知,他们通过不断更新应用程序来解决这个问题,要求用户每次在开始游戏之前下载并安装新的补丁。通常这是少量。这些补丁还为游戏添加了新内容。补丁程序还自行处理更新,因此如果修改了应用程序,补丁程序将失败。

所以理论上(不确定这有多准确),你基本上是在一个应用程序中编写一个应用程序。内部应用程序是完成繁重工作的应用程序。外部应用程序每次启动时都会下载一个补丁/完整性验证器,然后首先验证应用程序没有被篡改(通常通过校验和),然后在必要时修补内部应用程序。它类似于引导程序。

正如marstato所提到的,这仍然不是完美的。例如,攻击者可以将请求重定向到他们自己的服务器并以这种方式安装自定义补丁。一种可能的解决方法是在每个事务之前进行完整性验证,但这会相当慢。