Does it make sense to put antiforgerytoken in _Layout.cshtml? - ajax

I'm developing an ASP.NET MVC application and I'm planing to protect each non GET request (POST, PUT, DELETE, etc...) with AntiForegeryToken.
I've implemented an extension of the classical AntiForgery verification based on the [__RequestVerificationToken] sent in the header. This because most of my calls are async ($.ajax()) and it turns out easier for me to send the hidden field value that way.
Does it make sense to put one single #Html.AntiForgeryToken() in the _Layout.cshtml (template for all pages) and always refer to that one only ?
I've tryed to understand what wolud be different beteen this option and putting it in each form (that I don't use much since my requests are pretty much all async), but I haven't.
Can anyone clear this to me ?
Thanks
Lorenzo

You can put it in your _Layout.cshtml and generate a single token when the page is rendered, that's fine.
While there is a very slight security benefit of using a different token for every request, if your token has enough entropy (and the standard token generated by #Html.AntiForgeryToken() does), then it is practically infeasible for an attacker to guess the token even during the time of a user session. So one token per user session is still considered secure in most cases.
Actually, trying to use a new token for each request leads to all kinds of bugs in a Javascript heavy application, because the browser needs a non-neglectible time to actually change things like a cookie value or to send a request, and frequent ajax requests will lead to a race condition and you will have hard to debug bugs around token mismatches.
ASP.NET MVC still focuses on traditional form-based applications in this regard, and while you can use it to prevent CSRF in modern Javascript-heavy apps with some tweaks (like a custom attribute to actually verify a token sent in request headers), you do have to write some custom code to do that. Hopefully Microsoft will add built in support in future versions.
UPDATE
After implementing the solution with #Html.AntiForgeryToken() directly in Template page (_Layout.cshtml) I found out a possible problem bound to the use of custom Claims. The problem happens during re-validation of UserIdentity. As a reference I'll leave the link to another post in which I've been dealing with that and added there the wotrkaround for those who choose the same implementation.
Custom Claims lost on Identity re validation
Hope it helps !

Related

Dynamically Update Page in Application Requiring Authentication Via Azure AD

I am curious if anyone has a solution to this unique situation as I have a solution currently, though I feel it is not the most optimal.
The Situation.
I have built an MVC style web application that talks to a web API through http (authenticating via JWT). My web application is secured by appending authorization to its view controllers and redirecting to a Microsoft login endpoint - then directing back to the view where whichever given controller/function handles the request, connects to the API, appends data to the view, etc.
Preferably I would like to use JQuery/Ajax to submit http requests client-side and update a given view with whatever data the user may wish to see relative to the webpage they're on. This way I could control exactly what the user should see landing on the page any which way and submitting requests from web app to API. Also would enable better continuity between requests as there isn't actually a full refresh of the view. All in all it is my line of thought that this execution would lead to a nice user experience.
The Problem.
So the big issue that I have had to circumvent is CORS Policy. I initially attempted to use JS just as I said above but requests would be redirected to the login endpoint and blocked due to there being no CORS header appended to the request.
'So include a policy in your application and append an authorized header to your Ajax outgoing request' you might say, well... you cannot override CORS security around Microsoft's login endpoint.
My Solution.
What I have done simply instead is create HTML Forms around fields the user would pick and chose to specify what data they wanted from the API. Then carry over input data to the returned view via 'ViewData'
and using razor pages of course I can actually initialize JS variables via C# input.
Side Note
I use JS to transform the API data into graphs for the user to see. I am doing this with a JavaScript Library.
My Question to you.
This all leads me to ask then, is there a way to dynamically update a view without using JS? I require a method that can hit the login redirect without being blocked because the request initiated client-side.
Every solution I am aware in some way, shape, or form utilizes JS to make the request. So I am at a loss for how to truly get the functionality I am after without having my requests get blocked due to CORS Policy.
Thanks in advance y'all.

AntiForgeryToken without forms authentication

We have a website that uses MVC3 and a custom authentication method that does not rely on forms authentication at all -- at least from what I can tell. In web.config we set
<authentication mode="None"></authentication>
and we never use/set HttpContext.User anywhere in code. The problem is when using #Html.AntiForgeryToken() in some cases the user gets this error message:
A required anti-forgery token was not supplied or was invalid
We centralize all anti-forgery checks in OnAuthorization with this code:
if (String.Compare(filterContext.HttpContext.Request.HttpMethod, "post", true) == 0)
{
var forgery = new ValidateAntiForgeryTokenAttribute();
forgery.OnAuthorization(filterContext);
}
That is where the exception occurs. We have defined a machineKey in web.config to prevent new keys being generated when the application pool recycles. This did not fix the problem.
Next we thought that maybe the client's browser is not sending cookies. We started logging cookies and noticed that in some cases the RequestVerificationToken_Lw cookie is sent, but in others is not -- even though other cookies, like the ones made by Google Analytics, are sent along just fine. Could it be something in the browser is stripping out some cookies and leaving others in?
It seems like the anti-forgery token depends on forms authentication. Is this the case? Any way to keep using the AntiForgeryToken when not using forms authentication in a reliable way. Keep in mind that the method I described above works for more than 90% of cases, but we can't pinpoint why it doesn't work for some people.
Thoughts?
Thanks!
Do some users have this issue all the time? Or just some of the time? Also, does it work for some of the methods ALL the time or is it inconsistent for the same action method? Do you have any ajax calls? The default anti-forgery token implementation does not handle AJAX calls. But you can write some custom code to get it to work
Are you adding the antiforgery token inside of the form? The antiforgery token is stored on the client via a hidden HTML element so and not as a cookie. The other question would be what browser version are they using? Are can the upgrade to the latest?
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()...

anti-CSRF token and Javascript

I'm trying to protect an application (php and lots of JS) from CSRF.
I want to use tokens.
A lot of operations are done with AJAX, so I have to pass the token in Javascript.
If I want to generate 1 token per session or per page load it's simple - I generate new token, put it somewhere in a DOM and then find it with Javascript and send to the processing side.
But what if I want to use new token for every operation?
I was thinking about doing an ajax call to regenerate token and then pass the result to processing page.
Does this increase security risk?
I was thinking about luring user to page with script which would ask for token and then use it to make the request but then again cross domain Javascript is forbidden.
Can it be done with flash?
Maybe another approach for protecting ajax calls from CSRF?
Thanks!
There are several techniques, which when used together provide a sufficient CSRF protection.
Unique Token
A single, session-specific token is good enough for most applications. Just make sure that your site doesn't have any XSS vulnerabilities, otherwise any kind of token technique you employ is a waste.
AJAX call to regenerate the token is a bad idea. Who will guard the guards? If the AJAX call itself is vulnerable to CSRF, it kind of defeats the purpose. Multiple tokens with AJAX are in general bad idea. It forces you to serialize your requests i.e. only one AJAX request is allowed at a time. If you are willing to live with that limitation, you can perhaps piggyback token for the second AJAX call in response to the first request.
Personally, I think it is better to re-authenticate the user for critical transactions, and protect the remaining transactions with the session-specific token.
Custom HTTP header
You can add a custom HTTP header to each of your requests, and check its presence on the server side. The actual key/value doesn't need to be secret, the server just needs to ensure it exists in the incoming request.
This approach is good enough to protect CSRF in newer versions of the browsers, however its possible too work-around this if your user has older version for Flash Player.
Checking Referrer
Checking for the Referrer header is also good to protect CSRF in the newer browsers. Its not possible to spoof this header, though it was possible in older versions of Flash. So, while it is not foolproof, it still adds some protection.
Solving Captcha
Forcing the user to solve a captcha is also effective against CSRF. Its inconvenient as hell, but pretty effective. This is perhaps the only CSRF protection that works even if you have XSS vulnerabilities.
Summary
Use a session based token, but re-authenticate for high value transactions
Add a custom http header, and also check for referrer. Both are not foolproof by themselves, but don't hurt

Secure ajax form POST

I was wondering how to develop a secure form post through AJAX.
For example, i have:
My HTML form.
My JavaScript handling the submit.
The submit url is "post_data.php"
The posted data is:
id=8&name=Denis
The PHP verifies if variables id and name are POSTED and their data type. If this is ok it proceed to do some stuff on a database.
My question is, how can i prevent someone from creating his own html form, outside my web site, or whatever, and posting false data to my PHP script?
Imagine that data realy exists on my database, this could be bad.
Thanks
One very common way to do this is to have a token of some kind included in a <hidden> field on your form, and the same one saved in a session variable (or somewhere else) on your server. When the post is submitted, you check that the token is valid.
Someone else could still forge a token, but they can't (in any easy way, at least) force you to save the same token on your server, so no other form than your own will be accepted.
This is, for example, how the built-in support for this in ASP.NET MVC works.
The token method is probably the most effective way. With that said, you should never assume that the data is coming from your own form even once you have these other security measures in place. Validating data will always be important.

Securing AJAX Requests via GUID

I'm writing a web app that will be making requests via AJAX and would like to lock down those calls. After a little research, I am considering using some form of random token (string) to be passed back along with the request (GUID?). Here's the important parts of my algorithm:
Assign a token to a JavaScript variable (generated server-side).
Also, store that token in a DB and give it a valid time period (i.e. 10 minutes).
If the token has still not been used and is within it's valid time window, allow the call.
Return requested information if valid, otherwise, log the request and ignore it.
With an eye toward security, does this make sense? For the token, would a GUID work - should it be something else? Is there a good way to encrypt variables in the request?
EDIT:
I understand that these AJAX requests wouldn't be truly "secure" but I would like to add basic security in the sense that I would like to prevent others from using the service I intend to write. This random token would be a basic, front-line defense against abusive calls. The data that would be requested (and even submitted to generate such data) would is HIGHLY unlikely to be repeated.
Maybe I'm wrong in using a GUID... how about a randomly generated string (token)?
If you are doing this to trust code that you sent to the client browser, then change direction. You really don't want to trust user input, which includes calls from js that you sent to the browser. The logic on the server should be made so that nothing wrong can be done through there. That said, asp.net uses a signed field, you might want to go that way if absolutely necessary.
Expanding a bit:
Asp.net tamper-proofs the viewstate, which is sent as a html hidden field (depending on the configuration). I am sure there are better links as reference, but at least it is mentioned on this one: http://msdn.microsoft.com/en-us/library/ms998288.aspx
validation. This specifies the hashing
algorithm used to generate HMACs to
make ViewState and forms
authentication tickets tamper proof.
This attribute is also used to specify
the encryption algorithm used for
ViewState encryption. This attribute
supports the following options:
SHA1–SHA1 is used to tamper proof
ViewState and, if configured, the
forms authentication ticket. When SHA1
is selected for the validation
attribute, the algorithm used is
HMACSHA1.
A link for the .net class for that algorithm http://msdn.microsoft.com/en-us/library/system.security.cryptography.hmacsha1.hmacsha1.aspx.
Update 2:
For tamper-proofing you want to sign the data (not encrypt it). Note that when using cryptography in general, you should really avoid using a custom implementation or algorithm. Regarding the steps, I would stick to:
Assign a token to a JavaScript variable (generated server-side). You include info to identify the request and the exact date&time where it was issued. The signature will validate the server side application issued the data.
Identify double submits if appropriate.
That said, the reason asp.net validates the viewstate by default, is because devs rely on info coming in there as being handled only by the application when they shouldn't. The same probably applies for your scenario, don't rely on this mechanism. If you want to evaluate whether someone can do something use authentication+authorization. If you want to know the ajax call is sending only valid options, validate them. Don't expose an API at granularity level than the one where you can appropriately authorize the actions. This mechanism is just an extra measure, in case something slipped, not a real protection.
Ps. with the HMACSHA1 above, you would instantiate it with a fixed key
It really depends on what you're trying to accomplish by security. If you mean prevent unauthorized use of the HTTP endpoints there is very little you can do about it since the user will have full access to the HTML and JavaScript used to make the calls.
If you mean preventing someone from sniffing the data in the AJAX requests then I would just use SSL.
A GUID used in the way that you're suggesting is really just reinventing a session id cookie.
"Securing" is kind of a vague term. What exactly are you trying to accomplish? Using a GUID is a perfectly fine way to prevent duplicate submissions of the same request, but that is all.
If the information being passed between the client and server is truly sensitive, you should do it over HTTPS. That's really the only answer as far as securing the actual communication is concerned.
Edit: To answer your question regarding whether a GUID is the "right" way - there is no right way to do what you're suggesting. Using any token, whether it's a GUID or something of your own creation, will not have any effect other than preventing duplicate submissions of the same request. That's it.

Resources