I want to write a little game where the users has to click on appearing elements/objects in a given time. In detail the objects appears in holes onto the ground and after x seconds the objects disappear. The gamer has y lifes and all clicks gets counted until he lost the game.
After that his highscore gets posted to a database (via form post or AJAX). Long story short how can I avoid the user faking his highscore before sending? The program language is JS.
I know its not possible to hide all the code and make it not hack-able. But I think it's enough if the code is so difficult that the user has to do a lot of work to understand where he has to intervent to send faked data.
Has anybody some ideas howto make the code as difficult as its possible?
Thanks in advance for any ideas :)
You should never really try to make your source code unreadable. It will make as great a headache for yourself than any obstruction to anyone modifying it.
That said, you could refactor all your variable names to complete gibberish and play with whitespace, but anyone seriously trying to understand your code could revert that in a decent text editor. To make it any more complex would take away from the efficiency of your program - otherwise you could fill it with useless calls to functions that don't do anything and strange incrementation of counters that the program does not depend on.
there are compressors that do exact the job you want! Some of them can be downloaded and used as offline tools, some are directly via web accessible:
http://javascriptcompressor.com
like jquery and others you can use your code to maintain the scripts and deliver a faster loadable packed version that is hardly readable
How about this:
Create two PHP pages, with one containing the game interface and the other containing the game's code. Program the first one so that it creates a one-time-use string that the tag will pass along as a parameter when it calls the JS code from the second one. Program the second one so it checks the validity of the string sent. If the string is valid, the script should output the JS code, then invalidate the string.
Then, when the user copies the URL of the script, pastes it into his browser, and hits "Return," all he sees is either a blank page or a "not authorized" message.
Related
I am going to be processing a lot of form data from the client using Ajax. Right now, my way of validating input is to add a 'validate' class to each form control that needs to be checked. When the user enters information (or submits the form) the script looks at the input of each control with that class and verifies its contents before moving to the next tab (or sending it to the server). The issue, of course, is that a user can easily remove the class and the item wouldn't be looked at.
While I will of course be validating the input on the server-side (client data can never be trusted!), a lot of the user-side content generation [new inputs, dynamic forms, removing/adding validate classes, etc.] depends on people not tinkering with the classes. While I know that the client can ultimately do whatever they want, what are some ways to make this process difficult for the client to manipulate?
So far I have thought about:
Running a script at the beginning of the page load that grabs all the HTML inputs with the 'validate' class and stores them in a variable. When the user submits the data or moves to the next tab, instead of looking at the elements with the class 'validate', I instead look to validate the data compared to the contents of the variable.
Adding data-validate HTML attributes to each input and doing the same thing as above (running a script and grabbing the inputs that need validation before the client has time to tinker with the settings)
Is there anything else that can be done? I am a little hesitant to use the above approaches because there may be new, dynamically generated form elements that need to be added/removed to the list; and this + grabbing the data at the beginning of the page load could cause a little unnecessary overhead.
"While I know that the client can ultimately do whatever they want..."
You just answered your question. If that's your starting point, why are you trying to make it harder? Is it worth my while to actually try to hack your site? If it is, I don't care that it's harder. Also, how hard can it be? Are you going to make it so hard to figure out the JavaScript that the next developer who looks at this code also won't be able to figure out what's going on?
Also, you're adding more code. Have you ever written code without bugs? I haven't. So, guaranteed, there are going to be bugs in this thing. So, in the off chance that 1 in a million users might try doing something bad, you'll end up stopping lots of legitimate users who get errors when they're using the site like they should.
Client side checking is ONLY meant to be nice to the end user, to give them immediate feedback. Period.
Might not be the answer you like, but it is the answer. :)
Edit: One last comment. Let's say you did make it REALLY hard. Would you then not do server side checking? Would you say to your boss, "Oh, we made it pretty hard to hack on the client side. They still can. We just made it hard. So no need to do server side checks." Of course not. So, if you're doing server side checks no matter what, you don't gain anything from trying to obfuscate on the client side.
I am designing a SQL engine. From the UI the user will select certain parameters and based on those parameter I will design a SQL statement. User will have option to join tables, apply conditions, create temp tables, ability to apply many SQL in-build functions etc. I will write many functions which will look at the input and based that perform some action which will ultimately give a SQL statement.
I can do this code using any server side language but we want to try JavaScript.
Obviously this will require lot of string manipulation.
I am just worried if this will result "“A script on this page is causing Internet Explorer to run slowly. If it continues to run, your compute may become unresponsive." on IE or "A script on this page may be busy, or it may have stopped responding. You can stop the script now, open the script in the debugger, or let the script continue" on Firefox.
I know I am not sharing any code & the question is little subjective. But I am sure some of you may have faced similar issues/challenge in your previous assignment & your valuable suggestions will be a big help.
Unless I have misunderstood your question, you are asking if there is a risk of getting that dreaded message when doing a couple of string manipulations.
If you want to only construct the query in the browser, then I think you are fine, as you won't have to, say, concatenate 1000 strings, or search a string amongst 1000. The only risk I would say is if you intend to do complicated regexp operations on big strings.
If I misunderstood, a few example of the string manipulations you intend to do would help.
Of course, I am assuming you will send and run the SQL queries in an asynchronous manner.
I'm developing a little jQuery selector game. Essentially, you're given some HTML code, and you have to write the jQuery selector to select the highlighted item.
For example, say you have:
<body>
<p id="winner">Select this paragraph</p>
<p> But not this one </p>
</body>
And one of the correct selectors would be $('#winner')
I currently plan on grabbing the string within the "$(' ... ') " (where the ...'s are) and doing something like this:
var userInput = ...
var userSelectedItems = new Array();
userSelectedItems = $(userInput)
// Check if userSelectedItems == the array of elements supposed to be selected
// Change screen to green and allow users to press enter and continue to next challenge.
Now, I know that if you allow users to directly enter some PHP or something, all sorts of bad things can happen, but is there anything with essentially allowing users to enter/execute this kind of javascript command? If so, how do you propose I get around this situation. I'd really enjoy making this educational game, so any help is greatly appreciated. I can't really see any way it could be dangerous because it's all run on the client's computer right..? I don't know though, maybe I'm missing something
Thanks
Security problems may arise if you allow users to use other users' Javascript, however if the only person who is executing code is the person who is entering it, then you should be alright.
Anything on the client-side is always susceptible to changes done by the end-user.
However, if you aren't saving anything information to a database and there aren't any competitive conditions with regards to this game, I would not worry about any security issues that may arise. You can always sanitize client input within your own Javascript to ensure that non-technical users may not change game states during the process.
It's no different than Javascript, the only vulnerability would be if someone was able to inject some code into your app or database which in result displays the content served on your web server. As long as your app is protected against XSS and SQL Injections, you should be fine, it would be the same concept.
Thanks to the recent browsers enhancements, developing games with canvas and javascript has become a good option, but now that the code is easily accessible, just writing
javascript:score=99999
or
javascript:lives=99
Will spoil the game objectives.
I know that with some server-side checking something can be done, but I would prefer to access the server just to store player stats at the end, or even have it client only in most cases.
I wonder if at least the are some best pratices to start with.
(using not so obvious variables names is a start, but not enough)
-Added-
Thanks for the replies, I was looking to improve the client-side code, enough to stop "casual hackers", but still leaving the code as clean as possible.
Anyone that really wants to hack it will succeed anyway, even with server-side checks, as I've seen it in many flash games.
I'll say what I said at my comment: put every source code in (function(){ }());. Then, the variables and functions can't be accessed from outside.
Example:
(function(){
var a = 'Foo';
var b = 42;
function helloWorld(a,b){
for(i=0;i<b;i++)console.log(a);
}
helloWorld(a,b);
});
//Can't access to a, b, or helloWorld using javascript: or default console of Google Chrome,
//but people still can see by looking source code and may be modified by other tools
//(see comments of Tom & user120242)
I 'learned' this technique this when I dig into Les Paul Google Doodle.
To be more secure (not completely secure, but it'll annoy some hackers), compress and obfuscate your script by tools something like YUI compressor or packer.
One way is to send a record of every move to the server as well, then to verify that those moves would have got that score.
That's easy for games like solitaire or chess, but not really for more complex games.
A simpler version of that is to work out the max points that could be obtained per second, or per move, then to verify that the score isn't higher than your theoretical maximum.
Another way is for each move to be recorded on the server, and to total up the score there. That means there is no send at the end of the game, and that those variables are only for display, not the real score.
Offline games could be starred on the highscore table or something to show they aren't verified.
It's worth pointing out that with any javascript debugger, such as the Inspector in Webkit, Firebug for Firefox or Dragonfly on Opera it's trivial to change the value of variables on the client side, even if your code is in a closure. Any form of obfuscation is pointless, as again it's easy to watch which variable corresponds to the score as the game is played, and any encoding or whatever can simply be read out of the code.
In order of preference:
Send player moves or statistics to server. Prevent strange behavior.
eg: Score too high, invalid actions, actions that cannot be replayed, etc
Prevent strange behavior on client-side. Same as above but not on server. eg: sudden lives changed, moving too fast, etc
Create obfuscated JS output (which you should be doing to reduce JS size anyways) eg: GWT (Java to JS compiler), Google Closure Compiler (ADVANCED_OPTIMIZATIONS will obfuscate more, --output-wrapper (function(){%output%})() to wrap in closure), Yahoo Compressor
Obfuscate variable values eg: Encode strings (xor, substitution, BASE64), don't use normal variable increments
Use a closure to encapsulate variable names: (function(){code here})()
EDIT: I want to make clear that the best solution is still to move calculations to the server, as Rich Bradshaw had said. These things can only do so much, even after you obfuscate the code.
Here's a link that also applies to your Javascript game, and I think is probably the best possible answer to your question: What is the best way to stop people hacking the PHP-based highscore table of a Flash game
The most important idea to get from that link is:
The objective isn't to stop this
attack; it's to make the attack more
expensive than just getting really
good at the game and beating it.
I'm implementing a simple game in Javascript, and am interested in having an online highscores table for it, so that players can compete against one another. I've two concerns about this:
What is the simplest server-side program I need for this purpose? I don't need a full-fledged "web application", just something simple that gets POST requests with highscores, updates a database and sends back lists of scores. I'm familiar with Django. What are your suggestions?
How can I make the highscores table reasonably secure? I'm aware that making it bulletproof against competent and dedicated hackers is difficult, but I wouldn't want anyone with access to the Javascript sourcecode to be able to submit fictitious scores too simply. Any tools for this purpose?
It's going to be pretty hard to secure the high scores. I mean, it's not enough to ensure that it comes from your page, because if, say, the JavaScript function is submitHighScore(n) then they can always type javascript:submitHighScore(10000000) in the address bar on that page and have it work.
What comes to mind is perhaps some sort of hash function that generates specific codes that match certain levels in the game. When submitting the score it would also submit this hash, so users would have had to get to this level in order to get that equivalent score.
Another option would be for the game to pull in some kind of key that only works temporarily, so as you went along the key would change and then the score would be submitted to a central server intermittently.
Keep in mind that really determined individuals can always just track the data being sent to your data and decompile it.
You could go the Broderbund route and ask the player trivia questions which are validated server-side to ensure they really did pass the level they said they did...something like "What color was the monster in the previous level?"
To submit score securely, sign it (you'd also need to ensure that the score isn't faked before it's signed and sent, but that's another problem).
Hide a secret in JS code, and send highscore + hash(highscore + secret) to the server. The hash could be MD5/SHA1 — there are easy to find JS implementations.
Of course it won't stand anyone carefully analysing the JS code, but at least someone won't be able to submit fake highscore just by tampering with HTTP traffic.
On hiding stuff in JS:
You can't really hide it (it's ultimately futile like DRM), but you can try hard to obfuscate it and make debugging painful.
Don't put the secret as a literal in the source code - compute it at run time combining results of several functions, local and global-ish variables.
Minify all code, remove sourcemaps.
Add bits of code that don't do anything, but seem to be important, to make debugging more confusing.
Don't put anything in global scope, but do rely on shared mutable state by passing closures and arrays around.
Rely on Date and timers to cause race conditions to make your code produce wrong results if it's paused in the debugger (just don't make it too tight to allow it to run on slow machines).
If the game is deterministic (like a puzzle game), then users could submit highscore in form of a log of steps taken to win (user's input) that you'd replay on the server to calculate the score.
This would change attack from finding/emulating score-submitting function to witing AI or hacking the game itself to make it easier to play (but still within its basic rules).
1.) Any CGI script that can talk to a database and understand JSON, or other format of your choice, will do the work.
However, if you're familiar with Django, building your server on top of Django would be the most simple, in the sense of what you have to learn and how much application code you have to write. Seemingly simple CGI script can turn out rather complex if you write it from scratch.
I found django-piston to be a handy Django app to quickly write a REST-style API server. It supports JSON so it should be easy to interface with your JavaScript game.
2.) The most casual cracker will go for a replay attack and its variants: peek at the page source and execute a JavaScript function, intercept HTTP requests and resend it (should be easy with a Firefox add-on like Tamper Data).
To counteract the former, you can obfuscate the source code and HTTP body;
Minify the JavaScript code
Encode the message you send to the server with Base64 or other encoding algorithm
The latter can be prevented by requiring all update requests to include an one-time password ("session token" in the Wikipedia article) that was recently acquired from the server.
I am thinking about this myself. What seems to be the most reasonable solution to me is this:
1) Sessions, to disallow tampering with the scoretable outside the game.
2) Log every action in the game and send it to the score server. The server will then calculate if those actions actually give such score. If you also log the time spent playing the game, you can further minimize the chance of an attacker to bother himself enough to break your game. This will also enable you to make a replay script like Arcade servers with hi-score tables have and in case of a suspicious score, you can watch the replay and decide for yourself if the score is real. The cheater would have to use a clever bot to play your game - and unless you have a game for real prizes, noone will try that hard.
If the cheater won't even analyze your code, sessions will stop him. If he reads your code, he would quickly break anything similar to hashed scores, secrets, tokens and whatsoever. But if you make the game-logging script thorough enough, he will give up.
In answer to your question:
1.) This depends on your environment and coding preference. PHP, Python, ASP.NET are a few that come to mind. Sense you already know Python (from your profile) you can use a Python CGI script to do this or use one of the many frameworks for Python (Zope, Django, Pylons,...).
see: http://www.python.org/doc/essays/ppt/sd99east/index.htm
for info on Python CGI.
2.) A few tricks for security: (none or full-proof)
Hidden Text Box in HTML with encoded value that server checks to match a cookie to ensure high score comes from your page.
Server Script only accepts values from a specific domain
You could use a combination of one of the methods above, as well as simply requiring the user to be registered to be able to post high scores. Non registered users could view their current score compared to existing high scores, but in order to post your high score online, you must have already logged in with your registered account, or provide it when the app goes to update the score online.
A simple message along the lines of "Your high score is X, and ranks ### in the high score table. To post this score online, please register with us first".
The better I think, is to make the calculation of the score directly into the python files of your django app.
Instead of calculate it in the javascript file. You send the datas to compare with your data basis with a POST request, then you calculate the score and you store it in your data basis. Like this, you don't make circulate the score across the web to your servers. Which is completely safe because you are only doing local stuffs.