如何验证 POST 数据是从具有正确 SHA1 签名的 Android 应用程序发送的?

How to verify POST data is sent from Android app with correct SHA1 signature?

最近我的游戏被黑了,一个用户向服务器提交了一个不可能的分数。提交的分数带有经过验证的校验和和正确的数据。

我确信用户必须对我的 APK 文件进行逆向工程才能找到 POST 请求。

现在我想知道什么是防止这种情况再次发生的好方法,我考虑验证应用程序的 SHA1 签名。也许这样我可以确保该应用程序是由我签名的,而不是该应用程序的逆向工程和更改版本。

这可能吗?或者会有更好的解决方案来解决这个问题吗?

顺便说一句,我正在使用LibGDX。

验证您的应用程序的完整性是不够的,因为请求可以很容易地在应用程序外部伪造或在内存中动态修改,使用有根 android 的环境。更重要的是,你无法完全避免它

这是您无法控制的机器中所有应用程序 运行 共有的问题(所有客户端应用程序)。您永远不能相信来自他们的数据。

据我所知,您有多种选择:

  1. 混淆代码并使应用更难被逆向工程。请注意,这并没有解决问题,而是将其最小化。
  2. 将处理移至服务器。服务器控制的游戏越多,您的应用就越不容易受到这种恶意行为的攻击。
  3. 自动检测不可能的分数并关闭他们的帐户

干杯,

如果你想验证你的应用程序的签名而不可能被破解,你将不得不上传整个 apk 并在服务器上进行检查。这不是一个可行的解决方案。

唯一安全的 android 应用是纯终端应用,这意味着您必须在服务器上进行所有计算。由于延迟,大多数情况下这是不可能的。

这就是为什么我们 Android 开发人员必须忍受这一点:应用程序并非 100% 安全。

但你可以靠近它。

您可能需要阅读 Security with HTTPS and SSL 安全通信指南。

此外,您还需要确保您的客户端难以破解:android app piracy prevention and Combating Android App Piracy: Xposed

在您的情况下,您还需要实施服务器端请求验证: 如果你有一个服务器端的游戏,用户可能有一个帐户。如果用户发送了一个明显不可能的分数,自动忽略请求并禁止用户(和他的 ip)。 (但也要记住,这永远不应该发生在有效请求上,否则用户可能会生气并停止游戏。)

首先,你真的必须混淆你的代码。您可以找到有关 ProGuard 和代码混淆的更多信息 here

其次,您可以使用 GooglePlay 服务中提供的 GoogleAuthUtil,它适用于 运行 Android 2.2 或更高版本的设备。

GoogleAuthUtil 可以满足您的需求:

您的客户端服务器调用通过 HTTPS 请求转到 Google,Google 检查调用是否由使用您的发布证书签名的应用程序发出,然后将请求发送到你的服务器。

你可以找到关于如何实现这个的官方教程here and official documentation here

干杯!

1) 例如使用 code obfuscation。混淆器。这种工具不仅适用于 Java。 但要小心 - 混淆代码可能运行缓慢或包含其他错误。

2) 添加 App Licencing 检查(这将使用 Google Play 检查应用程序签名):

关注观看此视频: https://www.youtube.com/watch?v=TnSNCXR9fbY 我记得 他提到 运行 时使用的技术来验证您的应用程序没有被黑客入侵或修改 (邮编检查等)。

3) 确保您的 app/server 仅使用 现代密码套件 的安全连接 (SSL/TLS)。这将减轻降级攻击。

您可以使用此生成器为您的服务器构建带有现代密码套件的配置: https://mozilla.github.io/server-side-tls/ssl-config-generator/

您还可以在客户端使用证书固定 - 这将减轻权限攻击。

不要使用纯 HTTP 连接。

4) 使用某种请求签名(就像 Amazon AWS 那样) 您可以从他们的文档中获得核心思想。 http://docs.aws.amazon.com/general/latest/gr/sigv4_signing.html

另外 this article 应该会有帮助。

5) 通过添加 运行 时间检查,禁止在 ROOT 设备上使用您的应用程序。由于根 phone 更容易破解或分析您的应用程序。

6) 您可以通过在您的在线游戏中添加一些禁止系统来减少欺诈 - 如果有人入侵您的应用程序并将错误数据发送到您的服务器 => 将此用户添加到服务器端的禁止列表(通过 IP 或用户)身份证等)。可能将用户临时添加到此列表(例如 24 小时,7 天)

7) + 如果您使用 Json/XML 作为网络层的数据格式,请尝试使用像 Protocol Buffers 这样的二进制格式。二进制序列化格式更高效且难以逆向工程。

您可以更好地混淆您的代码并使用一些非常混淆的秘密来签署您的请求。这样您就可以提高安全性。

但是,如果您的所有游戏 运行 都在客户端中,则它不能完全安全。因为不管你用什么来签名,如果你在客户端做这意味着你在客户端有秘密或私钥,然后它就可以被黑客攻击。

为了使其更安全,您需要在服务器中加入一些游戏逻辑,然后在该逻辑中控制用户没有作弊。