【问题标题】:Protect your API KEYS from Reverse Engineering Android保护您的 API KEYS 免受 Android 逆向工程
【发布时间】:2017-10-06 23:39:33
【问题描述】:

我对 ProGuard 有点失望。 我正在使用 Gradle 隐藏我的 Google MAP API KEYS。我也在这里阅读了这个问题Manage Google Maps API Key with Gradle in Android Studio 并做了同样的事情。如果您遵循此问题中接受的答案,您的 api 密钥将不会被 ProGuard 混淆。问题是为什么? 有两个很好的答案。一个使用 ManifestPlaceHolder,一个使用 @string

不过,如果我反编译我的应用程序,仍然可以看到我的天气 api 密钥。 我正在使用private String myweatherapikey = BuildConfig.MY_API_WEATHER_KEY;,令人惊讶的是(以一种糟糕的方式)ProGuard 不会混淆这一点,即使在使用 Gradle 时也是如此。 当您进行逆向工程时,它看起来像private String myweatherapikey ="MY KEY IN PLAIN TEXT";

我一直在尝试混淆我的密钥,但没有任何效果,即使使用 Gradle。 你如何隐藏你的钥匙?当你反编译我的应用程序时,我所有的密钥都是公开的,这让我很恼火。

第二个问题:我认为隐藏你的 google maps api 密钥是不可能的。有 2 个键,一个用于发布版本,一个用于调试版本。它们都存储在 src/debug 和 src/release 中。你不能隐藏这个,对吧?

【问题讨论】:

  • “ProGuard 不会混淆这一点真是太神奇了(以一种糟糕的方式)”——请指出,在 Android 文档或 ProGuard 文档中,它说资源或字符串加密是 ProGuard 功能.
  • @CommonsWare 我知道。但它不起作用。我通过使用 Gradle 来使用最高的“安全性”。没有什么可以做的了(有吗?!)我不明白private String myweatherapikey = BuildConfig.MY_API_WEATHER_KEY; 是如何不被混淆的。
  • “但它不起作用”——那是因为它不是 ProGuard 的功能。 “没有什么可以做的了(有吗?!)”——就 Maps V2 API 密钥而言,任何人都无法使用它,所以我不确定你为什么担心。就个人而言,我认为第三方 Web 服务是一个实现细节,因此尝试仅从服务器而不是客户端使用它们。也欢迎您关注 DexGuard(ProGuard 的增强商业版)及其竞争对手。
  • @CommonsWare 感谢您的建议。也许你可以通过告诉我一些事情来消除我的担忧。当我在 Google Developer Console 中生成我的 Google Maps Api Key 时,我添加了我的包名和 SHA-1 指纹。这个 api 密钥只属于这个唯一的 SHa-1 指纹和我的包名,对吗?就像,如果有人在他们的应用程序中使用我的谷歌地图 api 密钥,它将无法工作,因为他没有相同的 sha-1 指纹。我的逻辑对吗?
  • "这个 api 密钥只属于这个唯一的 SHa-1 指纹和我的包名,对吗?" - 正确的。 “比如,如果有人在他们的应用程序中使用我的 google map api 密钥,它将无法正常工作,因为他没有相同的 sha-1 指纹。” - 正确的。我不知道任何人都可以使用该 API 密钥做任何事情。

标签: android proguard


【解决方案1】:

混淆

您的 api 密钥不会被 ProGuard 混淆

如果 Proguard 或任何其他工具对 API 密钥进行了混淆处理,那么它也需要在运行时进行去混淆处理,否则您将无法使用它。

无论您是否有混淆机制甚至加密机制,攻击者只需要在运行时将检测框架(如 Frida)挂钩到在去混淆或解密后返回 API 的代码.

Frida:

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

攻击者的另一种方法是在他控制或能够入侵的设备中执行中间人攻击,并拦截移动应用程序和后端之间的所有请求,以便从标头中提取 API 密钥,您可以阅读我的文章Steal that API Key with a Man in the Midlle Attack 了解如何做到这一点:

因此,在本文中,您将学习如何设置和运行中间人攻击,以拦截您控制的移动设备中的 https 流量,从而窃取 API 密钥。最后,您将了解如何缓解中间人攻击。

是的,它是公开的

我一直在尝试混淆我的密钥,但没有任何效果,即使使用 Gradle。你如何隐藏你的钥匙?当你反编译我的应用程序时,我所有的密钥都是公开的,这让我很恼火。

从您将移动应用发布到 Google、Apple 商店或任何其他商店的那一刻起,就可以下载二进制文件并对其进行逆向工程,因此其中的任何内容都必须被视为属于公共领域,无论是机密文件还是只是代码。

隐藏 API 密钥并对其进行逆向工程的技术

我最喜欢的移动应用二进制逆向工具是MobSF

移动安全框架 (MobSF) 是一种自动化的一体化移动应用程序 (Android/iOS/Windows) 渗透测试、恶意软件分析和安全评估框架,能够执行静态和动态分析。

您可以阅读我的文章How to Extract an API key from a Mobile App with Static Binary Analysis 以了解这是如何完成的,同时了解用于尝试隐藏 API 密钥的几种技术,并了解如何轻松绕过它们:

在本文中,我们将使用 Android Hide Secrets 研究存储库,它是一个使用多种不同技术隐藏 API 密钥的虚拟移动应用。

