ASP.NET MVC 4 and session security leak - asp.net

Instead of using ASP.NET MVC User's system, I'm simply using session, as the following:
When he logs in (username + password), I fetch the corresponding user from the Database and set:
Session["UserId"] = fetchedUser.UserId;
Then, I'm always checking if he is logged in:
if (Session["UserId"] != null && ...)
The problem is that if someone copies the value of ASP.NET_SessionId from a logged in user (eg: user goes to bathroom and coworker who is sitten next to him checks his cookies with chrome inspector), then he will be able to create a cookie in his computer and act as that user.
My questions are:
Why are sessions safer than cookies if the session id is saved in a cookie?
Can I make this safer (and continue using session)?
How does internally ASP.NET User authetication system do it?

A primary reason for not using Session as an authentication mechanism is that it could render your application vulnerable to Session Fixation. For example, a problem could be if a user arrived on your site using the HTTP protocol and receives a session ID that is stored in the ASP.NET_SessionId cookie. The user may later log in, and even though your login pages might be secured under HTTPS the session token has already been generated under HTTP which means it has already been transported using cleartext.
To answer your other points:
Why are sessions safer than cookies if the session id is saved in a
cookie?
The data stored in session is stored server side, so it is more difficult for an attacker to tamper with this data. All the cookie stores is a token for this data, rather than the data itself. Having said that, it is still safer to use the FormsAuthenticationProvider as this creates a new authentication token once login is complete rather than on session start for the reasons of avoiding session fixation as above.
Can I make this safer (and continue using session)? How does
internally ASP.NET User authetication system do it?
The built in provider is already fit for purpose, so it would be desirable to use that rather than fudge another mechanism to meet your requirements. It is also easily extensible so you can customise it to your needs. The ASP.NET User Authentication creates an encrypted ticket and stores it in the cookie rather than storing a reference to a server side variable: http://support.microsoft.com/kb/910443
I would also draw your attention to the signout mechanism and how to secure it. Particularly
Calling the SignOut method only removes the forms authentication cookie. The Web server does not store valid and expired authentication tickets for later comparison. This makes your site vulnerable to a replay attack if a malicious user obtains a valid forms authentication cookie.
Details here: http://msdn.microsoft.com/en-us/library/system.web.security.formsauthentication.signout.aspx
In addition you may want to set the "secure" flag on your ASP auth cookie to prevent it being leaked over HTTP by a MITM attacker.

Related

How to protect GET methods for .net application if the cookie is stolen

How to protect GET methods if the cookie is stolen since Antiforgery Token only protects the POST methods? The web application can return sensitive information via GET method.
I am using .AspNetCore claim based identity. I was trying to use Postman to view the content of the GET method, but I cannot get the it to work.
I assume this is theoretically possible. An authorized user cookie can be hijacked by a man sit in middle right?
The site is secured by SSL and I think the .AspNetCore claim based identity is session based cookie. What are the chances to break in to execute the GET methods and get returns values. How to secure the application?
It should never get to that point
Don't use just a cookie to validate a user. You should use several cookies based on each session, such as the device name or id, the device's IP address, a session ID stored in their browser, potentially something stored in their local data (permanently stored even if cookies are deleted) that validates that particular PC etc. There are plenty of other methods of security a user's identity.
However, if you use a session cookie and nothing else to authenticate a user, then you should probably revise how your application secures its users first. Because if that session cookie is stolen, then it's a bad sign for your user.

Remove auth cookie if user is deleted

