0

I have a MySQL table which stores scores of the users. Every time a user answer a question correctly, I add his or her score by one using AJAX request. The request sends just an integer number which is the id of the question.

My Question is: How to prevent fake AJAX requests?

As it is just an integer number I can't check if it is a fake request or not. So the only solution I come up with is to add an extra column to my table, named "yesterday_score", as its name describe it is a column that change at time 00:00 and save users score. If a user add his score more than 300 in a day, I assume it is a hack, and I prevent it.

cool
  • 710
  • 1
  • 6
  • 18
  • 1
    Possible duplicate of [Prevent Cheating on Javascript Game](http://stackoverflow.com/questions/7171101/prevent-cheating-on-javascript-game) and [many others](http://stackoverflow.com/search?q=%5Bjavascript%5D+prevent+cheating) – JJJ Sep 03 '16 at 17:25

4 Answers4

1

Check then answer with your back end to increment, not with the front end.

Never trust user input it the rule number one!

Tom
  • 4,666
  • 2
  • 29
  • 48
  • The answer isn't send, the user select the answer between four options, It is just an integer number (question_id) that sends to a php page, and if it is a number between 1 to 500, it is totally acceptable by the php code. – cool Sep 03 '16 at 17:25
  • @coolesterman that's my point! By checking the answer in JS, it means the JS has the correct answer, to check the user answer so to user can cheat. The only solution is to keep secret the correct answer in your server, and send to your server the user answer. – Tom Sep 03 '16 at 17:55
  • Thanks @Tom for the answer. But the user has to know that he answer the question correctly. It is an educational website, I'm really sorry, I forget to say that in the question, the JS turn the correct answer green immediately. – cool Sep 03 '16 at 18:54
  • The **back end** can return something so the JS can tell the user if the answer is correct or not. – Tom Sep 03 '16 at 19:25
  • OH @TOM I think I get what you mean. You mean I should send the "question_id" and "the answer the user selected" to the server and if it is the correct answer I tell the user "OH Yes, Your answer is correct". But he still can send "100 beautiful" a million times and my code will say okay the answer of the question number "100" would be "beautiful" and so he gets the point. I'm sorry but I don't get it. – cool Sep 03 '16 at 19:26
  • Yes, the client send you the question_id and the answer, if the answer is wrong the server reply to the client "wrong answer", if the answer is correct, the server reply to the client "correct answer" and, if the user answer correctly to that question for the first time, increment your counter AND note that the user answered correctly to that question (so you don't increment next time) – Tom Sep 03 '16 at 20:43
  • Yeah, about that, The user has to answer every question several time so I can meake sure he learn the lesson (or I can say he memorize the answer). I actually ask the question severeal time with JS. I'm sorry to bother man and appreciate the effort. – cool Sep 04 '16 at 01:39
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/122614/discussion-between-coolester-man-and-tom). – cool Sep 04 '16 at 12:37
1

Rather than sending the number to the database you can use the language your database uses to update the number. So in MySQL

UPDATE users SET score = score + 1 WHERE user_id = 12

user_id can be verified by comparing it with the session or something of the sort. Be sure to use prepared statements too.

NotJeeves
  • 43
  • 2
  • The score is not just one number for every user. Every user has 300 score, I should know which question he answered. – cool Sep 04 '16 at 12:42
0

I read a lot of related pages, some user suggested some kinds of solutions like: "If a user hits 10 headshots in 10ms then you kick him. Write a clever cheat detection algorithm." And there is an answer in same question:

There is no way to avoid forged requests in this case, as the client browser already has everything necessary to make the request; it is only a matter of some debugging for a malicious user to figure out how to make arbitrary requests to your backend, and probably even using your own code to make it easier. You don't need "cryptographic tricks", you need only obfuscation, and that will only make forging a bit inconvenient, but still not impossible.

in this page : How to block external http requests? (securing AJAX calls)

I might also use PHPIDS. But for know I think I will stick with my solution, I add another column and hold the user's "yesterday-score" and if the user get more than 100 score today I will know he is defenetly cheating so I won't increment extra score.

Community
  • 1
  • 1
cool
  • 710
  • 1
  • 6
  • 18
-1

Add a hidden field to form, and put in - md5(session_id())

if answer is correct - session_regenerate_id();

Alex Muravyov
  • 502
  • 6
  • 13