Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#648 invalid race post request #723

Open
wants to merge 12 commits into
base: main
Choose a base branch
from

Conversation

bkbCodes
Copy link
Contributor

@bkbCodes bkbCodes commented Oct 5, 2023


Directly posting to API creates invalid races : #648

Discord Username: @.d_k5g_1am_go.

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

  • πŸ• Feature
  • πŸ› Bug Fix
  • 🚧 Breaking Change
  • πŸ§‘β€πŸ’» Code Refactor
  • πŸ“ Documentation Update

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?

  • πŸ‘ yes
  • πŸ™… no, because they aren't needed
  • πŸ™‹ no, because I need help

[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

stamp = Math.random().toString(36).substring(2, 7);
signToken = Math.random().toString(36).substring(2, 22);

await prisma.$transaction(async (tx) => {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we need transaction in here?)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is needed for data migration part. To introduce new token field into database. As well as to update token every 7 days to strengthen the security

accuracy: calculateAccuracy(code.length - 1, totalErrors),
snippetId: snippet.id,

getUserTokenAndStamp()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't you think it has to be called on the server?
Otherwise I could get the result of it (tokenAndStamp) in the network tab
and then make a call to saveUserResultAction with invalid cpm amount

@webdevcody
Copy link
Owner

webdevcody commented Oct 22, 2023

@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
Copy link
Contributor Author

bkbCodes commented Oct 23, 2023

@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()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[BUG]: Directly posting to API creates unvalid races
3 participants