Is there a way to remove the authentication cookie, or sign a user out once they are removed from the asp.net membership database? By default if a user is removed from the database, the user can still browse the website since they still have a valid authentication cookie.
I've tried different things within global.asax but nothing seems to work. Is something like this even possible?
See here: FormsAuthentication.SignOut Method. Although this refers to users not being logged out server side, a similar approach can be used for managing deleted users.
Calling the SignOut method only removes the forms authentication cookie. The Web server does not store valid and expired authentication tickets for later comparison. This makes your site vulnerable to a replay attack if a malicious user obtains a valid forms authentication cookie. To improve security when using a forms authentication cookie, you should do the following:
Use absolute expiration for forms authentication cookies by setting the SlidingExpiration property to false. This limits the window in which a hijacked cookie can be replayed.
Only issue and accept authentication cookies over Secure Sockets Layer (SSL), by setting the RequireSSL property to true and by running the entire Web site under SSL. Setting the RequireSSL property to true ensures that ASP.NET will never send an authentication cookie to the browser over a non-SSL connection; however, the client might not honor the secure setting on the cookie. This means the client might send the forms authentication cookie over a non-SSL connection, thus leaving it vulnerable to hijack. You can prevent a client from sending the forms authentication cookie in the clear by running the entire Web site under SSL.
Use persistent storage on the server to record when a user logs out of the Web site, and then use an application event such as PostAuthenticateRequest event to determine whether the current user was authenticated with forms authentication. If the user was authenticated with forms authentication, and if the information in persistent storage indicates the user is logged out, immediately clear the authentication cookie and redirect the browser back to the login page. After a successful login, update storage to reflect that the user is logged in. When you use this method, your application must track the logged-in status of the user, and must force idle users to log out.
The third option is the most secure but requires the most effort. IMO, the first two do not resolve the issue adequately.
It is also possible to store custom information in the Forms Authentication Ticket. You could store the last explicit logout time in this ticket, and check it against your server side database record. Please note that if this record is at user level instead of session, then all logins under that account would be logged out at the same time.
In your case, if you are deleting server side user and session records, as the record does not exist you will be able to also fail the authentication request.
I'd advise also storing and checking the last date/time the password was changed - that way if a user updates their password then all existing sessions are logged out.

How does ASP.NET WebAPI using IIS store my users authentication state?

