【问题标题】:how to secure an HTTPs trigger function that increment user's balances from hackers如何保护 HTTPs 触发功能,增加黑客的用户余额
【发布时间】:2018-09-27 08:22:01
【问题描述】:

我在android上有一个简单的游戏,在完成游戏回合后调用了一个HTTPS firebase cloud函数来增加玩家的余额,问题我有一些黑客经常调用这个函数来增加他们的奖励,我该如何保护这个功能被滥用了吗?我可以在客户端实现的任何逻辑吗?

// this is a simple function that increases the player's balance after the game.

const MAX_REWARD = 1000;            

  exports.GameFinish = functions.https.onRequest((req, res) => {

        if (!req.headers.authorization) {
         console.error('No Firebase ID token was passed');
         res.status(403).send('Unauthorized');
         return;
         }


        res.contentType("application/json");


        if (req.query.userID) {
            userid = req.query.userID;
        }
        else {
            return res.status(404).json({'msg': 'Error', balance: 0, errors: 'no user ID was supplied'});    
        }


        if (!req.query.award) {
            return res.status(404).json({'msg': 'Error', balance: 0, errors: 'no award was supplied'});  
        }



        var award_amount = parseInt(req.query.award);

        if( award_amount > MAX_REWARD)
        {
            console.log('rewards exceeding the max limit!', result);
            award_amount = MAX_REWARD;          
        }



        admin.auth().verifyIdToken(req.headers.authorization).then(decodedIdToken => {
            return checkUserExists(userid).then((userinfo) => {
                if(userinfo != null)
                {


                var ref_prize = admin.database().ref("/game/${userid}/total_prize");
                        ref_prize.transaction(function(totalPrize) {
                        return totalPrize + award_amount;
                        });
                }
                else 
                    // error user is not in the record
                    res.status(200).json({'msg': 'Error', balance: 0, errors:  'no such a user exists'}); 

                });

        }).catch(error => {
        console.error('Error while verifying Firebase ID token:', error);
        res.status(403).send('Unauthorized'); });   

    });

【问题讨论】:

  • 不应该在内部更新余额作为在同一交易中完成游戏回合的一部分吗?我的意思是为什么要将余额更新 API 暴露给外部世界。如果必须公开,是否应该有一些同步或异步机制来验证用户的操作是否值得更新余额。例如可能余额更新 API 需要提供游戏实例 id,如果 api 逻辑发现游戏实例 id 已经有更新,或者游戏实例 id 甚至没有玩过,则游戏实例 id 会在那里过期不会有任何更新

标签: javascript firebase firebase-realtime-database firebase-authentication google-cloud-functions


【解决方案1】:

这种类型的滥用在游戏中相当普遍。您需要通过实施任何或所有这些来防止它:

  1. 输入已完成游戏的 ID,并验证每个已完成游戏对每个玩家只能计算一次。这是迄今为止最有效的改进,因为它使不玩游戏就无法提高分数。
  2. 仅在响应中返回基本错误消息,并依赖日志记录来解决实际问题。这意味着攻击者将很难通过检查错误来确定您的代码是如何工作的。
  3. 传递有关已完成游戏的游戏玩法的信息,验证这是一组有效的动作,并确定服务器上的奖励。所以让玩家说“我赢了这么多点”,让他们说“我做了这些动作”。然后,您的函数确定这些移动之后的游戏状态,并确定获胜者和奖励。请注意,您可能已经在游戏过程中记录了数据库中的动作,在这种情况下,您只需要玩家传入游戏 ID。
  4. 一般来说,记录移动是一种能够分析它们以检测错误游戏的好方法。即使您今天不进行此分析,但有了这些动作,以后也可以进行此分析(如果需要)。

所有这些都必须在服务器中实现,例如在 Cloud Functions 或 Firebase 的服务器端安全规则中。根据定义,不能信任客户端运行您的代码。

这些做法可能还有很多,但这些是这里首先想到的。

顺便说一句:恭喜你的游戏成功到足以让玩家尝试破解它! :-)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-06-19
    • 1970-01-01
    • 1970-01-01
    • 2020-09-30
    • 1970-01-01
    • 1970-01-01
    • 2018-08-06
    相关资源
    最近更新 更多