How AntiForgeryToken gets invalidated? I have set up this token to prevent CSRF attacks on my login page and have inspected it with fiddler. When i call GET method the token generates as hidden field __RequestVerificationToken. When i post login data should this token be changed on next GET call? I catch with fiddler this value with post data and reissue/replay request and this works. Is this good behavior, or this replay should not happen because token value should not be valid after i leave that form.
Thanks in advance.
The token is tied to a session cookie; when the session goes away and the cookie disappears the token will be rendered invalid. The reason replays work in Fiddler is that Fiddler is capturing (and replaying) both the session cookie and the form token.
You could simulate session expiration by removing the request's Cookie header from within Fiddler before replaying. The server should then reject the form's __RequestVerificationToken field.
Related
In certain flows in my web application I am getting csrf token invalid exception as follows:
HTTP Status 403 - Invalid CSRF Token 'ac6a93fd-6903-40f8-a5e2-00b9e830618b' was found on the request parameter '_csrf' or header 'X-CSRF-TOKEN'.
Here CSRF token is present, it is not null, but invalid.Session did not expire.Faced similar issue as here CSRF token not found and solved the same.
But here I am stuck.
Edit:
This issue crops up when we open multiple tabs in browser and from one of the tabs we logout and from another tab try to login from login page.
Delete browser cookie and try again.
Generally token information is stored in cookie, in your case it seems old csrf token is still being used from cookie.
I wonder how does ASP.NET check if an anti-forgery token is valid or not? Like where is ASP.NET storing those tokens? And how are they stored?
The short version is that a generated token is stored in 2 places: (a) cookie (b) hidden form value. When the form is submitted, these 2 values are compared against each other to determine if they are valid. For further reading:
http://www.asp.net/web-api/overview/security/preventing-cross-site-request-forgery-(csrf)-attacks
http://www.codeproject.com/Articles/793384/ASP-NET-Anti-Forgery-Tokens-internals
A stepwise explanation that is more clear than the accepted answer imho (from https://learn.microsoft.com/en-us/aspnet/web-api/overview/security/preventing-cross-site-request-forgery-csrf-attacks)
The client requests an HTML page that contains a form.
The server includes two tokens in the response. One token is sent as a cookie. The other is placed in a hidden form field. The tokens are generated randomly so that an adversary cannot guess the values.
When the client submits the form, it must send both tokens back to the server. The client sends the cookie token as a cookie, and it sends the form token inside the form data. (A browser client automatically does this when the user submits the form.)
If a request does not include both tokens, the server disallows the request.
The above description is not all what is done, in case of AjaxRequest the antiforgery, specifically in get requests, will not usually send the Form with the hidden value for comparison, instead you will need to set a header value with the same content of the cookie via javascript.. the header name that you should set is by default X-XRF-Token header [related to angularjs] ... of course you will need to disable CORS or enable it for only specific domains to protect the APIs, SAMEORIGIN also need to be set to avoid clickjacking ..
I have an asp.net page i do authentication and authorization of a user and user can make several ajax requests from this page. What i want to ensure is that the request only from this page so i will store some data(or token)(possibly a function of userID + user IP address + current time) encrypted in the page aswell as in the session so the requests that come with this token will only get served. Does anybody have any idea of doing this? Help
You could store it in the ViewState. You will then need to send the value of the ViewState hidden field along with your AJAX request.
I have an asp.net login page, which when initialized sets some session variables. When the user clicks login, an AJAX request is made which validates the user and sets additional session variables and returns a result to the client. The client is then redirected based on the login result. In the redirected page, I can access the session variables set when the login page was initialized (i.e. before the login) but none are present for those set during the login validation (part of an ajax call).
is this expected behaviour? Why would an ajax call generate a new session and thus cause the data to be lost?
Thanks
Is the location for your ajax call in the same application space as the rest of the application?? If I remember right you can't share session information between applications. That may be what's going on.
Normally the browser sends the sends the session id along with ajax requests. If you use Firebug or something similar you can view the contents of the ajax request and check if the session id is sent along.
The session id is stored in a cookie, which (depending on options) can only be used for the same domain/host name. This could be a reason why it is not sent.
Depending on your code, I guess that if no session id was sent a new one is created.
The session id is stored in a cookie, which is returned in the header of the response. As you are doing an AJAX call, the cookie is just part of the response. If you want to use the same session for another request, you have to get that cookie and send it along in the header of the request.
I use a ASP.Net login control in a straightforward manor however I have spotted that the ASPXAUTH cookie has an expiry date of {01/01/0001 00:00:00}. Should this not get to something to prevent hacker manipulation? I am not issuing the cookie myself I am letting .Net create it.
I have run a scan on my web app and it is able to store the ASPX cookie information, go to the log out page and then go to a page without a need to login I assume using the stored cookie information.
Using the application manually I am unable to do this, it always sends me to the login page when trying to access the page.
The logout page calls FormsAuthentication.SignOut()
EDIT: Turns out this is a known problem! Who knew! http://support.microsoft.com/kb/900111
You cannot read the cookies expiration date and time. The browser uses the cookies expiration date to determine whether or not to send the cookie to the server. If a cookie has expired, the browser does not send that cookie to the server with the page request, the cookie is deleted.
If the cookie has not expired the cookie is sent to the sever sans expiration information, since this information is utilized by the browser to determine if the cookie should be sent or not. You can read the expiration date from the request, but as you have discovered it returns a date time value of zero.
Try checking the expiry date of Response.Cookies collection in the LoggedIn event. This should yield the correct expiry date of the cookie.
protected void Login1_LoggedIn(object sender, System.EventArgs e)
{
HttpCookie cookie = Response.Cookies(".ASPXAUTH");
DateTime expires = cookie.Expires;
}
See Basics of Cookies in ASP.NET for more information.
If you save the value of the cookie, log out, and then re-present that cookie to the server, it will just log you in automatically as if you had never logged out.
This is because you can also tell the .NET framework to set a persistent authentication cookie (by default you can present this option to the user with the "Remember Me?" checkbox exposed with the DisplayRememberMe property of the Login control) so the expiry date would be a value in the future.
When the user comes back to the site and their browser sends the cookie, they are automatically logged in - so the behaviour you're seeing is be design.
If you need to be more secure, the easiest thing to do is add a method to the OnLoggedIn event of the login control, and set a session value (i.e. Session.Add("HasLoggedIn", true)) that you can then check elsewhere, and if it's not true, redirect to the login page:
if (null == Session["HasLoggedIn"] || !(bool)Session["HasLoggedIn"]) {
FormsAuthentication.RedirectToLoginPage();
}
Edit to respond to comment:
Which is why you're seeing the expiry date of 01/01/0001 00:00:00 - this will be deleted at the end of your session - or when you close the browser - but there's nothing fundamentally wrong with what you're seeing - just because you're not setting a persistent cookie doesn't mean that if you send a copy of an old cookie back to the server it won't log you in with it.
As I said, if you want to ensure that users have to log in each time (or to "resolve" this issue), add a session variable that you set when the user actually logs in, and reject all requests without it.
Further edit for second comment
From Explained: Forms Authentication:
Each time a subsequent request is received after authentication, the FormsAuthenticationModule class retrieves the authentication ticket from the authentication cookie, decrypts it, computes the hash value, and compares the MAC value to help ensure that the cookie has not been tampered with. Finally, the expiration time contained inside of the forms authentication ticket is verified.
Note ASP.NET does not depend on the expiration date of the cookie because this date could be easily forged.
So the cookie has to sent back to the server before the ticket has expired.