I have an asp.net Web Api 2 / Identity 2 application that requires a user to be authenticated. The authentication works but I notice that when I restart my local development machine and try to access a method that requires authentication then I get a failure.
As my application is unchanged from the asp.net sample then I think it uses cookies to store user data on the client. Where and how does the Server or IIS store information on which users have authenticated? Does it do this just the once or on every HTTP? Is there a difference between my using Token or cookie authentication in the way that the authentication and also authorization is checked on the server?
I think you are misunderstanding how authentication works with ASP.Net. As an example, let me show you some cookie details for a site of mine that uses Identity (note the token is actually in the cookie, the two are not mutually exclusive concepts):
Name __RequestVerificationToken
Value afeILhaIvRr56jXXXXXXXXXXX
Host site.azurewebsites.net
Path /
Expires At end of session
Note that the cookie, by default, expires at the end of your session. That means when you restart your development machine, your cookie is expired and your token is no longer valid.
In particular I have read that with token authentication then there is no need for continual re-authentication every time a request is made to the server
You need to understand that HTTP is a stateless protocol. Each request happens in a vacuum, and therefore you need to pass some data back to the server so that it can tell that the person who authenticated with Request A is really the initiator of Request B. Almost always, that piece of data is from a cookie. So, every request does indeed re-authenticate, and typically with a token in a cookie.
The only piece of data about your session that is stored on the client is the cookie (unless you are doing something atypical). The rest is on the server. How it is stored can vary:
Inproc: Easiest to setup, sessions are stored in process. So when your server or app pool is restarted, that data disappears
State Server Mode: Sessions are stored in process, but outside of the ASP.Net worker process, so the application can be restarted without losing session data
SQL Server: Unsurprisingly, this stores data in a database. Very resilient, but more work to setup. Also your best option if you are on a web farm.
ref: http://msdn.microsoft.com/en-us/library/vstudio/ms178586(v=vs.100).aspx
Expanding on the great answer by Chris, I would like to add that there are two possible models here. In forms authentication (which is the default membership type for asp.net) the cookie can either store authentication information and then it's called a ticket or the information can be stored in session, with the cookie being a simple identifier for "reconnecting" the authenticated session with the requesting client on each subsequent request.
This "reconnecting" happens in the Application_AuthenticateRequest method of the global.asax. If you are using the default forms authentication storage, i.e. an SQL DB created for you by the framework, the reconnection will be done automatically. If you are using a custom authentication store (like accessing active directory yourself or a custom users table structure) you can override the the method and reconnect the authenticated session using your own implementation. In any case, the authentication data is populated in the User.Identity object's different properties. From that point, if you use the [Authorize] attribute, the framework accesses the object to check if the user is indeed authenticated and authorized.
I any case, the authentication information is tied to both the cookie and the session. Assuming your session is InProc, like Chris said, when the session is lost (through timeout, app pool recycle or restart of the dev machine) the server-side of the session is lost and your authentication / session cookie is replaced by a new one on the next request.
EDIT: Ohh... and one more side comment. Make sure you distinguish between authentication and authorization. The client is not re-authenticated on each request. Authentication is the process of providing your credentials and being identified by the server. Authorization is, now that the server has verified who you are, on each request it checks if you are authorized to access the resource you are requesting.
The server doesn't store information about who's authenticated and who isn't. Depending on your authentication mechanism (forms, tokens?), typically, when a user logs in, the server will return some form of authentication token that the client should pass back to the server on each API call.
Without knowing more about your configuration, it's difficult to explain why when you restart your server you have to re-authenticate, it sounds like the authentication token generated by the server is invalidated on restart.
Where and how does the Server or IIS store information on which users have authenticated?
IIS does not store state based on cookie authentication. Everything is determined based on the request. Either a request has the correct encrypted information, or it doesn't. If you look at a default Forms authentication in ASP.NET, you will find a cookie called .ADUAUTH ... this cookie has all the information to authenticate the request. If the cookie is half expired, it will be reset, but that's all IIS does.
Does it do this just the once or on every HTTP?
Every HTTP request is unique, so yes, per HTTP request.
Is there a difference between my using Token or cookie authentication in the way that the authentication and also authorization is checked on the server?
It's always checked on the server: To find out more, check out: How ASP.NET Security Works: http://msdn.microsoft.com/en-us/library/ks310b8y.ASPX
I think my answer could be a little contradicting to all of the above.. But I think If I understand right..
IIS stores inside the memory space of the ASP.NET worker process, i.e the session data in the RAM.
The storing of authentication state depends on the authentication model you are using. For example: if you are using the Federated authentication, through ADFS, then when a user loads your web page he is required to sign in providing his credentials. The ADFS then sets the authentication token which is stored in the session data, the session id is stored as cookies in user's browser. The server has the mapping of Session Id to its session data.
Now the user is authenticated. The ADFS looks for authentication token to mark a user as authenticated.
When you restart the server, the session data is lost as the data is stored in RAM.
There are ways to handle this, there are 3 types of session storage:
1. InProc (Stored in memory space of ASP .NET Worker process - RAM)
2. State Server (Stored out side of ASP .NET worker process, like on cloud Azure storage)
3. SQL Server session storage (Stored in SQL server)
I think you are adopting 1, because of which you encounter the problem.
In cases 2 and 3, the session is not lost when you restart the server.
Several things --
Token based authentication is not really authentication. It is just issuing you a unique token (can be a guid, unique string, etc) and then associating it with something (like your IP address) and saving that association server side (in a database?). Now whenever you use that token, from the client app, the server checks the association already stored and serves or denies or request.
In many ways, it is very similar to using Cookies to maintain authentication. Only, token-auth was designed more for web services operation than for UIs.
In short: Out of the box, the membership provider will run it's authentication method and upon success, it will create an auth ticket/token/cookie that will be stored from the site. In addition to this, there is a session cookie that is stored with the site as well. When you make a page request, it'll pull these things and use them to determine whether or not you are already authenticated. If it finds the ticket and sees that it is still good, it'll allow access.
When you restart your local environment, the session and it's information is destroyed which is why you have to log in again.
There is an entire pipeline in the framework that makes all of this stuff happen (having to do with authentication, authorization, and identity) and there are number of ok articles on the interwebs explaining this, but imo, they're almost all incomplete or hard to follow. If you want a great soup-to-nuts explanation, PluralSight.com has some training videos that will deconstruct and explain the entire pipeline for you. Understanding the pipeline can help you implement your own custom authentication, and I highly recommend it.

