如何防止 Firebase 请求伪造?

How to protect against Firebase Request Forgery?

如果您在浏览器中使用 Firebase 实时数据库,则需要共享 API 密钥,因此无法保护数据库。我有一个保存游戏最高分的简单游戏(ASCII Tetris),问题是任何人都可以欺骗请求并发送自己的分数。 (这里是一个人所做的截图):

有什么解决方案可以防止这种情况发生?我正在考虑做与防止 CSRF 相同的事情,你创建一个令牌并验证它是否有效,这样只有我的代码才会有适当的 CSRF 之类的令牌。攻击者仍然可以在调试器中暂停应用程序并检查令牌并发送他自己的令牌,但这需要他知道如何使用调试器,因此破解起来会有点困难。

firebase 实时数据库有 ".validate" 规则,您可以在其中验证令牌是否有效 (https://firebase.google.com/docs/database/security)。我也在考虑创建类似校验和链的东西(比如 git 或区块链)。

你觉得这样的东西有可能创造出来吗?您知道对于我保存分数的情况是否有更好的方法来保护 firebase 实时数据库?对于这个简单的游戏,答案可能对其他情况有用,而不是像我这样的简单情况。

您可以在 Firebase 的安全规则中实现非常复杂的功能。例如,我曾经看到过验证国际象棋动作的规则 - 非常令人印象深刻。

大多数情况下,我建议存储足够的信息以重播发生的事情,以便您可以检查结果是否有效。我的第一个 Firebase 游戏是文字输入游戏,所以我会存储:

  • 游戏种子
  • 每个按键及其时间戳
  • 总分

这让我可以重玩游戏来检查我是否得到相同的结果。但它也允许我(在未来)编写代码来检查按键中的不规则模式。例如,我的机器人过去常常以非常特定的时间间隔按下一个键。当然,恶意用户可以很容易地使它变得更智能,但您也可以改进您的作弊检测代码。

这样的作弊检测代码当然不应该出现在客户端中,因为这会给恶意用户提供您不希望他们拥有的信息。因此,您会 运行 在受信任的环境中编写此代码,例如您的开发机器、您控制的服务器或 Cloud Functions。

所以我的典型步骤是:

  1. 存储用户的准确移动和 PRNG 的种子,以便您可以重现准确的游戏。
  2. 尽可能使用安全规则拒绝无效动作。
  3. 使用安全规则拒绝极不可能出现的结果,例如高于一定数量的分数(尤其是当您可以将其与游戏花费的时间联系起来时)。
  4. 使用服务器端代码检查玩家的移动是否导致他们得到的结果。
  5. 考虑隔离异常高的分数,这样您就可以在将它们发布到计分板上之前通过重播来验证它们。这将是客户端代码和服务器端安全规则的组合。
  6. 如果您怀疑滥用,请检查动作列表。如果这种情况经常发生,请开始自动化。

欢迎来到游戏开发者与恶意玩家的军备竞赛。 :)