It’s very easy to hack AJAX requests
Construct 2 allows to communicate with server side scripts by using AJAX. It’s very easy to use and it’s the most popular way to store and fetch game data over which we want to have control. The problem is that AJAX request is nothing else than a simple URL trigger. We can send data with GET or POST but still it’s just a URL request and can be viewed using simple tools by anyone with basic knowledge of WWW technology.
In this tutorial we assume that we use PHP and MySQL for our server side app as it is the most popular choise.
How to hack AJAX request?
Assuming that by “hack” we understand unintended use (in the meaning that we didn’t plan it to be used like that), it’s is as simple as just lookup the AJAX call URL and then trigger it (even by simply opening the URL in the browser).
By default AJAX calls are quite secure as they are not allowed to be cross-domain calls. However if we have a mobile game which needs an AJAX connection with our server, we have no choice – we need to allow cross-domain calls. Otherwise our app won’t be able to connect to our server. From this moment we are in danger.
A quick example.
Let’s say players can register an account via the app. Once they put credentials, the following AJAX call is triggered: http://www.myserver.com/api.php?action=register&username=John&pass=123123123
Once this URL is spotted by a “hacker” he can run this URL with a browser or cURL etc. to create dummy users. He just needs to change params values. It seems harmless right? Well imagine that he runs it in the loop with random data and create millions of dummy users. Your database will get polluted and heavy. A bit smarter hacker could even delete your database entries with SQL Injection tricks.
How to protect our games then?
There are really a lot of ways to do it an most of them depends on your calls, game architecture etc. But let’s talk about some basics.
First of all you should protect what is the most valuable for you – the database. If you are not experienced in building server side apps then avoid building database managament API by yourself and use some ORM frameworks/libs instead. In fact even advanced coders use prepared ORM tools. There is no point to do it by yourself. Using common libraries is simply much more comfortable.
Popular database libraries/PHP frameworks have SQL Injection protection already implemented so you don’t have to worry about that yourself. I don’t really want to point any library as the best one because it really depends what you do. If you build something big on your server side then I suggest to use some popular PHP framework (you can Google them easily). But if you just have a simple save/load actions on your server side script then pick something light-weight. Here is some light-weight lib I’ve been using recently: Medoo.
Now second thing we should do is to validate if the AJAX request is comming from our application or not. To do it we can add one extra parameter to our request. We cannot simply add something like “&comming_from=myGame”, because it’s a static data and hacker can simply send it as well. Our security parameter must be dynamic. Must be different for every call.
Let’s call it an API_KEY. The goal is to send a dynamically generated API_KEY which can be understandable only for our server-side script.
First create a constant which will be our SALT. It means that it will be used to hash the API_KEY “even more”. SALT is nothing else than a string.
Now to generate our API_KEY we will hash a mix of our SALT and something which is different for each call. For registration call it can be a password or username (or both).
As you can see we use SHA1 hashing algorithm here. SHA1 is a great choise for such things because it’s a one way hash algorithm which means there is no way to decode it.
Finally we add our API_KEY to the call as a ragular parameter.
On your server side you basically do exactly the same thing. You need to create a SALT constant (with exactly the same value) and generate an API_KEY in the exactly same way. Now once we have API_KEYs generated on both sides we simply need to compare them against each other. If both keys are equal then we are sure that the call has been generated by our app. Otherwise we stop the script and don’t do any further actions.
Here is a sample PHP comparison function. Please note that in this example $salt parameter is the one which is not constant (for instance username). Our constant is hardcoded inside T::getApiKey() function.
That’s it. Not very fancy and not complex but does the job!
This tutorial covers just a simple example to give you the idea of how api salt system works. Ideally you may want to make it much more complex by using function for fetching the salt or using multi salt or combining the final salt from various pieces in various places, etc. Digging in minified JS to crack it is much harder then. Actually there’s a planty of ways to improve it, depends how seriously you think about security. And after all if security is a serious point in your project you obviously would like to use SSL.
Still even though this tutorial covers the very basic example it does the job. I mean it will probably not secure you from someone who is quite experienced hacker/developer, but it helps to get rid of kids who simply sniffing the network traffic and play with the URL variables (various bots do that as well). So yes, it’s not perfect but for simple projects which don’t get much hackers attention it’s enough to filter bots and noobie-hackers.