0

Through several threads I can see that the use of the MVC antiforgery token is overkill on areas of a site where a user is not authenticated.

I have an application that posts some information to mysite.com from site1, site2, site3, etc. Each site has a unique identifier that gets sent in the POST request through an asynchronous Javascript POST. The Javascript that is executed on site1-3, is generated on mysite.com, then returned to the sites with some Javascript variables populated.

So the lifecycle is as follows:

  1. A page on site1 has a Javascript reference to mysite.com.
  2. That link reference is to a controller route that generates Javascript to return to site1.
  3. The end of the JS that is returned contains a POST request that goes back to mysite.com containing Url, browser, etc., details for the visitor of the page on site1.

I can read in the POST parameters just fine in the accepting controller from the JS POST request, however, what I wanted to know is if there is any point in adding an antiforgery token to the parameter list.

If so, I would have to generate it on the initial request, and pass it back as a JS variable in the JS returned to site1, then pass it back along with the form POST in the second request.

Since any processing on mysite.com will only occur if a valid account is found, is there any point in going through this?

If so, how would I generate the antiforgery token on at the controller level?

Community
  • 1
  • 1
ElHaix
  • 12,846
  • 27
  • 115
  • 203

1 Answers1

0

I would say that it depends on the sensitivity of the data that is being posted. If another user could cause harm (or annoyance) by crafting forged requests and submitting them, then I would say that it would be appropriate. It sounds like you're just collecting some usage information so that's not likely to be the case.

A one-time, random nonce might be a better solution. That would make it difficult to forge a request and prevent erroneous multiple submits, say from the user using a cached copy. Generate a random value (a GUID might work) on mysite.com, inserting it in the database and marking it as unused. Send it back with the POST. Check whether it has been used or not. If not used, then mark it used and perform your logging action. If it has been used already, discard the request as a duplicate submission.

Note that you wouldn't need a POST for this, a simple GET with URL parameters would be sufficient since the nonce will prevent it from being accidentally repeated.

tvanfosson
  • 524,688
  • 99
  • 697
  • 795
  • I'm actually doing something like this already. Two new GUIDs are created on each request. The first GUID refers to the user - and reads a cookie on the client side. If that visitor's GUID already exists in my DB, then I use their value. If not, set the cookie and add it to the DB. The second GUID is used to track their session (expires in 3 minutes). I'm wondering if these two in combination is sufficient, or go with as you recommended, in this case, create a third GUID that is a request validator (if I'm getting you correctly)? – ElHaix Jan 02 '12 at 15:40
  • I'm not saying that it's strictly necessary, but it does close a hole where a request could be repeated accidentally and also makes it much harder to forge a request. Neither of your two GUIDs do this. A successful attacker could submit thousands of requests with the intercepted user/session GUIDs in 3 minutes. You'd have to weigh the risk of that happening against the complexity of adding the additional one-time nonce. – tvanfosson Jan 02 '12 at 15:50
  • Makes sense. I will add this approach, and like the used/unused concept. Thanks. – ElHaix Jan 02 '12 at 16:05
  • if only we had single use tokens built in. I think its time to add this to http://mvcsecurity.codeplex.com/ – Adam Tuliper Jan 02 '12 at 16:05
  • @AdamTuliper - That would be really nice actually. I'm thinking about the implementation right now, and the issue I foresee is that my RequestToken table will get pretty huge, as each request will have an entry containing the GUID. At how many records do you think it would be safe to clear the table? Leave it populated with say, 100,000 rows of expired request tokens? – ElHaix Jan 02 '12 at 18:13
  • that (and the implementation) is up to you. You could clear daily. Preferably you may want a different cache here to help on the db load. Check out https://github.com/enyim/EnyimMemcached for example for a memcache implementation so as to keep DB pressure down. – Adam Tuliper Jan 02 '12 at 19:40