Using the MVC3 AntiForgeryToken in non-authenticated scenarios? - javascript

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:
A page on site1 has a Javascript reference to mysite.com.
That link reference is to a controller route that generates Javascript to return to site1.
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?

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.

Related

Quiz application in .NET MVC/JS/JQUERY, how to prevent cheating?

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.
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.
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.

How can I go to an html page while passing a hidden parameter using Javascript or jQuery?

Upon completion of an ajax call I would like to direct the user to an html page, but at the same time passing a hidden variable (this variable contains sensitive information and should not show up in the URL).
How can I accomplish this?
window.location.href = 'userpage.html?id=14253';
But with the id remaining invisible? Can I POST the id somehow while sending the user to userpage.html?
You should not be checking user credentials on the client side of your website. Regardless of how the ID is being passed to your script, it can be replicated without you being able to check if the request is valid.
To start being even remotely secure with what information is granted to a user, you need to be checking it via the server side. With every request, ensure the user is authenticated to view such data.
If I were you, I would look into using PHP sessions as the first line of defense for checking if a user is authenticated. Doing so will at least keep the information about a user out of a replicable space that can be viewed by the user.
Look up 'php session login tutorial' on Google and you will find plenty of simple tutorials which should get you on the right track.
Example Tutorial
No matter what, the information you pass along is insecure. You can submit a post request using XMLHttpRequest objects if you'd like (or use a framework/library to make AJAX calls) -- but the user could still spoof the data and get different results.
ID enforcement should be done in the backend. Does the requested ID match the ID of the user signed in? No? Don't show it. etc etc.

detecting if a request is a post in jQuery

I'm trying to load a page differently if it is a post or a get, and seems like jQuery would have something so I could do
if (isPost())
{
// do something if this page was a post
}
I'm showing/hiding something based on the request type and want to do it specifically with javascript. I can easily do it with the framework I'm using, but don't want to.
The problem here is that you are confusing client-side with server-side.
GET, POST, PUT, DELETE, etc are all HTTP 'methods' that are sent to a server from the client (e.g.: the browser). The server then responds with the appropriate HTTP response, normally in the form of content that contains HTML.
POST/GET/etc have no context at the client side outside of dictating how a request should be sent to the server.
Think of the browser being your postal mailbox and POST/GET/etc being the method it was delivered. When someone sends you a piece of mail, they specify the method, such as first-class mail, overnight express, or same-day delivery. The Post Office handles the mail based on how it was received and sends the mail using the appropriate action. When you pick up your mail in the mailbox, you don't know if it got there via standard mail, overnight express, or same-day delivery. The only way you would know is any information that is on the envelope itself.
The solution to your problem would would follow this same principal. To resolve it, what you will need to do is include a hidden value that jQuery can pull in, either in the query-string, a special element, or as a hidden textbox that contains the HTTP method used to get the page.
This requires that server-side code be changed accordingly to push that information back to the client.
Hope that helps clear it up a bit.
i don't know if this is really possible in javascript. But you can check if there is a query string which is GET in the URL
if (location.search.length > 1) {
// your code.
}
location.search returns the query string in the URL
http://example.com/index.html?id=1&value=3
in this case location.search will be ?id=1&value=3 including the question mark.
so if it is present then you have a GET

request parameters ordering undefined [in multipart/form-data or in general] - what to do?

I am writing a web application that submits a form (one of its fields is mulitpart/form-data, so obviously POST must be used and not GET, since the files might be really big). One of the fields is kinda transaction/upload_id and the other is obviously the file contents. While uploading, a progress bar must be displayed.
The known fact says that the order of parameters is undefined in general, meaning that any of (file content / upload_id) might come first.
Is there any acceptable / recommended way to cause the browser to send the upload_id before sending the file content?
Is it a considered a correct implementation - to expect the upload_id to come first OR there is a better / most common / more correct way to handle the problem? In that case - it would be fantastic to hear some details.
Update: my server-side language is Java/Servlets 3.0
Well, the better answer (without utilizing filters) would be to publish the upload_id(s) as a part of the URL (after '?'), even when issuing a POST request. In that case, they will be always processed ahead of files' contents.
Using servlets as well, and in my case I wanted to run my CSRF filter in my servlet before I started streaming the file: if the filter failed, I can kill the request before I've uploaded my 20gb video file, as opposed to the default PHP implementation where the server only hits your script AFTER its parsed the entire request.
Its been a bit of a hack on my part, but in the couple of cases I've had to do this I've cheated and put the non-file request parameters into the URL and in every case (using pretty much every browser I've tested with) an Iterator over the request parameters on the server (I'm using commons fileupload in streaming mode) has received the non-file request parameters first before the file data was received. Somewhat fragile, but not unworkable.
I'm assuming that if you order your request parameters with the file <input> as the last item you'll get the same behavior.
You shouldn't have to worry about the order in which the parameters are sent. If so, then your server-side code is very brittle.
A multi-part request will contain the field name of every form field that is passed in. Use the name to reference that field regardless of the order it was sent in.
If you are parsing the post body by hand, I suggest you look at existing projects like Apache FileUpload which abstract that away.

