What's the best way to authenticate and track user authentication state from page to page? Some say session state, some say cookies?
Could I just use a session variable that has the ID of the user and upon authentication, instatiate a custom User class that has the User's information. Then, on every page, verify the session variable is still active and access basic user data from the User object?
Any thoughts? Any good examples?
The problem with favoring sessions over cookies for 'security' is that sessions USE cookies to identify the user, so any issue with cookies is present with sessions.
One thing to keep in mind with the use of Sessions is data locality. If you plan to scale to more than one webserver at any point, you need to be very careful storing large amounts of data in the session objects.
Since you are using .NET, you will basically have to write your own session store provider to handle this, as InProc won't scale past 1 server, the DB provider is just a bad idea entirely (The whole point is to AVOID DB reads here while scaling, not add more), and the StateServer has a lot of capacity issues. (In the past, I have used a memcached session store provider with some success to combat this issue).
I would google for signed cookies and look into using that instead of either regular cookies or sessions. It solves a lot of the security concerns, and removes the locality issues with sessions. Keep in mind they come back and forth on every request, so store data sparingly.
There's no perfect way to do it. If you store it in a cookie you'll take flak that cookies can be stolen. If you store it in the session you'll take flak because sessions can be hijacked.
Personally, I tend to think a session is a little more reliable because the only thing stored on the client is a session key. The actual data remains on the server. It plays the cards a little closer to the chest, if you will. However, that's just my preference, and a good hacker would be able to get past shoddy security regardless.
No matter what you do, don't try to implement this yourself. You'll get it wrong. Use the authentication system provided by your specific platform. You also need to make sure you have adequate security precautions protecting the authentication token.
I dont know if its THE BEST way to do it, but we are comfortable with the way we do it.
we have a custom user object that we instantiate when the user authenticates, we then use Session to maintain this object across the application.
In some application we combine it with the use of cookies to extend the session continuously.
Cookies and Sessions by themselves are not truly sufficient. They are tools to use to track the user and what they do, but you really need to think about using a database to persist information about the user that can also be used to secure the application.
Sessions are Cookies...
Related
I'm looking into storing some security sensitive information (a users effective permissions for our web application) in a session-resident object, to reduce database queries while performing permissions checks throughout the app.
I understand that the session is stored server-side, and not directly accessible to the client under normal circumstances. ASP.net's other persistence mechanisms can be theoretically defeated, by modifying viewstate or cookie values client-side, but these kinds of cryptography implementation flaws should not expose session-state.
What degree of control over your server would an attacker need to modify data in a clients session-state? Assume they have a sessionID, and an ASPAUTH cookie.
For instance:
A remote attack, like a modified POST or other handler call to a
page?
Would an attacker with programmatic access to IIS (WMI mabey?)
be able to access and change session-state in the same or another app pool's memory?
Would an attacker need to be able to post code to my app, in order to manipulate session memory?
I know these kinds of questions often rely on mistakes in my code, so by all means assume I've written the worst, most insecure code ever (I haven't, but...) and do things like change session in a constructor or life cycle event.
Since we don't know exactly how your code is implemented, all we can do is guess.
First, Session should NEVER be used for security sensitive things. Yes, it's true that a client can't directly read session, there are other factors to consider.
Session cookies are not, by default, encrypted and are passed as plain text.
Session Fixation attacks are easy to accomplish
If a session cookie is hijacked, or even guessed, then it doesn't matter what the users account is, they will get whatever security rights you assign via that cookie.
Session is unstable, and IIS can kill sessions whenever it feels like, so you end up with the situation where a user is still logged in, but their session is lost due to many possible reasons. So now their security is also unstable.
There are many other, more appropriate ways to do what you want, Session is NEVER an appropriate method.
Other methods that would be appropriate include...
Using the user data field of a FormsAuthentication ticket to store the information
Using a custom Claim with a claims based authentication, like ASP.NET Identity, WIF, or IdentityServer.
Using the asp.net Cache to hold the temporary information, based on identity (not session) and adding a cache eviction timeout.
and many more...
Session variable can be a security risk. It is always better to secure your session variable.
Few links you should take into consideration...
Securing Session State
http://msdn.microsoft.com/en-us/library/ms178201%28v=vs.140%29.aspx
http://www.dotnetnoob.com/2013/07/ramping-up-aspnet-session-security.html
http://www.codeproject.com/Articles/210993/Session-Fixation-vulnerability-in-ASP-NET
http://www.dotnetfunda.com/articles/show/730/session-security-in-aspnet
I agree with Erik views.
regards
I need to store some session related data for a user. This data does not need to be encrypted but I want to ensure the user cannot modify it. I think my options are to store it into a hidden field, store it into a cookie, or store it in ASP.Net session state. I need the solution to be server farm safe.
If its stored in a cookie or hidden field then I need a way to ensure a user can't modify it.
What do you think is the best approach for this sort of data?
First question I ask myself about session data: I really need them?
Remember that web is stateless so maybe you can re-engineering your application to not use session state.
Sessions requires a lot of management and server resources.
Meanwhile you have two solutions:
because you are in a farm put your session on SQL Server configuring session state in web.config (it requires resources and it's a bit slower but is the safest way to store session data to ensure the user cannot modify it)
add an encryption/decryption mechanism to your cookie with a private server key
A user is always able to modify cookies, because it is client-side storage. You need to store the data server-side.
ASP.NET Session State is an acceptable solution for your problem, although there are some caveats regarding server farms. This MSDN article explains how to make Session State work for your server farm environment. Be.St.'s answer touches on the suggested out-of-process approach.
A third alternative is to create a database driven session storage that does not necessarily depend on Session state. I find Session State to be a bit of a hassle with different deployment environments (e.g. server farms), so I will sometimes use this approach. You can then access this data by attaching a session key to the querystring or storing the session key in the cookie (still potentially modifiable by the user, but less likely to be a target for such action).
Personally, I reckon it's better to store the information in the cache, although you could perfectly well store it in the session or encrypt it and store it in a cookie and it's just a matter of personal preference
The reason I prefer the cache is that it is not vulnerable to Session Hijacking, so there is no possible way the user can modify it as it's stored on the server (same as session in that respect).
I asked a question about using a custom principal and I included quite a bit of code in there that might help you.
Code to store extra user information in cache: Is this Custom Principal in Base Controller ASP.NET MVC 3 terribly inefficient?
EDIT: And the reason I prefer to store this information somewhere close at hand is that I don't want to kep nipping off to the database all the time as it is very inefficient to do so.
If you need to use a farm and want to share session state among the nodes without going back to the database all the time you could use the AppFabric Session Provider. There is a bit of a learning curve setting it up but it does the job and is fast (don't run it on the same box as your application though).
Just brainstorming some ideas for a Web App I'm building soon.
One of the cornerstones of the Web is Session Handling: Have the user log in, send a cookie with magic binary encoded pixie dust, trust the user blindly afterwards.
I just wonder if it's feasible to completely eliminate 'traditional' sessions for a web app that would normally use it, e.g. an online store.
The idea would be to have a 'server side session' that doesn't use the SessionID or anything, but the username instead. So there is exactly 1 session per user, not more. That would allow stuff like a persistent shopping cart to work.
Authentication would be handled similar to how Web Services work: Expect HTTP Digest authentication on every single page view.
Ignoring the fact that anonymous visitors would have to be handled differently, do you think this approach would be feasible? Or would the additional traffic/load for constant authentication be a deal-breaker in the long run?
First off, we don't use sessions at all.
We found that utilizing session complicated the code without any benefit. There are only two reasons to even consider using session state. The first is to reduce the amount of traffic to your sql server.. However, with load balanced web servers etc, session has to be stored in a sql server... Which kind of eliminates it's first point. But it's worse than that as the session has to be retrieved, deserialized, serialized, and stored on every single page load.
The second reason is to keep from having the browser pass the user id back to the application on each request. However, "session hijacking" is a fairly easy trick to pull off and is rarely taken into account.
So, instead, we use a highly encrypted cookie with non-guessable values that indicate exactly who the user is. We've coupled this with a changing, non-guessable, request id and have eliminated both session state (and it's unnecessary overhead) while at the same time improving security all around.
Can the cookie be stolen? Sure, but it has a very limited life that is the amount of time between two postbacks. Which means it will be found to have been compromised rather quickly.
So, I wouldn't say sessions are a "corner stone" of the web. Rather I'd say they are crutches that are often used improperly and should be avoided for both security and performance reasons.
All of that said, the only way you are going to tie this to a user id is if you force your users to login/create account prior to shopping.. Which no one is going to do unless they have no other choice but to be on your site.
Oh, and don't take my word for it:
4GuysFromRolla.com -> Session variables are evil.
aps.net -> Are session variables still evil?
Scott Hansleman -> Moving Viewstate to Session Pay attention to the part in bold covering memory consumption and it's ability to stay around for way too long.
Coding Horror -> Your Session has timed out This details just some of the problems associated with even using session
Wikipedia -> Session Hijacking What list would be complete without a link to wikipedia?
REST-like implementations such ASP.NET MVC do not require session state at all.
You should just use sessions. Even if its your own session implementation: eg. cookie contains random key used to store information the server. A cookie must be used or you will have to encode all links on the site with a query parameter that specifies the key -- bad idea!
I would then store the "session key", or what every you want to call it, with the persons username in the database.
When a user logs in to your site simply restore their previous "session".
Other then the query parameter option, which is a bad idea, you can track users by IP address. But this again is a horrible idea! Eg. many buildings have a limited number of Internet IPs and many times more internal computers.
There is no good way to track a user without using cookies.
Yes maybe you can use HTTP authentication but why bother? You are just going to introduce new issues and put limitations on your UI.
That actually is pretty much what a traditional session does -- provide a unique identifier to distinguish a browser "session", all you are doing is tying it to username rather then a random variable.
I would say just be very careful of how you generate your token, if it is reproducible you could easily accomplishes the goal of a session fixation attack by generating someone elses session and jamming it into a cookie. That is the reason that sessions are usually a random unique value.
The idea would be to have a 'server side session' that doesn't use the SessionID or anything, but the username instead. So there is exactly 1 session per user, not more. That would allow stuff like a persistent shopping cart to work.
That's just a session, but using the username as the session identifier - which is going to cause all sorts of problems - its open to replay attacks even if you encrypt it. You can't change the encrpytion per-request because that will break when the user opens a second window or presses the back button.
You can't rely on the client address - multiple users may share a NAT address, the same user may access your site from behind a cluster of load-balanced proxies.
like a persistent shopping cart
...implies that you have server-side data for the customer - since the size of this data will vary, you can't store it in the URL nor in a cookie.
Expect HTTP Digest authentication on every single page view.
That presupposes that you create accounts for every user, and that you're not concerned about the impact of the same user id being used by different clients. I don't think that this would require significantly more processing than a conventional session - but its still web-based session management with a different set of problems and vulnerabilities compared to the conventional approach.
I'm porting an ASP.NET application to MVC and need to store two items relating to an authenitcated user: a list of roles and a list of visible item IDs, to determine what the user can or cannot see.
We've used WSE with a web service in the past and this made things unbelievably complex and impossible to debug properly. Now we're ditching the web service I was looking foward to drastically simplifying the solution simply to store these things in the session. A colleague suggested using the roles and membership providers but on looking into this I've found a number of problems:
a) It suffers from similar but different problems to WSE in that it has to be used in a very constrained way maing it tricky even to write tests;
b) The only caching option for the RolesProvider is based on cookies which we've rejected on security grounds;
c) It introduces no end of complications and extra unwanted baggage;
All we want to do, in a nutshell, is store two string variables in a user's session or something equivalent in a secure way and refer to them when we need to. What seems to be a ten minute job has so far taken several days of investigation and to compound the problem we have now discovered that session IDs can apparently be faked, see
http://blogs.sans.org/appsecstreetfighter/2009/06/14/session-attacks-and-aspnet-part-1/
I'm left thinking there is no easy way to do this very simple job, but I find that impossible to believe.
Could anyone:
a) provide simple information on how to make ASP.NET MVC sessions secure as I always believed they were?
b) suggest another simple way to store these two string variables for a logged in user's roles etc. without having to replace one complex nightmare with another as described above?
Thank you.
Storing the user's role information in a server-side session is safe providing a session cannot be hijacked. Restating this more broadly, it does not matter where user role info is stored if an authenticated session is hijacked.
I advise not putting too much faith in the article you linked to, but the 2002 vintage report linked to from your link is of interest. Here are my take-aways:
Don't accept session IDs embedded in URLs.
Focus your time on eliminating cross site scripting dangers i.e. scan all user supplied data and parse out executable java script.
Issue cookies for complete domains (e.g. myapp.mydomain.com)
Host your domain at a high class DNS operator e.g. one that only allows DNS changes from a preset remote IP address.
Don't issue persistent session cookies.
Reissue a session cookie if someone arrives at a login page with a sessionID already associated with an authenticated session.
Better still, always issue a new session cookie on successful authentication and abandon the prior session. (Can this be configured in IIS?)
The only way to make a secure cinnection is to use SSL. Anything less than that, and you simply have to make the evaluation when it's "safe enough".
A session variable works fine for storing a value, with the exception that the web server may be recycled now and then, which will cause the session to be lost. When that happens you would have to re-authenticate the user and set the session variable again.
The session variable itself is completely safe in the sense that it never leaves the server unless you specifically copy it to a response.
Have you considered setting up a custom Authorize tag in MVC. I gave an example of this in another question.
On initial authorization (sign-in screen or session start) you could seed a session value with the IP address also. Then in your custom authorization, you could also verify that IP's still match up as well. This will help make sure that someone isn't 'stealing' the person's session. Everytime you access your session data just make sure to pass the requester's IP and have some check on it.
Are you trying to control the access to functions at the client level? That is the only reason I would expose the roles and items to control client side functions.
Alternatively, you could create a function to obtain the items that the roles of the user are allowed to use, and then even if the function is called outside of the items given back to the web application, you can prevent the user from accessing them.
4Guys seems to show how to control functions with the roles.
The approach I have used in the past is to use symmetric encryption of a cookie alongside SSL. Encrypt the user information in the reponse and decrypt it in the request. I'm not claiming this is foolproof or 100% secure and I wouldn't want to do this on a banking application, but it is good enough for many purposes.
The main issue with session variables is that if you store them inProc rather than persisting them, then you need to apply 'sticky' sessions to your load balancing in a web farm environment. Guffa is correct that without this persistence session variables will occasionally be lost causing a poor user experience.
Sticky sessions can lead to uneven load balancing, perhaps reducing the value of being able to scale out.
If you are going to be be persisting the sessions so they can be accessed by all servers in your web farm, you may be better off using a Guid to identify the user, encrypting this in a cookie and retrieving the user record from your data store each time.
My obvious question is that why do you want to store a users role in session ?
Here is my answer to your query, how this helps. I have attached a small demo application for you to take a look at and understand my points. When you open this project in visual studio, click on the project tab on the top and select asp.net configuration. From the page that will show up you can do the user administration stuff.
You need to store the roles of a user in some secure manner ? The answer to this question is that there is no need for you to worry about storing the role for any user, when we have the asp.net membership, profiles and roles framework to help us out on this. All you need to do is create a role in the aspnet database and assign that role to the user.
Next you want to store two string in some secure manner. I suggest you user profile for storing user specific information. This way you have the information available to you where ever you want from the profilecommon class.
Also please see the attached demo application placed at the end of my blog http://blogs.bootcampedu.com/blog/post/Reply-to-httpstackoverflowcomquestions1672007user-roles-why-not-store-in-session.aspx
Just a suggestion, you might consider using this little library:
http://www.codeproject.com/KB/aspnet/Univar.aspx
It has a server side implementation of the cookie whereby all cookies can be stored on the server while asp.net authentification is used to identify the user. It supports encryption and is also very flexible making it very easy to switch from one storage type to another.
Working inside the context of an ASP.NET application I am creating a page that will be able to execute database scripts against one of many databases in our environment. To do this we need to prompt the user for a username/password combination, this value can be used for all servers without issue.
The question is where is the most secure location to store this information? We need to store it temporarily as when they are on this specific page they could be executing hundreds of scripts, over multiple postbacks. From what I can tell I have 3 options and I'm not sure what is the best. Below is my take on the options, what is the recommendation of everyone here? What is the most secure, while still being friendly for the user?
Store Information In Viewstate
One of the first ideas we discussed was storing the information after being supplied by the user in the ViewState for the page. This is helpful as the information will only exist for the lifetime of the page, however, we are unsure of the security implications.
Store information in Session
The next idea we had was to store it in session, however, the downside to this is that the information can be made available to other pages inside the application, and the information always lingers in memory on the server.
Store Information in Application
The last idea that we had was to store it in the Application cache, with a user specific key and a sliding 5 minute expiration. This would still be available to other pages, however, it would ensure that the information is cached for a shorter period.
Why?
The final question that is important is "Why are you doing this?". Why don't we just use their Lan id's? Well we cannot use lan id's due to the lack of network support for delegation.
S0 what is the recommended solution? Why? How secure is it, and can we be?
Update
Great information has been discussed. TO clarify, we are running in an intranet environment, we CANNOT use Impersonation or Delegation due to limitations in the network.
In my opinion the natural place for this is the Session.
I'm not sure why you seem to be fearing "other pages inside the application" (you control the appliciation, don't you?), but if you really are, you could use some sort of encryption before you store it.
But if you are going to do that, the data could live in the ViewState as well.
I don't like any of these ideas, but totally hate the viewstate idea.
I don't know how many databases you are attaching to, but if there is a limited number, I kind of wonder if handling your authentication and authorization in a standard secure manner, then connect to those databases via integrated security using identity impersonation with an account that has minimal permissions.
The ViewState approach is good but has the problem that you are giving out the username and password to the client. Even if you encrypt it, if some attacker has the encryption key, the situation will not be very good.
Regarding the Session and Application approaches, I don't think Application approach makes sense. Data is user specific, so Session should be the way to go. It'll go away as soon as user's session is closed. By the way, if you chose to store it at the server, use SecureString class.
As John MacIntyre wrote you should use integrated security and impersonation for this.
If for some reason you can not use it and you are going to provide your own login page, use by all means SSL to encrypt the traffic between the browser and your server. Using the ViewState approach is also completely insecure if you do not use SSL, there are tools to view the contents very easily. From the methods that you enumerate the best one would be to use the Session state. You can offload saving the session state from your web server memory and save that data in a database that you can secure the way you want. If you don't like the way these work you could even write your own session state provider and apply the security you need there.
Storing in Viewstate increases your exposure because the password will be flying around the internet again and again. It's up to you if encryption is good enough to address this risk.
Using Application or Session both keeps the password in the server. As mentioned above SecureString will keep people from simply reading passwords out of memory. Session will scale to more users, and probably more importantly to multiple servers much easier than Application. Unless you are sure you will never use more than 1 web server I would not use Application, as it will be up to you to synchronize all the servers.
Never store passwords!
Rather store the hash of a password. See: http://en.wikipedia.org/wiki/Crypt_(Unix)#Library_Function.
I'm aware this does not answer the question, but the more programmers who ignore this advice, the easier it will be for criminals to steal data. Don't let your organization become a news story.
The username/password really shouldn't be stored anywhere.
You store a live database connection, preferably from a pool in your Session object. You only need the username/password as long as it takes to log into the database.
While another page can use the live connection, it doesn't give anyone else permanent access to the database as you would by storing a username/password.