webdevcody / code-racer

https://code-racer-eight.vercel.app
MIT License
694 stars 514 forks source link

#648 invalid race post request #723

Open bkbCodes opened 1 year ago

bkbCodes commented 1 year ago

Directly posting to API creates invalid races : #648

Discord Username: @.d_k5g_1am_go.

What type of PR is this? (select all that apply)

Description

Added data integrity with hashes to patch the stats boost exploit. This PR deals with 9999 average CPM cheat.

Related Tickets & Documents

QA Instructions, Screenshots, Recordings

UI accessibility concerns?

Added/updated tests?

[optional] Are there any post deployment tasks we need to perform?

Check DB schema update

[optional] What gif best describes this PR or how it makes you feel?

GpoGrandPieceOnlineGIF

LuffyLooksDeliciousGIF

webdevcody commented 1 year ago

@bkbCodes I'm not sure I understand what this is doing. Could you explain more how this helps prevent the exploits so as I read through the code it makes more sense?

bkbCodes commented 1 year ago

@webdevcody @scape76 sure, here you go. Starting step is when user completed race and is about to submit it.

Prior to this we directly post the details of race, like, cpm, accuracy, time taken etc. This allowed the exploit of re-sending the same request with updated value such as 10000cpm, 100 accuracy, and to make it work better exploiters also used the newly generated raceID. Since, all details are now legitimate this got accepted, marking the completion of exploit.

Now, instead of submitting it directly we do following:

  1. Get a signature token from DB (unique signature token), used for generating a hash of the race details.
  2. After getting the token, stringfy the race results and create it's hash.
  3. And now we send race result along with its hash.

Now at server side:

  1. We receive the race result with the hash.
  2. Now, server gets the signature token of the user from DB.
  3. We stringfy the received data and create its hash.
  4. Now, we compare both hashes, if equal, then, all is good we proceed forward, else, data is tampered so ignore the request.

This is main working. To make it more robust client will get a token as well as a random number that needs to be add to data before hashing to make it difficult to break. And this random number is stored in DB and client can only read it and server can read it and update it. This part was done to avoid replay attack, say I got an impressive race with 800cpm and 100% accuracy, I can resend this multiple times to boost my overall stats, as hash value will be same if no randomness was present.

@scape76 this is the reason I used getUserTokenAndStamp()