2

I'm making a quiz application, where 4 users join a lobby (finished), and then the leader starts the quiz.

When the quiz is started, questions get randomly selected. Users can answer them, and click submit. Each question is timed, meaning user only has 10 seconds to answer the question.

This is all done through AJAX, since I want the website to be real-time. How exactly would I prevent cheating? User could manually edit the JS file, etc.

I was thinking of getting the exact time when the question gets loaded + the answer time. And if it's not in the span of 10 seconds, he's cheating. Would that work, or is there a better and easier way to do this?

Thank you.

Ashley
  • 133
  • 2
  • 7
  • Use Anti Forgery Tokens to prevent side scripting. If the built in one in the ASP.Net MVC framework does not suite your need, then you have to create your own. – Transcendent Sep 02 '17 at 17:57
  • 2
    @Ashley, my understanding is Anti Forgery tokens can prevent Cross-site scripting but it's not clear to me how can this prevent a hacker to tamper the DOM using inspection tool, e.g. replacing event handlers and unbinding old ones. What you mentioned seems reasonable. Move sensitive logics to server side, choose next question there and track timing for preventing cheating. – derloopkat Sep 02 '17 at 18:21
  • @derloopkat Yeah, I have exactly the same question. Since both answers offered the result using Anti Forgery tokens, do they prevent tampering with the code using inspection tools, etc? – Ashley Sep 02 '17 at 19:21

2 Answers2

1

Edit

I thought AntiForgeryToken was right solution to solve your problem. I read a lot of articles to make sure my old answer is correct.

1- Hiding or Encrypting the javascript source code

2- How to Disable HTML view source or Encrypt Html elements programatically?

3- How To Prove That Client Side Javascript Is Secure?

4- ASP.NET MVC - does AntiForgeryToken prevent the user from changing posted form values?

I came to the conclusion:

AntiForgeryToken prevents a malicious site to trick a user to a form that looks the same as the original and post it to the original site. It does not prevent the scenario you are describing.

There's really no way to do this completely client-side. If the person has a valid auth cookie, they can craft any sort of request they want regardless of the code on the page and send it to your server.

You can use HtmlHelper.AntiForgeryToken with salt value.

To use these helpers to protect a particular form, put an Html.AntiForgeryToken() into the BeginForm, e.g.,

@using (Html.BeginForm("Users", "SubmitQuiz"))
{
    @Html.AntiForgeryToken()
    <!-- rest of form goes here -->
}

This will output something like the following:

<form action="/Users/SubmitQuiz" method="post">
    <input name="__RequestVerificationToken" type="hidden" value="saTFWpkKN0BYazFtN6c4YbZAmsEwG0srqlUqqloi/fVgeV2ciIFVmelvzwRZpArs" />
    <!-- rest of form goes here -->
</form>

Next, to validate an incoming form post, add the [ValidateAntiForgeryToken] filter to your target action method. For example,

[ValidateAntiForgeryToken]
public ViewResult SubmitQuiz()
{
    // ... etc
}

Salt is just an arbitrary string. A different salt value means a different anti-forgery token will be generated. This means that even if an attacker manages to get hold of a valid token somehow, they can’t reuse it in other parts of the application where a different salt value is required.

You can create different salts for different users like this.

Edit

AntiForgeryToken() prevents tampering with the code using inspection tools like this:

In Client side

1- A new random anti-XSRF token will be generated.

2- An anti-XSRF field token is generated using the security token from step (1).

In Server side (Validating the tokens)

1- The incoming session token and field token are read and the anti-XSRF token extracted from each. The anti-XSRF tokens must be identical per step (2 client side) in the generation routine.

2- If validation succeeds, the request is allowed to proceed. If validation fails, the framework will throw an HttpAntiForgeryException.

For more information this, Please see this article.

Ali Soltani
  • 9,589
  • 5
  • 30
  • 55
  • @Ashley I added edit portion to my answer to explain why it prevents tampering with the code using inspection tools. Please see this. – Ali Soltani Sep 02 '17 at 20:15
  • 1
    This has nothing to do with the question. –  Sep 02 '17 at 23:12
  • @StephenMuecke Thank you for comment. I edited my answer. Thanks if you tell me about edited answer. – Ali Soltani Sep 03 '17 at 07:43
  • I never asked for a specific client side solution. Even in my original post, I'm describing a server side solution by submitting the time when the initial page loads, and submitting it when the user submits the answer. I still don't know if there are any other solution, or if this one is even viable, since I don't know exactly how to POST these 2 DateTime's without them being to able tamper with them. – Ashley Sep 03 '17 at 07:56
1

Conclusion: Since there's no way to prevent anything on the client side, the only solution that actually sounds okay is having server check everything.

A GET request, which requests the question and logs the time. After that, a JS timer which automatically submits the question if the countdown is finished. The user can also manually submit the answer (obviously). POST of the answer, and the server logs the time of it, compares it to the initial time of the GET request. If it's longer than 10 seconds, it throws and error, and the answer is not counted.

Thank you everyone.

Ashley
  • 133
  • 2
  • 7