Securing High Score - security

I develop a simple game with an online simple high score.
One way to attack it is spoofing.
I wanted to send out a Post Request containing username and points.
Right now we just looking at sending data, receive it and process it. (=> no anticheat within the game or SQL injection etc)
The Question is:
What possibilities do I have to protect this process client side?
How do baddies hijack a post request, so they can spoof it?
What would be a solution to protect the content of the the request?
greetings

You can't stop fake high scores from being submittable.
You can have the end client digitally sign the high score, but the client could be modified, so that achieves nothing.
The best you can do is have the high score accompanied by a complete play by play of the game. That way the play by play can be audited to look for suspicious/erroneous behaviour.

You can't guarantee 100% that your communication will be secure but you can make an attacker's job harder.
If you encrypt the score within the game and send the (encrypted) score to the server you defeat most script kiddies who just downloaded Wireshark and learned to change numbers.
However, a determined attacker can always reverse-engineer your game to determine the encryption key, or even attach a debugger to the game and modify their score right before it's sent.
There are ways to make this more difficult as well but at the end it's a balance of how secure you want your game to be and how much time and effort you're willing to put into it.

Related

Safely Storing sensitive data client side

Back Story
I work at a small-mid size company and we are reworking our customer facing accounting portal and my manager wants to make single click payment option with the Credit Card info stored in cookies on the end users computer. I'm not in love this the idea.... at all (in fact I'm still trying to change his mind). That being said I am trying to make it as secure as I can, I think I've got a way to minimize the risk, here it is:
using SSL for all exchanges
encrypt the data in a number of cookies that are stored locally
having the cipher as a confirm password that must be entered each time. forcing the cipher to be strong, say 15+ mixed chars, and this is confirmed by checking a hash of it on the server.
I know that the major weak spot is the cookie info that is stored in a two way encryption, that said is this a reasonably safe way to store the info....
The Question
How can it be improved using this basic method.
Please I know that there is going to be a lot DON'T DO IT! answers (if I was not asking, I would be one of them) so please be specific, you are preaching to the choir on this so be constructive in the negatives.
Edit - If you have a specific point that you think I can use in reasoning with my manager please share. (I've already brought up that we maybe legally responsible if the CC info is stolen from a cookie, and he said he would have a lawyer look that over)
Thank you.
using SSL for all exchanges
Should be done no matter what solution you use, as long as credit cards/payment info is involved. As you probably know.
encrypt the data in a number of cookies that are stored locally having
the cipher as a confirm password that must be entered each time.
forcing the cipher to be strong, say 15+ mixed chars, and this is
confirmed by checking a hash of it on the server.
I usually remember my credit card number, and I'd rather put that in (as I'm already intent on not disclosing it to anyone) than a long and complicated key that most customers would write down somewhere anyway.
Even if we aren't allowed to say "don't do it!" - why don't you ask us for good ways to dissuade your manager from taking this decision? ;-)
What makes you unwilling to store this server-side? It's not like Amazon stores my credit card info in a cookie. The basic idea is to store all user info on the server, and access it when a user has authenticated successfully (i.e. logged in).
Cookies are in this case used to persist the logged in-state between browser sessions. The info this logged in-session has access to is stored on the server. With credit card info this usually entails a lot more security than other sensitive info, but it's the same basic idea.
Storing actual credit card numbers in cookies (encrypted or not) could be a potential PR nightmare when some tech-savvy customer realises what you are doing.
Thread for more reading: What information is OK to store in cookies?
Edit: The more I read through this question the more dumbfounded I get. Does your manager even know what a cookie is? How it works? What the point of it is? Saying that you want to store credit card info in cookies is like saying you want to use shoes as a means to transport shoe-laces. He is actively and purposefully shooting himself in the foot for no reason whatsoever. What he wants to achieve can be achieve a lot easier with other, much safer techniques - without any loss in functionality whatsoever.
From an article linked by Scott Hanselman:
Storing Credit Cards
If you absolutely must store credit card data it should be stored in encrypted form.
There are various compliance standards (specifically CSIP and PCI) that vendors are supposed to follow that describe specific rules of how networks need to be secured and data stored. These rules are fairly complex and require very expensive certification. However, these standards are so strict and expensive to get verified for that it's nearly impossible for smaller businesses to comply. While smaller vendors are not likely to be pushed to comply, not complying essentially releases the credit card company of any liability should there be fraud or a security breach. In other words you are fully responsible for the full extent of the damage (realistically you are anyway – I'm only echoing back the rough concepts of these certifications).
(my emphasis)
Point out that Cookies are transmitted across each request. If you store credit card information in them not only is it less safe, but you are not actually gaining any sort of realistic time benefit. Outside of being easier to implement, there is no reason to do it this way. Since you're the one implementing it he shouldn't care about the ease of implementation anyway...
Edit: You could also point out that if anything goes wrong, he will be the one getting fired for it. Threatening his job is a great way to get him to see it your way.
Don't use the user's password as the key, or at least, it shouldn't be the only thing that comprises the key. You should encrypt the credit card account information with a private key that is stored on the server (and not known to the user).
You can decrypt the credit card information on the server, even though it's stored on the client. This way, there is no way for the encrypted credit card information to be reversed on the client (without knowing the private key).
You might encrypt the credit card account information with both the private key and the user's entered password, that way, they can't be sent to the server to be decrypted without the proper password.