是时候寻找一种更高级的技术来隐藏 API 密钥了,这种技术很难从 APK 进行逆向工程,为此我们将使用原生 C++ 代码来存储 API 密钥,通过利用在底层使用 NDK 的 JNI 接口。

谷歌地图 API 密钥

第二个问题:我认为隐藏您的 google maps api 密钥是不可能的。有 2 个键,一个用于发布版本,一个用于调试版本。它们都存储在 src/debug 和 src/release 中。你不能隐藏这个,对吧?

如果您已经阅读了我在上面发布的所有链接,那么现在您可能已经意识到在您的移动应用程序的二进制文件中隐藏任何秘密确实是一个不可能的任务

底线是,如果它在二进制文件中,则可以通过静态分析或在运行时提取。

我不太熟悉移动应用程序中的谷歌地图使用,因此我不知道是否可以将调用它移动到后端,因为这是使用 Third 时必须完成的操作移动应用程序中的派对 API,否则 API 密钥很容易被提取和滥用,如果您基于它进行计费或费率限制,那么当攻击者获得您的 API 密钥时,您可能会遇到麻烦。

第三方 API

目前您使用第三方 API 会将您的移动应用置于此位置:

但最好是您的移动应用应位于此位置:

虽然我在图中提到了反向代理,但它可能是您的移动应用程序的后端。

注意:图片属于我目前正在撰写的一篇关于使用反向代理访问第三方 API 的文章。

将 API 密钥的访问权限委托给我们控制的反向代理或后端时,保护 API 密钥以访问第三方 API 会容易得多,这种方法的直接优势是第三方服务的 API 密钥是不再属于公共领域,也就是您的移动应用程序的二进制文件。

因此,从图中我们只剩下一个 API 密钥需要保护,一个用于访问您的反向代理或后端的密钥,您可以在其中采用尽可能多的安全措施来防止未经授权的访问。

可能的解决方案

你如何隐藏你的钥匙?

在您的移动应用程序中根本没有隐藏任何密钥会更好,因为这将是理想的解决方案。所以上图看起来更像:

要处于不需要在移动应用中传送任何机密的位置,您需要求助于移动应用证明概念,我将从this article section 提取相关位,解释它的作用:

在深入了解移动应用证明服务的角色之前,我们首先需要了解什么 访问 API 服务器之间的区别。这在this article 中有更详细的讨论,我们可以在其中阅读:

what 是向 API 服务器发出请求的事物。它真的是您的移动应用程序的真实实例,还是机器人、自动脚本或攻击者使用 Postman 之类的工具手动绕过您的 API 服务器?

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

移动应用证明服务的作用是验证发送请求的什么,因此只响应来自真正移动应用实例的请求并拒绝来自未经授权来源的所有其他请求。

为了了解什么将请求发送到 API 服务器,移动应用证明服务在运行时将高度确定您的移动应用存在,但尚未被篡改/重新打包,没有在有根设备中运行,没有被检测框架(Frida、xPosed、Cydia 等)挂钩,并且不是Man in the Middle Attack (MitM) 的对象。这是通过在后台运行 SDK 来实现的,该 SDK 将与在云中运行的服务进行通信,以证明移动应用程序和运行它的设备的完整性。

成功证明移动应用程序的完整性后,会发出一个短时间的JWT token,并使用只有云中的 API 服务器和移动应用程序证明服务知道的秘密进行签名。在证明失败的情况下,JWT 令牌使用不正确的密钥进行签名。由于移动应用程序不知道移动应用程序证明服务使用的秘密,因此即使应用程序已被篡改、在根设备中运行或通过连接进行通信,也无法在运行时对其进行逆向工程这是 MitM 攻击的目标。

移动应用必须在每个 API 请求的标头中发送 JWT 令牌。这允许 API 服务器仅在可以验证 JWT 令牌已使用共享密钥签名并且尚未过期时才提供请求。所有其他请求将被拒绝。换句话说,一个有效的 JWT 令牌告诉 API 服务器 什么 发出的请求是上传到 Google 或 Apple 商店的正版移动应用,而一个无效或缺失的 JWT 令牌意味着 什么 发出的请求未经授权,因为它可能是机器人、重新打包的应用程序或进行中间人攻击的攻击者。

使用移动应用证明服务的一大好处是其主动和积极的身份验证模型,它不会产生误报,因此不会阻止合法用户,同时阻止坏人。

Mobile App Attestation 将您的移动应用程序解放出来,使其代码中嵌入机密,而现在它只需要传递给反向代理或后端它从 Attestation 接收到的 JWT 令牌。现在,反向代理或后端可以验证 JWT 令牌,并且在成功验证后,他们可以非常自信地满足请求,这些请求来自他们期望的what,一个真正的移动应用实例,具有不公开 API 密钥以访问您的第三方服务的额外好处。

加倍努力

忍不住推荐OWASP - Mobile Security Testing Guide中的优秀作品:

移动安全测试指南 (MSTG) 是一本针对移动应用安全开发、测试和逆向工程的综合手册。

【讨论】:

  • 如果通过https通信,中间人攻击还可以吗?
  • 是的,并且在攻击者控制的设备中很容易做到,看看我在this article 中是如何写的。也可以在公共 WiFi 中进行,只需在谷歌搜索 wifi hacking with pineapple
猜你喜欢
  • 2017-09-21
  • 1970-01-01
  • 2020-05-02
  • 2017-05-28
  • 2016-12-15
  • 2019-10-11
  • 2018-06-22
  • 2011-11-18
  • 2021-02-08
相关资源
最近更新 更多