I have an asp.net web form. when a user authenticate, it create a Secured cookie called .aspxauth
uppon logout, I call these 2 methods
FormsAuthentication.SignOut();
Session.Abandon()
Problem is that we had penetration test and if I steal the cookie, logout and manually reinsert the cookie, I become loggued in again. So the .aspauth isn't invalidated server side.
I've googled it and I can't find the answer to that security breach.
Microsoft has acknowledged this issue here: https://support.microsoft.com/en-us/kb/900111
They offer several ideas for mitigating this vulnerability:
protect the application by using SSL
Enforce TTL and absolute expiration
Use HttpOnly cookies and forms authentication in ASP.NET 2.0
Use the Membership class in ASP.NET 2.0
Regarding the last one, I'll paste the contents from the site for convenience/preservation:
When you implement forms authentication in ASP.NET 2.0, you have the option of storing user information in a Membership provider. This option is a new feature that is introduced in ASP.NET 2.0. The MembershipUser object contains specific users.
If the user is logged in, you can store this information in the Comment property of the MembershipUser object. If you use this property, you can develop a mechanism to reduce cookie replay issues in ASP.NET 2.0. This mechanism would follow these steps:
You create an HttpModule that hooks the PostAuthenticateRequest event.
If a FormsIdentity object is in the HttpContext.User property, the FormsAuthenticationModule class recognizes the forms authentication ticket as valid.
Then, the custom HttpModule class obtains a reference to the MembershipUser instance that is associated with the authenticated user.
You examine the Comment property to determine whether the user is currently logged in.
Important: You must store information in the Comment property that indicates when the user explicitly signed out. Also, you must clear the information that is in the Comment property when the customer eventually signs in again.
If the user is not currently logged in as indicated by the Comment property, you must take the following actions:
Clear the cookie.
Set the Response.Status property to 401.
Make a call to the Response.End method that will implicitly redirect the request to the logon page.
By using this method, the forms authentication cookie will only be accepted if the user has not been explicitly signed out and the forms authentication ticket has not yet expired.
Read this article about Session fixation and how to get rid of it once and for all:
http://www.dotnetfunda.com/articles/show/1395/how-to-avoid-the-session-fixation-vulnerability-in-aspnet
This remains an issue in .NET Framework. Everyone seems to think Session.Abandon() is the answer, but the sad truth is that command does not invalidate the session on the server's side. Anyone with the right token value can still resurrect a dead session, until the session expires based on the Web.config settings (default = 20minutes).
A similar questioner posed this question a long time ago here:
Session Fixation in ASP.NET
Most of those links are dead, and Microsoft has no new news on the topic.
https://forums.asp.net/t/2154458.aspx?Preventing+Cookie+Replay+Attacks+MS+support+article+is+now+a+dead+link
Worse still, you're still vulnerable to this cookie replay attack even if you're implementing a completely stateless MVC application and don't use the Session object to store data between views. You can even turn off session state in the web.config settings and still replay cookies to gain access to a logged-out session.
The true solution is hack-y and described here, and you need to have session data enabled InProc to use it.
When the user logs in, set a boolean value in the session data, like Session["LoggedIn"] = true;, which is stored on the server side.
When the user logs out, set that value to false.
Check the session value on every request--an attacker trying to replay a session isn't going to be nice to you and come in through the Login page only. It's probably easiest to do this using a custom filter and registering it globally in the global.asax file (so you don't have to duplicate the code everywhere, or attribute every controller/method).
Even if the attacker has all the cookie values, they won't be able to re-use that same session ID, and the server will automatically delete it once it reaches the specified timeout.
if you are using the FormsAuthentication, you can use this code. By using this code you can destroy the created cookies by setting the Expire property of HttpCookie. It will help you:
FormsAuthentication.SignOut();
Session.Clear();
Session.Abandon();
Session.RemoveAll();
// clear authentication cookie
HttpCookie httpCookie = new HttpCookie(FormsAuthentication.FormsCookieName, "");
httpCookie.Expires = DateTime.Now.AddYears(-1);
Response.Cookies.Add(httpCookie);
Related
I'm working on a project with Asp.Net MVC 5 and Asp.Net Identity and I'm using two factor authentication. For the login I use:
var result = await SignInManager.TwoFactorSignInAsync(model.Provider, model.Code, isPersistent: model.RememberMe, rememberBrowser: model.RememberBrowser);
which is the default code that came with the new project. However, I also need the ability for a user to "trust" or "remember" a browser, similar to how banks can indicate if this was the first time you have signed in from a particular browser/pc.
My question is around the RememberBrowser property on the sign in method and what .NET Identity does with this data. I want the list of saved browsers and the ability to revoke access to one/and-or all of them. Is that possible within the Identity framework? Also, can I tell if a browser has been "trusted" before by some type of lookup?
Edit:
Maybe it's a good idea to save the browser info in the database and check on login instead of the cookie? That way it can be shown as a list with the ability to delete it. What I'm looking for is what to save and how to integrate it with the Asp.Net Identity without having a security risk.
Edit 2
Here's an example from a website that is already using this:
Edit 3
Maybe this can be implemented as another step for authentication. So basically we'll have a 3 factor authentication:
First user logs in with user/pass
Then we'll check if the 2FA is enabled and get the code if necessary
We get the user's aser agent and IP and check the database if it's new. Then notify if necessary.
So I'm guessing an new cookie should be added to save browser's info. However, we should be able to invalidate this cookie along with the 2FA cookie.
RememberBrowser sets a cookie that allows the 2FA step to be skipped. There is no central way to track this though it would be easy enough to log, however the results may not be accurate because people can delete cookies manually. There's no way to invalidate it I believe but it doesn't really matter as you can invalidate their session and the user is will be required to login with their password again.
Not sure whether saving browser info adds value as browser info is gonna be same for different users (using same browser and version) unless you save requestor IP as well; and saving requestor IP has too many complications.
How about adding a custom claim to the token if user has set RememberBrowser and then do your logic based on this custom claim? For eg, set a custom claim your_claim_name and set a Guid.NewGuid() to it if RememberBrowser is true. Also save the username, this guid and status flag in database . When a request comes, check whether your custom claim is present, if yes query the table with the custom claim value and username to check whether the entry is still active.
You can either delete the entry or soft delete (set the status) the entry for an user so that when next request comes you can perform your required logic.
I am very confused in my implementation of sessions in asp.net web application. My logic is once user enters user name+password, I validate credentials and then create a new session with some user info[All I am after from this point onward is that this user has access to restricted resources and a user must never be able to access those resources unless he/she is authenticated]. This I validate on each request and the rest. Here is my issue though. I have many places in the website where I have html links, and I read that if I have a link such as
<a href='resource1.aspx'>resource 1</a>
This will generate a new session id, hence in reality invalidating the existing session id, which in my case will be treated as session expired and user is sent to login page. While reading up on this issue I came across an asp.net API method[
Response.ApplyAppPathModifier(url);
] which prepends the session id to each request hence resolving the new session id generation for each link. Though it resolves session breaking issue it does add the session id next to all of the urls and now session id can be seen in the source code( view source for web page). I really don't want to use cookies and want to use session for user sessions...Can some one please help me create a system which will work the way I wish it to ? if I am doing it utterly incorrect, I would really really appreciate a details discussion and if possible some example...Thanks you much in advance..
It looks like you are trying to use cookieless sessions which add a session id to all links in order to be able to track the sessions.
The other (much more common, standard and IMO secure) approach is to use normal sessions, which auto creates a session cookie (when you use the .Session object), and uses that to determin the current session. If you don't want a cookie you'll have to stick with cookieless, and the session id in the url.
I am facing a very basic problem while building a website ; The website have 10 pages , The problem is that when i login once how can i remain logged in through out the rest of the pages ??
Since this question includes tags for asp.net and sesion variables, I'm not sure what you are missing.
On login form:
if (authentaionSuceeded){
HttpContext.Current.Session["loggedin"]="yes";
}
On all other pages (except for logout)
if (HttpContext.Current.Session["loggedin"]=="yes"){
// whatever you do for logged in users.
}
That's the basic idea. Although I prefer to access the session variable through an extension method/class that provides a type safety and a list of all session variables. The example in that answer is in VB, but you can do the same thing in c#.
There are some possible solutions as below:
Cookies: Store session information in the cookies in the page header
Hidden Form Fields: Maintain the session information in some hidden fields in the page forms
In each option, you need to generate the session key(some encrypted unique key) on the server side and on subsequent request, you should be able to validate that session key. Its better to regenerate a new session key on each request and expire it after certain interval. So for active user, it will keep getting new keys, but inactive user session will simply expire.
I am using Asp.Net Membership and when user enters correct username and password I sign him in using:
FormsAuthentication.SetAuthCookie(String, Boolean)
If I create a persistent cookie then I think my membership will still be able to work but my session data will be null.
This is really annonying and introducing a whole lot of bugs in my application. How can I handle this?
Should I handle global.asax's Application_AuthenticateRequest and check if the userId which I store in session is null and Membership.GetUser() is not null, then I should store ProviderUserKey (Guid) again in Session.
Is this a reasonable approach or is there any better way of handling this?
You must configure your session and authcookie's life-time in your web.config file. See:
<forms timeout="5" />
<sessionState timeout="5" />
Forms are used for authentication and when it times out it will logout
user. You can 'prevent' timeout by setting SlidingExpiration property
to 'true' and it will renew forms ticket on user activity (read
request to asp) if needed. This will keep user logged on while he is
'active' on your site.
and
When session times out you will lose data found in Session object.
Your problem may may be of this issue. Your auth-cookie is alive, but the session is timed-out. User is logged-in, but the session-variables are destroyed! Check this configuration in your app.
See this Q also
I think, you need to use session for it instead of cookie.
And according to me that should be not preferable to save ProviderUserKey in session or any where.
Use global.asax(Application_AuthenticateRequest) for check authentication and based on that id, get ProviderUserKey from DB.
Hope my comment is useful for you.
sessions and authcookies are different. authcookies life-time can be set in forms timeout="5" config-section and sessions life-time should be set in sessionState timeout="5" config-section. It is possible that an auth-cookie is persist yet, but the session expires. Check this.
I am developing the application that stores current user and user's role to session state (System.Web.SessionState.HttpSessionState Page.Session).
if (Session["username"] == null)
Session.Add("username", User.Identity.Name);
if (Session["isAdministrator"] == null)
Session.Add("isAdministrator", User.IsInRole(domain + "\\Domain Admins"));
After I check these session states in code behind for granting permissions to some excecution:
if ((bool)Session["isAdministrator"] || computer.Administrators.Contains(Session["username"].ToString()))
My question is next: how safe that mechanism is? Is it possible to change the session states using some JavaScript for example or some how else?
Thanks :)
If User.Identity.Name is set, why do you need to put it in the Session? Why don't you just call User.IsInRole(domain + "\\Domain Admins") directly (or wrap it in a helper)? It looks to me like you're using Windows Authentication, so setting the username in the session is redundant.
As for your XSS question, the session stores the session ID in a cookie, so in theory an attacker could be sniffing the HTTP traffic or inject JavaScript code into your pages, get a hold of the cookie, then use it and impersonate another user.
It is not possible to change the session state using javascript or other client-side mechanisms, as the state is only stored on the server. However, it is, as others have pointed out, possible for a malicious user to hijack a session by getting hold of the contents of the session cookie.
ASP.NET is designed with this weakness in mind - the session ID is suitably long and hard to predict. Also, the session cookie is marked as HTTP ONLY, which means that most modern browsers will not allow javascript code to access it.
In general I would say this is very safe from XSS attacks. ASP.Net, by default, tracks a users session based on a Cookie which contains the users session ID. You can see this if you open your browsers cookie list and look for ones from your site, there will be one there named ASP.Net Session something... The SessionID's unique, and not incremental. Probably some variance of a GUID.
For added security you can also specify, in your web.config, how long to keep a users session alive. If you are dealing with sensitive information you might want to set this timeout to be relatively short period of time, maybe 10 minutes of inactivity, the default is 20 minutes. You can find more info # http://msdn.microsoft.com/en-us/library/system.web.sessionstate.httpsessionstate.timeout.aspx.
<system.web>
<sessionState timeout="10" />
</system.web>
--Peter