Regarding Session Hijacking & Protection in ASP.NET

i read few article about Session Hijacking. hacker sniff cookie and get the session id from there. but i think session id is stored in cookie as encrypted value. is not it?
is it possible to decrypt easily?
what other sensitive data is stored in session cookie...please explain. whatever we stored in session variable from server side code that is stored in session cookie...is it right?
please guide me regarding session cookie and what would be best way to protect Session hijacking. thanks
The idea is that they get the session cookie and used it as it is, to send it to the server and server connects the cookie with the victim session. Actually there is no data on session cookie, just an encrypted number of the session id.
Now there is a case that sensitive data stored on cookie and that is the Roles of the currenct user. To avoid a possible decrypt and change on web.config on <roleManager cacheRolesInCookie="false"
Also on the authentication cookie and on role manager always use the requireSSL="true", so its impossible to steal the cookie of authentication, but you must use secure pages for this make work.
How some can stole a critical session. This can be done if the programmer depends the critical data that show to the user, on the session id. For example, if you store the phone number and the name on a session variable and show that to the user, then some one can stole the full web page and read it (if not ssl). If you have connect the backoffice and the access to hidden administrate page with the session id, then if some steal the session cookie and open the pages, then he can gets on that administrators back office pages.
So its up to you not to store critical information's on session data, and always use ssl pages to administrate and to get send cookie critical data.
Now if a hacker steal the session cookie and you there just store what users see in previous pages, a history of products like amazon, then is not big deal because still can not connect this history with the user, but also can anyone sniff the urls that a user see.
Of course its up to you also to not store critical data on any unencrypted cookie !
So you split your data to critical ones, and not critical ones, and always use SSL for page and cookie for the critical ones, and never trust the data that comes from unsecure pages.
You can also read :
Can some hacker steal the cookie from a user and login with that name on a web site?
Hope this helps you.
An ASP.NET cookie stores Session ID and an Authorization Ticket; however, the issue is not whether one can decrypt the cookie, but rather to be able to create one with identical values and trick the server into believing that your copy of the original cookie is the real one.
The HTTP protocol is stateless so client and server don't maintain information about each other. Session Cookies (using the Session ID and Authorization Ticket) is how they keep track of each other. The web server knows which Session ID is attached to which authorization ticket and if you can provide a valid pair of these values, the web server will happily accept it. The Web server encrypts the cookie using a symmetric encryption algorithm and an autogenerated key (default setting). You can tweak these settings, if you want to, by modifying the appropriate sections in the machine.config file.

ASP.NET FormsAuthentication exclusive login

I'm working on a website where I get a feed of usernames / hashed passwords from another service. When someone sucesfully logs in I set a forms authentication cookie with FormsAuthentication.SetAuthCookie.
My client doesn't like multiple people logged with the same credentials. They would like a log in to invalidate any currently logged in clients.
There isn't a method on FormsAuthentication to tell the server "invalidate any other cookie under this name". KB900111 suggests the server doesn't maintain a list of valid cookies. So my approach isn't sounding good.
What's the alternative? Time to ditch forms auth?
Not necessarily. Forms auth still provides quite a bit of baked-in functionality you might want. Maybe you can generate and issue a Guid the first time each user logs in, and store that on the server-side, and in a cookie (security ticket preferably). Every time a request is made, you check to make sure the user is using not only the correct credentials, but also the same machine and browser (based on the cookie you issued the user when the user logged in). You would of course have to make sure that your Guid expires at some point, and also make sure you clear it out when the user signs out.

Resources