基于浏览器的 xmlhttp/js/perl/php 游戏的作弊预防

发布于 2024-08-11 19:52:21 字数 343 浏览 7 评论 0原文

假设在一个基于浏览器的游戏中,完成一些操作(为简单起见,假设有人点击了一个将分数增加 100 的链接),点击此链接,该链接将有一个 url,例如 increase_score.pl?amount=100 对于某人简单地向网络服务器发送请求来执行此命令有什么预防措施:

  1. 一遍又一遍地重复而不实际执行单击链接的任务并向
  2. 设置金额的服务器发送虚假请求到像 100000 这样的限制。

我知道检查 HTTP_REFERER 但我知道人们可以绕过它(不确定具体如何),除了对第二个选项进行一些边界检查之外,我有点困惑。有人遇到过类似的问题吗?解决方案?

Lets say that in a browser based game, completing some action (for simplicity lets say someone clicks on a link that increases their score by 100) clicking on this link which would have a url for example increase_score.pl?amount=100 what kind of prevention is there from someone simply sending requests to the web server to execute this command:

  1. Over and over again without actually doing the task of clicking on the link and
  2. Sending a false request to the server where amount is set to something rediculus like 100000.

I am aware of checking HTTP_REFERER however I know people can get around that (not sure how exactly) and other than some bounds checking for the 2nd option I'm kind of stumped. Anyone ever experience similar problems? Solutions?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

明月松间行 2024-08-18 19:52:22

如果您按照您的建议实现游戏,那么没有什么可以阻止他们这样做。

您需要在服务器上实现游戏逻辑,并仅在服务器验证操作后才分配分数。

例如:在 SO 上,当有人对您的问题进行投票时,这不会作为提高您声誉的命令发送。网络应用程序只是告诉服务器用户 X 对问题 Y 投了赞成票。然后,服务器验证数据并在一切正常的情况下分配分数。 (并不是说SO是游戏,但所需的逻辑是相似的。)

Nothing can stop them from doing this if you implement your game how you propose.

You need to implement game logic on the server and assign points only once the server validates the action.

For example: on SO when someone votes your question up, this isn't sent as a command to increase your reputation. The web-app just says to the server user X voted question Y up. The server then validates the data and assigns the points if everything checks out. (Not to say SO is a game, but the logic required is similar.)

浮生面具三千个 2024-08-18 19:52:22

简短版本:你不能。您从客户端(浏览器)获得的每条数据都可以被知道自己在做什么的人手动欺骗。

您需要从根本上重新思考应用程序的结构。您需要以这样的方式对应用程序的服务器端进行编码,使其将来自客户端的每一条数据视为一组肮脏的谎言,直到它能够向自己证明这些数据实际上是可信的。您需要避免给服务器一种“如果客户端告诉我这样做,显然允许告诉我这样做”的心态。

错误的方式:
客户:玩家史蒂夫说要给玩家史蒂夫一亿分。
服务员:好的!

正确的方法:
客户:玩家史蒂夫说要给玩家史蒂夫一亿分。
服务器:好吧,让我先检查一下史蒂夫玩家此时此刻是否允许给自己提供无数的积分……啊。他不是。请向玩家史蒂夫展示这条“去 Fsck Yourself,骗子”消息。

至于告诉谁登录了,这是一个简单的问题,向客户端提供一个 cookie,其中包含您在服务器上跟踪的该死的几乎不可能猜测的值 - 但我假设您知道如何处理与会话管理。 :-) (如果您不这样做,Google 正在等待。)

Short version: you can't. Every piece of data you get from the client (browser) can be manually spoofed by somebody who knows what they're doing.

You need to fundamentally re-think how the application is structured. You need to code the server side of the app in such a way that it treats every piece of data coming from the client as a pack of filthy filthy lies until it can prove to itself that the data is, in fact, plausible. You need to avoid giving the server a mindset of "If the client tells me to do this, clearly it was allowed to tell me to do this."

WRONG WAY:
Client: Player Steve says to give Player Steve one gazillion points.
Server: Okay!

