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
Related
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);
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 have a site with a login function, and a "Remember Me" option. In my users table I have a 128 digit random token which I put in the cookie, and then use to lookup the user.
I will be using a "LoggedInUser" which is an instance of my "User" class, which will be populated with a database lookup, so I can retrieve the users username, id, and other info. Now assuming the user has a cookie, should I simply perform a user lookup using the cookies value, or should I store the token in a session and perform the lookup with that? The main worries here are security and performance, IE which is more secure and which will have shorter load times?
Session Id normally stored in cookie - so there is almost no security differences whether you store ID in cookie yourself or use SessionState cookie.
Same for performance - the main cost will bin in DB lookup, obviously if you do couple extra steps (add/red from session state) it will be (probably not measurably) faster.
Notes:
"random" generated by session state went through plenty of security reviews, hopefully your one is as good too.
Session State cookie is not marked as "secure" by default so will be sent over HTTP too, clearly yours will not be - so custom cookie a bit better.
Session state can be configured cookieless, in your case your scheme is a bit safe (as you can't mistakenly share cookie, but urls are easy to share).
In my web application I test for a condition on one page and want to retain the results of the test for a specified duration (such as 5 minutes). I can do this with a cookie, of course, but just in case a user has disabled cookies, I'm thinking a custom server varible might do the trick. I've heard about this, but I haven't been able to find out to do it.
Alternatively, maybe a session variable might be better? There's no inherent way to expire these, right? How long would such a variable survive before IIS tosses it?
Asp.Net has session state. Each Asp.Net Page has a Session property. You can also access it via HttpContext.Current.Session, though there is a subtle difference that won't matter until it bites you (which see my answer to the question, Difference between Session and HttpContext.Current.Session.
The default session state configuration is in-memory. That means that if your web site is served up from something like an F5 Networks Big IP (load balancer) cluster, unless the load balancer is set up to be 'sticky' (meaning that once assigned to a machine in the cluster, you'll always hit that machine unless it goes down or is otherwise removed from the cluster).
If your clustered web site doesn't have sticky sessions, your session state will vanish when your request hits a different machine...and then reappear when another request hits the original machine. You can guess how much fun that can be.
There is built-in support for SQL Server session that you can enable in your web.config. Once set up that way, you're using SQL Server as the backing store for session state. That solves the server farm issue noted above, but does so at the expense of hitting a SQL Server each and every time a session state value is accessed. That slows down access considerable, especially if the session size large. Oddly, executing a SQL query and shoving a 500kb session blog across the network every time you access a session state setting can negatively impact performance. Who knew? [Don't ask how we found that out].
There are other solutions to the problem: ScaleOut's products come to mind (e.g., ScaleOut SessionServer).
Or you can roll your own session state provider using something like an AppFabric cache.
Another "feature" of using SQL Server sessions state is that anything going into Session must be ISerializable.
You can't set a server variable; instead, using Session, which is tied to the current user, is the best approach for user-based data. For application-based data, you can consider cache. So assuming the former, do:
Session["Key"] = MyValue
Note that session lasts 20 minutes; if you have to have exactly 5 minutes, you can use cache, which you can explicitly expire at 5 minutes:
Cache.Add(CurrentUserID.ToString() + "Key", "Value", .. TimeSpan.FromMinutes(5));
You can use the ID of the current user to make the cache value specific to a user, or use cookies, but set HttpOnly=True on the cookie object. An HTTPOnly cookie is only on the server and never accessible on the client, as such:
varcookie = New HttpCookie("Key", Value);
cookie.Expires = ..;
cookie.HttpOnly = true;
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.