I’ve been increasingly enjoying working in web development. It’s not my area and I’m far from being an expert but lately I’ve been dealing with a lot of web-related technologies and let’s just say it has had quite an effect on me. For that reason, I’ve been trying to learn more on this subject and, in particular, on the more recent standards of web development such as HTML5.
- imagine a small area where you have a bunch of balls moving around very slowly;
- you then have the chance to choose just one ball to trigger a chain reaction of explosions in an attempt to destroy as many balls as possible;
- each level has a different ratio of the number of balls on the area and the number of balls you have to destroy to go through to the next level
- there are 42 levels
Wanna try it? Go ahead, it’s here. But be sure to come back and read the rest of the story, you might learn something 🙂
As it turned out, the challenge was not actually implementing the game engine and the visual aspects, since I was able to do that quite quickly on a Saturday morning. The real problem was the Leaderboard.
As naive as I am, I decided to implement a simple PHP/MySQL backend that would receive the scores from the web page and would insert them in the database, which would in turn serve as the source of the Leaderboard that you now see at the game.
By now, if you’re a web developer, you’ve probably discovered my n00b error: trusting the information that comes from the browser. Good thing I didn’t release the web site like this to the public… well, the general public, anyway. I just sent the link to a few friends that were quite happy with the game logic and to provide an endless list of bugs (yes, web programming is all about finding the solutions that work accross all browsers and operating systems).
Among those friends, there were some with enough web-related knowledge to be able to discover the score uploading method and data structure to upload their own scores manually without even playing the game. Needless to say, the Leaderboard was rendered useless just after a few minutes of releasing the game to those “friends” 🙂
The solution is quite obvious: implement whatever you want on the browser but make sure the server doesn’t trust anything that comes out of it. However, this seldom leads to desirable solutions.
Basically, instead of sending the scores directly from the browser to the server, the browser now sends the parameters of the game, namely: the ball that the user clicked (the coordinates actually); the instant in which the user clicked the ball; the level played; a random token that is generated on each page-load and the score obtained on the browser side.
When receiving this information, the server is now ready to do the same as the browser did: simulate what would happen in that instant by clicking that ball. But since the server doesn’t have to visually display this info, it can perform the simulation quite quickly. The server then compares its result with the one sent by the browser and if they match, the score is uploaded to the Leaderboard, otherwise, it probably means that an hacker is trying to force his/her way into the Leaderboard and discards the info.
This has, evidently, some disadvantages. The more people play the game, the more simulations the server has to perform, which basically affects the server’s overall performance.
Moreover, this solution is not bullet-proof. One can still use this method to play the game manually and play a different level (like the last one) that the one he/she should’ve played. To avoid that, I decided to enforce some rules on the server-side: for example, one cannot play a level without having submitted a valid score for the previous level.
Nevertheless, no matter how many restrictions one implements, a trully-motivated hacker will always find a way to break through the restrictions. Or in this case, “implement someone” that will do that job for the hacker. Yes, I’m talking about implementing programs to play the game.
Someone (:P) decided to take this as a personal challenge and implement a bot that uses the brute-force approach to check every possible action in the game until a solution is found for each level. Basically, his bot tries to click on every ball on each instant and simulates the same behavior as the server’s, thus producing a solution for each level that, once submitted, the server will interpret as being valid and will upload to the Leaderboard.
In conclusion, this serves to show that it is quite difficult to actually implement something on the web that is totally bullet-proof towards hackers. But I don’t mind that this turned out this way, not at all. First of all, because this web site was just an experiment and there’s no actual value on the info that is being used on the Leaderboard. But if you’re implementing something that has actual value in it (like websites that deal with actual money transfers or similar), you may want to fully check your sites’ vulnerabilities. Second of all, it served to learn more about the challenges of implementing something on the Web.
And lastly, it also stird some ideas in my head and I’m already thinking about my next game. But that one will not be played by humans…well, not directly, anyway. It’ll be a game for bots only 🙂
Will you accept that challenge?