RIGHT WAY:
Client: Player Steve says to give Player Steve one gazillion points.
Server: Well, let me first check to see if Player Steve is, at this moment in time, allowed to give himself one gazillion points ... ah. He isn't. Please display this "Go Fsck Yourself, Cheater" message to Player Steve.

As for telling who's logged-in, that's a simple matter of handing the client a cookie with a damn-near-impossible-to-guess value that you keep track of on the server -- but I'll assume you know how to deal with session management. :-) (And if you don't, Google awaits.)

ゞ记忆︶ㄣ 2024-08-18 19:52:22

游戏(应用程序)的逻辑应该基于不信任来自用户的任何内容的规则。

HTTP_REFERER 可以被任何 Web 客户端欺骗。

The logic of the game (application) should be based on the rule to not trust anything that comes from the user.

HTTP_REFERER can be spoofed with any web client.

泅渡 2024-08-18 19:52:22

带有 cookie/会话的令牌。

Token with cookie/session.

江南月 2024-08-18 19:52:22

您可以使链接动态化,并在其末尾更改哈希值。验证该哈希值在给定的时间段内是否正确。

根据您允许点击的频率,其复杂程度会有所不同。

You could make the link dynamic and have a hash that changed at the end of it. Verify that the hash is correct given that period of time.

This would vary in complexity depending on how often you allowed clicks.

把昨日还给我 2024-08-18 19:52:22

这里有几点需要注意。

首先,您的服务器对此类内容的请求应该是 POST,而不是 GET。只有 GET 请求才应该是幂等的,不这样做实际上违反了 HTTP规范

其次,您在这里看到的是经典的客户信任问题。您必须信任客户端将分数或其他游戏间隔信息发送到服务器,但您希望客户端发送非法数据。防止不允许的操作很容易,但防止允许的操作中的犯规数据则要困难得多。

Ben S 就如何设计这样的客户端和服务器之间的通信协议提出了很好的观点。允许点值作为可信数据发送通常是一个坏主意。最好指示发生了某个操作,并让服务器确定应该分配多少分(如果有的话)。但有时你无法回避这一点。考虑赛车游戏的场景。客户端必须发送用户的时间,并且不能将其抽象到诸如“completedLevelFour”之类的其他调用中。那你现在做什么?

艾哈迈德和迪恩建议的象征性方法是合理的 - 但它并不完美。首先,令牌仍然必须传输到客户端,这意味着它可以被潜在攻击者发现并可能被恶意使用。另外,如果你的游戏 API 需要无状态怎么办?这意味着基于会话的令牌身份验证已经过时。现在您将深入了解客户信任问题的最深处。

您几乎无法做到 100% 万无一失。但你可以让作弊变得非常不方便。考虑 Facebook 的安全模型(每个 API 请求都经过签名)。这非常好,需要攻击者真正深入研究您的客户端代码,然后才能弄清楚如何欺骗请求。

另一种方法是服务器重播。就像赛车游戏一样,不仅仅是将“时间”值发送到服务器,还设置检查点来记录时间并将其全部发送。为每个间隔建立实际的最小值,并在服务器上验证所有这些数据是否在既定的范围内。

祝你好运!

A few things to note here.

First, your server requests for something like this should be POST, not GET. Only GET requests should be idempotent, and not doing so is actually a violation of the HTTP specification.

Secondly, what you're looking at here is the classic Client Trust Problem. You have to trust the client to send scores or other game-interval information to the server, but you don't want the client to send illegitimate data. Preventing disallowed actions is easy - but preventing foul-play data in an allowed action is much more problematic.

Ben S makes a great point about how you design the communication protocols between a client and a server like this. Allowing point values to be sent as trusted data is generally going to be a bad idea. It's preferable to indicate that an action took place, and let the server figoure out how many points should be assigned, if at all. But sometimes you can't get around that. Consider the scenario of a racing game. The client has to send the user's time and it can't be abstracted away into some other call like "completedLevelFour". So what do you do now?

The token approach that Ahmet and Dean suggest is sound - but it's not perfect. Firstly, the token still has to be transmitted to the client, which means it's discoverable by the potential attacker and could be used maliciously. Also, what if your game API needs to be stateless? That means session-based token authentication is out. And now you get into the deep, dark bowels of the Client Trust Problem.