Verifying Client authenticity

I have built a game in HTML5 and a web form posts data to a server.
The scores in the game are calculated using Javascript, and the form posts the data to the server.
Won't this architecture be vulnerable to an attack, where the client can be modified, such that it posts rogue values instead of the calculated scores?
How can I prevent this from happening?
To keep things short - you need to do all of your verification server-side. There no problem using client-side scripts to keep things looking good, but you cannot trust anything from the client.
Take Stackoverflow as an example. When you vote it is instantly calculated client-side (to keep things nice and quick) but it is properly validated by the server once submitted.
For example if I attempt to upvote my own answer the server rejects it with the following JSON:
{"Success":false,"Warning":false,"NewScore":0,"Message":"You can't vote for your own post.","Refresh":false}
even though the javascript happily submitted it.
Therefore you also need to calculate your game scores server-side.
Don't trust user inputs, especially trough a form they might perform SQL injection as you send data to your server. (see also How can I prevent SQL injection in PHP?)
Try to verify as much data as possible server side.
Seeing that you also use javascript watch out for javascript injection (http://www.testingsecurity.com/how-to-test/injection-vulnerabilities/Javascript-Injection) as they can inject changes into ur script (e.g. score value)

HTML5 Multiplayer Game Security Solutions

Now that there are a couple of neat canvas demo's of both classic platform and even 3D fps games in HTML5, the next step might be to try developing a multiplayer HTML5 game. HTML5 socket support makes this relatively straight-forward, but with client-side source being viewable by anyone in the browser, what are some solutions for basic game security features for a HTML5-frontend multiuser game -- such as being able to prevent a faked high-score submit?
The simple answer is: You can't trust the data from client, which means that the high score submit can't come from the client.
Since the code client is available for anyone to inspect, there's no way of trusting the data that the client sends your server. Even if you encrypt the data with a per-user encryption key (which is possible), the user can simply alter your code within the browser and change the values it's sending to the server.
Since your game is multiplayer, this might be possible IF the server generates all the scoring events. If the server generates all the scoring events, the client never sends score data to the server which means that the high score data can't be faked.
You'll still have to deal with cheating, which is even more challenging, but that's another issue...
Adding on to what Larry said, you're definitely going to have to handle the scoring on the backend to really prevent cheating/fake score posting.
For an example of this in practice... The game Word Wars is a boggle-esque game where you find as many words as you can from a 4x4 grid of letters.
At the start of each game, a 4x4 board is generated server side. A list of possible words for that board is generated and a hashed version (md5'd with a random salt) of each word as well as the salt are passed to the client.
On the client side, when the letters are typed and the enter key is pressed, we md5 (with the salt from the server) the word that was entered and check that against the list of hashed words provided by the server. If it's a match, we update the client with the new score (there's a function based on letters used and their point values).
Once the game is over, the client sends the list of words they came up with to the server (NOT the score), and the server double-checks that those words existed in the board, and handles the scoring.
This is where Clay.io, the company I'm working in comes in. Clay.io offers an API for high level HTML5 game features like leaderboards, achievements, payment processing, etc... Needless to say, we needed a solution for games that have a backend to make certain things like high scores more secure.
The solution was to encrypt JavaScript objects on the backend (node.js, php, whatever) using JWT (JSON Web Token), and pass that encrypted object rather than the score itself. This lets us communicate both ways (game -> Clay.io and Clay.io -> game), and is pretty painless to do. The full docs on this are here: clay.io/docs/encryption (max links hit on this answer)
Back to Word Wars... from the server we generate that JWT with the user's score and pass that on to Clay.io to post the score. Voila :)
Of course, this will differ as the type of game you're developing differs, but the moral of the story is you have to get creative :)
I wrote a blog post that covers HTML5 game security in greater detail. Part 3 of a series on HTML5 Game Development Tips.

What is a simple and secure way to transmit a login key from one website to another while redirecting a user?

I want to create a portal website for log-in, news and user management. And another web site for a web app that the portal redirects to after login.
One of my goals is to be able to host the portal and web-app on different servers. The portal would transmit the user's id to the web-app, once the user had successfully logged in and been redirected to the web app. But I don't want people to be able to just bypass the login, or access other users accounts, by transmitting user ids straight to the web app.
My first thought is to transmit the user id encrypted as a post variable or query string value. Using some kind of public/private key scenario, and adding a DateTime stamp to key to make it vary everytime.
But I haven't done this kind of thing before, so I'm wondering if there aren't better ways to do this.
(I could potentially communicate via database, by having the portal store the user id with a key in a database and passing that key to the web app which uses it to get the user id from that database. But that seems crazy.)
Can anyone give a way to do this or advice? Or is this a bad idea all-together?
Thanks for your time.
Basically, you are asking for a single-sign-on solution. What you describe sounds a lot like SAML, although SAML is a bit more advanced ;-)
It depends on how secure you want this entire thing to be. Generating an encrypted token with embedded timestamp still leaves you open to spoofing - if somebody steals the token (i.e. through a network sniffing) he will be able to submit his own request with the stolen token. Depending on the time to live you will give your token this time can be limited, but a determined hacker will be able to do this. Besides you cannot make time to live to small - you will be rejecting valid requests.
Another approach is to generate "use once" tokens. This is 'bullet proof' in terms of spoofing, but it requires coordination among all the servers within the server farm servicing your app, so that if one of them processed the token the other ones would reject it.
To make it really secure for the failover scenarios, etc. it would require some additional steps, so it all boils down to how secure you need it to be and how much you want to invest in building it up
I suggest looking at SAML
PGP would work but it might get slow on a high-traffic site
One thing I've done in the past is used a shared secret method. Some token that only myself and the other website operator knows concatenated to something identifying the user (like their user name), then hash that with a checksum algorithm such as SHA256 (you can use MD5 or SHA1 which usually are more available but they are much easier to break)
The other end should do the same thing as above. Take the passed identifying information and checksum it. Compare that to the passed checksum, if they match the login is valid.
For added security you could also concat the date or some other rotating key. Helps to run SSL on both sides as well.
In general, the answer resides somewhere in SHA256 / MD5 / SHA1 plus shared secret based on human actually has to think. If there is money somewhere, we may assume there are no limits to what some persons will do - I ran with [ a person ] in High School for a few months to observe what those ilks will do in practice. After a few months, I learned not to be running with those kind. Tediously avoiding work, suddenly at 4 AM on Saturday Morning the level of effort and analytical functioning could only be described as "Expertise" ( note capitalization ) There has to be a solution else sites like Google and this one would not stand the chance of a dandelion in lightning bolt.
There is a study in the mathematical works of cryptography whereby an institution ( with reputable goals ) can issue information - digital cash - that can exist on the open wire but does not reveal any information. Who would break them? My experience with [ person ]
shows that it is a study in socialization, depends on who you want to run with. What's the defense against sniffers if the code is already available more easily just using a browser?
<form type="hidden" value="myreallysecretid">
vis a vis
<form type="hidden" value="weoi938389wiwdfu0789we394">
So which one is valuable against attack? Neither, if someone wants to snag some Snake Oil from you, maybe you get the 2:59 am phone call that begins: "I'm an investor, we sunk thousands into your website. I just got a call from our security pro ....." all you can do to prepare for that moment is use established, known tools like SHA - of which the 256 variety is the acknowledged "next thing" - and have trace controls such that the security pro can put in on insurance and bonding.
Let alone trying to find one who knows how those tools work, their first line of defense is not talking to you ... then they have their own literature - they will want you to use their tools.
Then you don't get to code anything.

cheat prevention for browser based xmlhttp/js/perl/php game

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:
Over and over again without actually doing the task of clicking on the link and
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?
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.)
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.)
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.
Token with cookie/session.
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.
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!
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.
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.
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:
Mark in the session that the link has been clicked so that it wont track that link again.
Add to their score.
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.

Resources