How to prevent direct access to my JSON service?

I have a JSON web service to return home markers to be displayed on my Google Map.
Essentially, http://example.com calls the web service to find out the location of all map markers to display like so:
http://example.com/json/?zipcode=12345
And it returns a JSON string such as:
{"address": "321 Main St, Mountain View, CA, USA", ...}
So on my index.html page, I take that JSON string and place the map markers.
However, what I don't want to have happen is people calling out to my JSON web service directly.
I only want http://example.com/index.html to be able to call my http://example.com/json/ web service ... and not some random dude calling the /json/ directly.
Quesiton: how do I prevent direct calling/access to my http://example.com/json/ web service?
UPDATE:
To give more clarity, http://example.com/index.html call http://example.com/json/?zipcode=12345 ... and the JSON service
- returns semi-sensitive data,
- returns a JSON array,
- responds to GET requests,
- the browser making the request has JavaScript enabled
Again, what I don't want to have happen is people simply look at my index.html source code and then call the JSON service directly.
There are a few good ways to authenticate clients.
By IP address. In Apache, use the Allow / Deny directives.
By HTTP auth: basic or digest. This is nice and standardized, and uses usernames/passwords to authenticate.
By cookie. You'll have to come up with the cookie.
By a custom HTTP header that you invent.
Edit:
I didn't catch at first that your web service is being called by client-side code. It is literally NOT POSSIBLE to prevent people from calling your web service directly, if you let client-side Javascript do it. Someone could just read the source code.
Some more specific answers here, but I'd like to make the following general point:
Anything done over AJAX is being loaded by the user's browser. You could make a hacker's life hard if you wanted to, but, ultimately, there is no way of stopping me from getting data that you already freely make available to me. Any service that is publicly available is publicly available, plain and simple.
If you are using Apache you can set allow/deny on locations.
http://www.apachesecurity.net/
or here is a link to the apache docs on the Deny directive
http://httpd.apache.org/docs/2.0/mod/mod_access.html#deny
EDITS (responding to the new info).
The Deny directive also works with environment variables. You can restrict access based on browser string (not really secure, but discourages casual browsing) which would still allow XHR calls.
I would suggest the best way to accomplish this is to have a token of some kind that validates the request is a 'good' request. You can do that with a cookie, a session store of some kind, or a parameter (or some combination).
What I would suggest for something like this is to generate a unique url for the service that expires after a short period of time. You could do something like this pretty easily with Memcache. This strategy could also be used to obfuscate the service url (which would not provide any actual security, but would raise the bar for someone wanting to make direct calls).
Lastly, you could also use public key crypto to do this, but that would be very heavy. You would need to generate a new pub/priv key pair for each request and return the pubkey to the js client (here is a link to an implementation in javascript) http://www.cs.pitt.edu/~kirk/cs1501/notes/rsademo/
You can add a random number as a flag to determine whether the request are coming from the page just sent:
1) When generates index.html, add a random number to the JSON request URL:
Old: http://example.com/json/?zipcode=12345
New: http://example.com/json/?zipcode=12345&f=234234234234234234
Add this number to the Session Context as well.
2) The client browser renders the index.html and request JSON data by the new URL.
3) Your server gets the json request and checks the flag number with Session Context. If matched, response data. Otherwise, return an error message.
4) Clear Session Context by the end of response, or timeout triggered.
Accept only POST requests to the JSON-yielding URL. That won't prevent determined people from getting to it, but it will prevent casual browsing.
I know this is old but for anyone getting here later this is the easiest way to do this. You need to protect the AJAX subpage with a password that you can set on the container page before calling the include.
The easiest way to do this is to require HTTPS on the AJAX call and pass a POST variable. HTTPS + POST ensures the password is always encrypted.
So on the AJAX/sub-page do something like
if ($_POST["access"] == "makeupapassword")
{
...
}
else
{
echo "You can't access this directly";
}
When you call the AJAX make sure to include the POST variable and password in your payload. Since it is in POST it will be encrypted, and since it is random (hopefully) nobody will be able to guess it.
If you want to include or require the PHP directly on another page, just set the POST variable to the password before including it.
$_POST["access"] = "makeupapassword";
require("path/to/the/ajax/file.php");
This is a lot better than maintaining a global variable, session variable, or cookie because some of those are persistent across page loads so you have to make sure to reset the state after checking so users can't get accidental access.
Also I think it is better than page headers because it can't be sniffed since it is secured by HHTPS.
You'll probably have to have some kind of cookie-based authentication. In addition, Ignacio has a good point about using POST. This can help prevent JSON hijacking if you have untrusted scripts running on your domain. However, I don't think using POST is strictly necessary unless the outermost JSON type is an array. In your example it is an object.

Categories

Resources