There's very little you can do make it 100% foolproof. But you can make it very inconvenient to cheat. Consider Facebook's security model (every API request is signed). This is pretty good and requires the attacker to actually dig into your client side code before they can figure out how to spoof a reqeust.

Another approach is server replay. Like for a racing game, instead of just having a "time" value sent to the server, have checkpoints that also record time and send them all. Establish realistic minimums for each interval and verify on the server that all this data is within the established bounds.

Good luck!

未蓝澄海的烟 2024-08-18 19:52:22

听起来您的游戏的一个组件需要请求限制。基本上,您跟踪特定客户访问您网站的速度,当该客户的速度超过您认为合理的速度时,您开始减慢对该客户的响应速度。它有不同的级别,从低级别的 IP 过滤器开始,一直到您在 Web 服务器中处理的内容。例如,Stackoverflow 在 Web 应用程序中有一个功能,可以捕获它认为太多、太接近的编辑内容。它会将您重定向到验证码,如果您想继续,您需要响应该验证码。

至于其他位,您应该验证所有输入,不仅要验证其形式(例如,它是一个数字),还要验证该值是否合理(例如,小于 100,或其他)。如果你发现客户做了一些有趣的事情,请记住这一点。如果您发现同一客户经常做一些有趣的事情,您可以禁止该客户。

It sounds like one component of your game would need request throttling. Basically, you keep track of how fast a particular client is accessing your site and you start to slow down your responses to that client when their rate exceeds what you think is reasonable. There are various levels of that, starting at the low-level IP filters up to something you handle in the web server. For instance, Stackoverflow has a bit in the web application that catches what it thinks are too many edits too close together. It redirects you to a captcha that you need to respond to if you want to continue.

As for the other bits, you should validate all input not just for its form (e.g. it's a number) but also that the value is reasonable (e.g. less than 100, or whatever). If you catch a client doing something funny, remember that. If you catch the same client doing something funny often, you can ban that client.

吲‖鸣 2024-08-18 19:52:22

扩展艾哈迈德的响应,每次加载页面时,都会生成一个随机密钥。将密钥存储在用户会话中。将随机密钥添加到每个链接,以便获得这 100 点的新链接是:

increase_score.pl?amount=100&token=AF32Z90

单击每个链接时,检查以确保令牌与会话中的令牌匹配,然后创建一个新密钥并将其存储在会议。他们每次提出请求时都会获得一个新的随机密钥。

如果他们给你错误的密钥,他们会尝试重新加载页面。

Expanding on Ahmet's response, every time they load a page, generate a random key. Store the key in the user session. Add the random key to every link, so that the new link to get those 100 points is:

increase_score.pl?amount=100&token=AF32Z90

When every link is clicked, check to make sure the token matches the one in the session, and then make a new key and store it in the session. One new random key for every time they make a request.

If they give you the wrong key, they're trying to reload a page.

我最亲爱的 2024-08-18 19:52:22

我建议为每个操作创建一个特定的 URL。大致如下:

/score/link_88_clicked/
/score/link_69_clicked/
/score/link_42_clicked/

每个链接都可以做两件事:

  1. 在会话中标记该链接已被单击,以便它不会再次跟踪该链接。
  2. 添加到他们的分数中。

I would suggest making a URL specific to each action. Something along the lines of:

/score/link_88_clicked/
/score/link_69_clicked/
/score/link_42_clicked/

Each of these links can do two things:

  1. Mark in the session that the link has been clicked so that it wont track that link again.
  2. Add to their score.
如痴如狂 2024-08-18 19:52:22

如果您希望游戏仅在您的服务器上运行,您还可以在接收技巧中检测信号的发送位置,并忽略任何不是来自您的域的信号。如果您必须从专用域运行来提交分数,那么篡改您的代码将是一件非常痛苦的事情。

这也阻止了 CheatEngine 的大部分技巧。

If you want the game to only run on your server, you can also detect where the signal is sent from in your recieving trick, and ignore anything not coming from your domain. It will be a real pain to tamper with your codes, if you have to run from your dedicated domain to submit scores.

This also blocks out most of CheatEngine's tricks.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文