Related
I'm working on a game, which has score based on a JavaScript countdown: the faster you finish the level before the countdown reaches zero, the bigger your score is.
How can I make sure it is not somehow altered when I finally receive it from client-side on server-side?
My initial idea is to make two checkpoints: one at the beginning of a level and another at the end. Checkpoint is basically a session sent via AJAX to server-side PHP script which is then timestamped. So after the game is finished on client-side, the score is verified with the one on server-side. Is this kind of protection any good?
Thank you in advance!
EDIT:
I'm also open to any other ways to achieve the desired functionality.
Simply, you store the value in a datetime field in your database. Then, you seed your javascript with that value. Thus, any change on the client side, will not have an effect on the stored time.
However, if you depend on the client side to get a value, you cannot do anything to make sure it's correct. The user can still spoof the ajax request with no real problem. It makes it a bit harded, but certainly doable.
Once your countdown is somehow related to the client side, there is no escape :)
As others have pointed out, there's no way you can be certain that the times have not been tampered with, however there are ways to mitigate the consequences:
If you have a (server-side) system that suspects that scores have been tampered, you can blacklist that IP address or cookie, and not show those scores to other users. Do show the scores to the hacker, though. This has several effects: Firstly, if they think they've beaten you they may move on and leave your code alone. Secondly, if your cheat detection wrongly thinks that a ninja player is hacking, the player will still see their score in the tables as normal (even if other players don't). Consequently, false positives don't matter so much, and you can use fuzzier algorithms, e.g. How does this player's rate of improvement compare to the average? Has he got a bunch of poor scores then suddenly an incredible one? Has my server seen an unusual pattern of hits from this user? Etc.
You could probably set this up so that you could refine your detection algorithms incrementally, and blacklist players after you've got suspicious about them (and un-blacklist false positives).
There are 2 possible scenarios which you might be facing. Let me start with the easy one:
a) If the web application is designed such that the game starts as soon as the page is loaded, your life is going to be simple. The script which sends out the game should timestamp the database with the time at which the game was sent out. This would be the start time. The end time would be recorded when the client sends in a "level completed" message. As time is being recorded at the server side in both the cases, you do not need the client to keep time. However, there is a catch. See The Catch section below.
b) If the client loads the application but the game begins much later when the user hits 'play' etc., your life is going to be a little more difficult. In this scenario, you would need a "level began" as well as a "level completed" message coming from the client. Again, it would be a better idea to keep time at the server and not the client. However, you would need to ensure that the client receives an ACK to the "level began" message before starting the game to ensure that the user does not play a game which is not being recorded by the server. (The "level began" message might never have reached the server).
The Catch: You need to realise that there is no protection possible for the user cheating on his scores! JS is completely open and no matter how you implement your start / end calls to the server, any user can write a script to send similar calls to the server at whatever time interval she wishes to use. Even if you use a session / cookie, these can be easily replicated. (Using a sniffer for instance). Thus, you must realise and accept the design limitations imposed by the HTML/JS architecture and code within these limits. Hence, the best idea is to write code for the users and not to prevent the hackers from sending rogue calls. Make your game fun for the people who would be playing your game and do not worry about the hackers cheating on their scores - they would not be your target audience anyway.
First of all, forget getting the elapsed time from the client side. Any malicious user can alter the sent data.
Server side must be the only authority for storing the time. At the beginning of the level, store the current time in the $_SESSION. At the end of the level, subtract it from the current time and it is the elapsed time for the level.
$_SESSION['start_time'] = time();
$elapsed_time = time() - $_SESSION['start_time'];
You can still show the elapsed time by Javascript for the user's convenience. For the timing differences between the client and the server (which is perfectly possible), you can do synchronization by getting the elapsed_time whenever your client hit the server.
If the level completion span between multiple sessions (like you start the level, leave the site, and come back later to finish it) you have to store it in a persistent data store (database).
You can use a timestamp in a session to store the start date and then send make JavaScript do a request when the player's done (but the second timestamp should come from PHP, or other server-side language, too).
The ony really bullet-proof way is to show nothing to the user and to ask him to tell you every single move, check it with the server and send back what it allows him to know. But this means delay.
You could issue a unique token, that is stored within the user's session and is available to your Javascript code. When starting an AJAX request, pass this token as an additional parameter, so the server can distinguish between legimitate and spurious requests.
This token should be valid for a single request only of course.
In combination with the mentioned solutions (server-based time checks etc.) you should be able to build a solid scoring system.
well, thinking of this problem gives me two ideas:
Attack your own server.
by that i mean, send a request every 1 second, that will save the score.
this way, the "hacker" can not send Start/End time and cheat.
make the requests at a specific time diffrences.
ok, so lets say we started playing, you can send a request at specific time intervals (3.4 sec? )
if a request is not in that time frame then the user is cheating ?
or at least marked as possible cheater.
use a simple string. XD
for start/end time sent to server, offcourse encrypted.
you can try jCryption for encryption.
since as the others said, it is not totaly fail proof ( since we are talking about client side script ) , but at least it will make it a lot harder to cheat.
dunno, its just my two cents.
It is not possible to make it 100% bulletproof, you can only make it harder to hack if it is based on client-side
You can generate a GUID when the page is rendered. You can concatenate this GUID, the start datetime ticks, the session ID, and calculate a hash of them to validate the data when user return.
I wrote a game in c++ using SDL. The game currently updates a highscore to my game site by making a post with curl if the user has logged in. The problem that I am having is that the post provides the url to the php file that receives the post on my server, and the variables that the post uses. Last night someone from china figured this out and created 5 accounts and then posted ridiculously high highscores to those users. Is there any way I can make this more secure?
Would ssl work? I've been reading about ssl all morning, and I got curl to verify that ssl is installed, but I honestly dont even know where to start with getting my php verification page communicating with my game using ssl. I'd really hate to take the whole hiscore feature down because I've already invested so much time into all of this.
At this point I am looking for the simplest solution to prevent someone from making a form and posting new hiscores to the php page.
Any help would be greatly appreciated.
You could add a small layer of security by passing not only the high score, but a hashed version that is validated on the PHP side.
e.g.
{hs:"2000";hash:'843ed7842a6bd864162022e48b84a668'}
Posted to your PHP script, that then checks,
if($hash==md5('secret'.$hs)){
//UPDATE HighScore
}else{
//Discard, flag spammer
}
The quickest solution would be to keep an eye on the high score list, delete impossible-looking scores, and blacklist known cheaters.
However, for a longer-term solution, could you possibly send a list of the players' timestamped "physical input" (mouse clicks, key presses, etc.) along with the high score?
The server could then perform some logic using the input (perhaps even running that input through a game client running on the server) to determine whether the high score is valid.
If your game uses random numbers, you'd have to send the initial random seed as well.
Once you manage to implement this, you could fairly easily create a replay system, too, which would allow players to share replays of their games with each other.
You can add salt to data, and only app on c++ knows it, and server
Or you can`t?
SSL itself won't be enough to stop people from posting high scores. There are a couple approaches I can think of to begin with:
Ship your code with a secret key that is used to encrypt the high score before sending it to the server. This has the downside that someone could reverse engineer your game to get the key. This is probably okay though, if you don't think someone would go through the trouble. Crypto++ is a C++ encryption library that you could use for this. You probably want to use symmetric-key encryption.
What I think some other games do is to use some aspect of the game along with just the raw high score value to make a submitted score invalid if it didn't contain the game state.
I am about to write a voting method for my site. I want a method to stop people voting for the same thing twice. So far my thoughts have been:
Drop a cookie once the vote is complete (susceptible to multi browser gaming)
Log IP address per vote (this will fail in proxy / corporate environments)
Force logins
My site is not account based as such, although it aggregates Twitter data, so there is scope for using Twitter OAuth as a means of identification.
What existing systems exist and how do they do this?
The best thing would be to disallow anonymous voting. If the user is forced to log in you can save the userid with each vote and make sure that he/she only votes once.
The cookie approach is very fragile since cookies can be deleted easily. The IP address approach has the shortcoming you yourself describe.
One step towards a user auth system but not all of the complications:
Get the user to enter their email address and confirm their vote, you would not eradicate gaming but you would make it harder for gamers to register another email address and then vote etc.
Might be worth the extra step.
Let us know what you end up going for.
If you want to go with cookies after all, use an evercookie.
evercookie is a javascript API available that produces
extremely persistent cookies in a browser. Its goal
is to identify a client even after they've removed standard
cookies, Flash cookies (Local Shared Objects or LSOs), and
others.
evercookie accomplishes this by storing the cookie data in
several types of storage mechanisms that are available on
the local browser. Additionally, if evercookie has found the
user has removed any of the types of cookies in question, it
recreates them using each mechanism available.
Multi-browser cheating won't be affected, of course.
What type of gaming do you want to protect yourself against? Someone creating a couple of bots and bombing you with thousands (millions) of requests? Or someone with no better things to do and try to make 10-20 votes?
Yes, I know: both - but which one is your main concern in here?
Using CAPTCHA together with email based voting (send a link to the email to validate the vote) might work well against bots. But a human can more or less easily exploit the email system (as I comment in one answer and post here again)
I own a custom domain and I can have any email I want within it.
Another example: if your email is
myuser*#gmail.com*, you could use
"myuser+1#gmail.com"
myuser+2#gmail.com, etc (the plus sign and the text after
it are ignored and it is delivered
to your account). You can also include
dots in your username (my.user#gmail.com). (This only
works on gmail addresses!)
To protect against humans, I don't know ever-cookie but it might be a good choice. Using OAuth integrated with twitter, FB and other networks might also work well.
Also, remember: requiring emails for someone to vote will scare many people off! You will get many less votes!
Another option is to limit the number of votes your system accepts from each ip per minute (or hour or anything else). To protect against distributed attacks, limit the total number of votes your system accepts within a timeframe.
Different approach, just to provide an alternative:
Assuming most people know how to behave or just can't be bothered to misbehave, just retroactively clean the votes. This would also keep voting unobtrusive for the voters.
So, set cookies, log every vote and afterwards (or on a time interval?) go through the results and remove duplicates based on the cookie values, IP/UserAgent combinations etc.
I'd assume that not actively blocking multiple votes from same person keeps the usage of highly technical circumvention methods to a minimum and the results are easy to clean.
As a down side, you can't probably show the actual vote counts live on the user interface, or eyebrows will be raised when bunch of votes just happen to go missing.
Although I probably wouldn't do this myself, but look at these cookies, they are pretty hard to get rid of:
http://samy.pl/evercookie/
A different way that I had to approach this problem and fight voting fraud, was to require an email address, then a person could still vote, but the votes wouldn't count until they clicked on a link in the email. This was easier than full on registration, but was still very effective in eliminating most of the fraudulent votes.
If you don't want force users to log, consider this evercookie, but force java script to enable logging!
This evercookie is trivial to block because it is java script based. The attacker would not likely use browser, with curl he could generate tousends of requests. Hovewer such tools have usually poor javascript support.
Mail is even easier to cheat. When you run your own server, you can accept all email addresses, so you will have practically unlimited pool of addresses to use.
I am making a game where the battle system uses javascript to battle. At the end of the battle you either win or lose. If the user wins, I need to update the mysql database with the XP they earned.
The best way I can think of doing this is to have the javascript run an ajax function when the user wins that POSTs something like addxp.php?amount=235, but if I do that then the user can easilly look at the source and see that they can just enter in that page themself to update their xp without battling. But this is the only way I know how to do it?
Help please :-/
If you rely on the code running on the client's web browser to update the battle results, you do not have control over that code. Many javascript and flash games that have a high score board that depend on the browser sending in the high score registration are vulnerable to this. There is no real easy way around this.
You can try to obfuscate things somewhat, but someone who's interested enough is going to be able to fairly easily get around this.
As knoopx mentioned in his comments, the only sure-fire way to get around this is to do computations server-side. For example, the client browser sends user actions to the server, and the server is the one that determines the outcome of the battle, inserts the result into the mySQL db, and sends the result back to the client. This is obviously a major architectural change and you'll have to decide whether it's worth it.
This one is tricky and unfortunately there is no easy solution. I can give you some advice that helped me when I was creating a flash-game with a cash-prize. It worked quite well for me, but again - it was by no means full proof.
First of all do some thinking about the highest score it would be possible to achieve over a given time period. For example, you could say that the highest score you could reasonably get after playing for 1 minute is 200 points.
Each time someone starts playing the game, you do an AJAX call to your server to obtain a game ID. At set intervals (say 10 seconds), you make your game phone home with the game ID and the latest score. This way the only way to cheat would be to create a script that periodically contacts the server with a slowly incrementing score that falls under your maximum. Not a difficult thing to do, but at least now we're entering the territory where we've eliminated the casual louts with TamperData and a few minutes to kill boredom with.
Another thing you can do when you send back the current score is the current status of the gameboard. This isn't so useful for catching cheats live, but it's a very good tool you can use when awarding a prize to check that the high-score is a genuine one. This adds another layer of complexity to your system and hopefully make some of the more slightly-hard-core louts get bored and find something else to do.
My last suggestion is this - you in no way make your users immediately aware of what you're doing. That is to say, that if someone's score falls above your high-score/time threshold, you do nothing to let them know that they've tripped your cheat-detector. In the game I created, I even recorded their high-score along with their cookie. When getting the highscores from your database you SELECT * FROM scores WHERE cheated = FALSE OR cookie = userscookie. This way, unless they clear their cookie and check again, it will appear (only to them) that their hack attempt was successful.
Oh and one last thing; minify your javascript. This will obfuscate the code and make it very hard to read. Again, someone determined enough can easily circumvent this and look at your code, but it's all about making your system complex enough that people won't bother.
Unfortunately the web's strongest point can sometimes also be its weakest. It is the nature of the WWW that source code is open and available for anyone to read, which means that keeping secrets from your users is very hard if not impossible.
Currently we are running a competition which proceeds very well. Unfortunately we have all those cheaters back in business who are running scripts which automatically vote for their entries. We already saw some cheaters by looking at the database entries by hand - 5 Star ratings with same browser exactly all 70 minutes for example. Now as the userbase grows up it gets harder and harder to identify them.
What we do until now:
We store the IP and the browser and block that combination to a one hour timeframe. Cookies won't help against these guys.
We are also using a Captcha, which has been broken
Does anyone know how we could find patterns in our database with a PHP script or how we could block them more efficiently?
Any help would be very appreciated...
Direct feedback elimination
This is more of a general strategy that can be combined with many of the other methods. Don't let the spammer know if he succeeds.
You can either hide the current results altogether, only show percentages without absolute number of votes or delay the display of the votes.
Pro: good against all methods
Con: if the fraud is massive, percentage display and delay won't be effective
Vote flagging
Also a general strategy. If you have some reason to assume that the vote is by a spammer, count their vote and mark it as invalid and delete the invalid votes at the end.
Pro: good against all detectable spam attacks
Con: skews the vote, harder to set up, false positives
Captcha
Use a CAPTCHA. If your Captcha is broken, use a better one.
Pro: good against all automated scripts.
Con: useless against pharygulation
IP checking
Limit the number of votes an IP address can cast in a timespan.
Pro: Good against random dudes who constantly hit F5 in their browser
Pro: Easy to implement
Con: Useless against Pharyngulation and elaborate scripts which use proxy servers.
Con: An IP address sometimes maps to many different users
Referrer checking
If you assume that one user maps one IP address, you can limit the number if votes by that IP address. However this assumption usually only holds true for private households.
Pro: Easy to implement
Pro: Good against simple pharyngulation to some extent
Con: Very easy to circumvent by automated scripts
Email Confirmation
Use Email confirmation and only allow one vote per Email. Check your database manually to see if they are using throwaway-emails.
Note that you can add +foo to your username in an email address. username#example.com and username+foo#example.com will both deliver the mail to the same account, so remember that when checking if somebody has already voted.
Pro: good against simple spam scripts
Con: harder to implement
Con: Some users won't like it
HTML Form Randomization
Randomize the order of choices. This might take a while for them to find out.
Pro: nice to have anyways
Con: once detected, very easy to circumvent
HTTPS
One method of vote faking is to capture the http request from a valid browser like Firefox and mimic it with a script, this doesn't work as easy when you use encryption.
Pro: nice to have anyway
Pro: good against very simple scripts
Con: more difficult to set up
Proxy checking
If the spammer votes via proxy, you can check for the X-Forwarded-For header.
Pro: good against more advanced scripts that use proxies
Con: some legitimate users can be affected
Cache checking
Try to see if the client loads all the uncached resources.
Many spambots don't do this. I never tried this, I just know that this isn't checked usually by voting sites.
An example would be embedding <img src="a.gif" /> in your html, with a.gif being some 1x1 pixel image. Then you have to set the http header for the request GET /a.gif with Cache-Control "no-cache, must-revalidate". You can set the http headers in Apache with your .htaccess file like this. (thanks Jacco)
Pro: uncommon method as far as I know
Con: slightly harder to set up
[Edit 2010-09-22]
Evercookie
A so-called evercookie can be useful to track browser-based spammers
Have you tried to do browser fingerprinting?
Check this open source from EFF:
https://panopticlick.eff.org/
Could be used to identify one person similar to 500-1500 in the world (!).
You may add captcha to voting form. Also requiring e-mail confirmation will be useful
If you're really worried about it then you have to do something like email verification, which might be sufficient to block most cheaters.
Also it depends whether multiple people behind a NAT are likely to want to vote for the same option (e.g. favourite school).
Any scheme you create can be gamed.
EDIT: As everyone else has suggested, you can use a CAPTCHA such as reCAPTCHA to block automated bots, and make humans less likely to repeat vote. At the cost of making humans less likely to vote at all.
The Vote to Promote pattern (you may be aware of it) has a section on how to mitigate against gaming - but it is a tricky one to avoid altogether. Given your actions to date I would consider using weighting, for example consider a reasonable level of voting over a time period, say 10 votes per ting per hour (just an example not a guide) and for surplus votes weight the next 10 at 90% (ie only count 9), the next 10 at 80% and so on. This is Yahoo's advice on gaming within this pattern:
Community voting systems do present a
number of challenges. Particularly the
possibility that members of the
community may try to game the system,
out of any number of motivations:
malice - perhaps against another member of the community and that
member's contributions.
gain - to realize some reward, monetary or otherwise, from
influencing the placement of certain
items in the pool)
or an overarching agenda - always promoting certain viewpoints or
political statements, with little
regard for the actual quality of the
content being voted for.
There are a number of ways to attempt
to safeguard against this type of
abuse. Though nothing can stop gaming
altogether. Here are some ways to
minimize or hinder abusers in their
efforts:
Vote for things, not people. In keeping with Yahoo's general strategy,
don't offer users the ability to
directly vote on another user: their
looks, their likeability,
intelligence, or anything else. It's
OK for the community to vote on a
person's contributions, but not on the
quality of their character.
Consider rate-limiting of votes.
o Only allow the user a certain number of votes within a given
time-period.
o Limit the number of times (or the rate at which) a user votes
down a particular user's content. (To
prevent ad-hominem attacks.)
Weigh other factors besides just the number of votes. Digg, for
instance, does not calculate their
Digg-score solely on the number of
votes a submission receives. Their
algorithm also considers: "story
source (is it a blog repost, or the
original story), user history, traffic
levels of the category the story falls
under, and user reports." They update
this algorithm frequently. Consider
keeping the exact algorithm a secret
from the community, or only discuss
the factored inputs in general terms.
If relationship information is available consider weighting user
votes accordingly. Perhaps prohibit
users with formal relationships from
voting for each other's submissions.
While this is currently a popular
pattern on the Web, it is important to
consider the contexts in which we use
it. Very active and popular
communities (Digg is an excellent
example) that enable community-voting
can also engender a certain negativity
of spirit (mean comments, opinionated
cliques, group attacks on 'outlier'
viewpoints).
Check out Asirra: http://research.microsoft.com/en-us/um/redmond/projects/asirra/
It's still in beta, but it's pretty cool.
To prevent the bots from voting you can use CAPTCHA.
The only thing that comes to mind is using a Captcha. Either an elaborate one with pictures and noise like the ReCaptcha service, or a very simple and unobtrusive one like "What is seven plus three?" or (If you're located in the US), "What is the last name of our President", simple common sense questions everybody can answer. If you change them often enough, this could even be more effective than a classic image-based CAPTCHA.
CAPTCHA's aren't a silver bullet, the user could have their script display the CAPTCHA to them and solve them manually for at least several votes per minute.
You need to use them in combination with other techniques mentioned here.
You could add a honeypot field like in Django. Most likely, this will not protect you from cheaters who deliberately want to change your competition, but at least you will have lesser 'drive-by' spammers to additionally take care of.
Sorry for the double post, but I wasn't allowed to post two URLs in the same post...
If you're looking at building your own tracking, maybe this link might provide some inspiration: https://panopticlick.eff.org/
Turns out that a lot of browsers can be uniquely identified, even without any form of tracking cookies. I'm guessing a vote-bot might give a very specific fingerprint?
So if everyone ever wants to make a competition where people can win something and wanna use a community driven rating system... here i share some experiences:
The bad:
1) First it cant be made secure for 100%
2) to reach a mass of users which filters out all the nonsense ratings is very hard
3) Forget about star ratings in that case... their is always either 5 Stars or 1 Star
The good
1) Dont give them orientation about where they stand... We replaced the "Order by place" view with a random presentation of the TOP 100 (only the top 30 wll win a price)... This really helped because a lot of users lost their interest as soon as they didnt see where they stood.
2) Don't allow votings like: 1x5_Stars 40x1_Star... Just allow users which vote in a fair way...
3) Most of them act a little bit stupid... You'll see them in your logs and can trace down who votes fair and who unfair... Search for patterns...
**GOOD LUCK ;-) **
CAPTCHA is always good, might be "disturbing" for some users though.
reCAPTCHA is a fairly used service
How about only allow users who logged in with openid and with reCaptcha before submitting the vote, and monitering the submitter list with same ip address.
We use a combination of CAPTCHA and email. The user receive a link with a GUID by mail.
This one must be unique for each user that try to vote.
www.votesite.com/vote.aspx?guid=.....
By using this link the vote is confirmed or not. In database we check the combination of email address and GUID to be unique.
I use a combination of CAPTCHA, IP verification and LSO (Flash Local Shared Objects, hard to find and delete for common people).
1.Use recaptcha
2. Yes randomize your voting options but not like this:
-> from vote_id_1 to asdsasd_1, grdsgsdg_2,
Instead use session variables to set a mask from vote_id_1 to asgjdas87th2ad in the vote form.
What about some post hoc stochastic analysis, like time series analysis - looking for periodicity in events of particular (ip, browser, vote)? You could then assign probability to each such group of events that it belongs to 1 person and either discard all such groups of events beyond some probability level, or use some kind of weighting to lower the weight according to the probability.
Look in R, it contains A LOT of useful analysis packages.
Check the domain details of the email they are using. I had the same problem and found that all of them were registered to the same registrant. I wrote it up here: http://tincan.co.uk/659/news/competition-spammers.html
Now, I filter on the DNS information for the email used in the registration.