I understand that it is possible to hijack the asp.net session by stealing the asp.net session cookie. I guess that I'm thinking of stealing the cookie as it is transmitted over unsecure wi-fi.
Other than using SSL are there standard ways of securing this information? Or preventing the hijacking of the session?
Sadly, the only way to prevent cookies from being used in a replay attack is to send them over HTTPS since that ensures that the cookie itself is encrypted and, therefore, kept from prying eyes.
Have you seen Jeff Atwood's blog entry about this matter, Breaking the Web's Cookie Jar? Jeff focuses more on the concerns from the user's perspective, but it's worth reading anyway. Here's what he says folks can do today:
So here's what you can do to protect yourself, right now, today:
We should be very careful how we browse on unencrypted wireless networks.
Get in the habit of accessing your web mail through HTTPS.
Lobby the websites you use to offer HTTPS browsing.
This is very broad advice, and there are a whole host of technical caveats to the above. But it's a starting point toward evangelizing the risks and responsible use of open wireless networks.
There probably needs to be some sort of new, more secure approach for cookies going forward, but who knows if there will be enough traction to warrant such change or enough interest to spurn adoption. For web applications where security is paramount - think medical information websites, financial websites, and so on - the only plausible option is to require HTTS for the user's entire browsing session.
There is no easy solution to that problem, other than requiring the authentication information with every page request (which isn't practical and is worse from a security standpoint in an unencrypted environment).
In order to maintain state while using HTTP (which is stateless), something like a cookie must be used. If that cookie is being sent unencrypted, it can be used by somebody else.
As a side note, if you have to pick between two evils of having a session hijacked and having the password compromised, you would rather have the session hijacked. That is why it is crucial that changes like password modifications require re-authentication so that a hijacked session can't take over the account itself. Of course that can also be circumvented if the authentication credentials are not encrypted.
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
Update
I have an ASP.NET website that uses SSL for all pages all the time.
My question is that, is it possible (practically) for someone to perform form authentication session cookie hijacking, where the form cookie id is compromised, and the target user's session is hijacked by using the compromised cookie id.
SSL is about encryption; it's not about preventing access to information flowing over the wire. In other words, it's possible for anyone on the same network to inspect every single packet that goes between your server and the client. The only thing SSL does is encrypt the data in those packets so it's not viewable as plain-text.
SSL is great, but it's not fool-proof. Unless you've been living under a rock for the last few months, you've undoubtedly heard about the Heartbleed bug. It is particularly nasty because it allows a malicious user to obtain the encryption key for the SSL connection, and then, therefore, be able to unencrypt the packets that were sent. The mechanism in play is an important consideration even before the bug, though. Your SSL traffic is only as secure as your private key for your cert. If the private key gets compromised, or you allow it to leak somehow, you effectively have no security.
Cookies are just pieces of data that fall into the broader category of all data that gets encrypted over an SSL connection. Where they do differ is that they are stored on the client, unencrypted. If you allow the cookie to be sent over non-secure connections (HTTP), the data could leak under that circumstance. However, if you set the Secure flag on the cookie, then (in supported clients), it will only ever be sent back to the server if the connection is HTTPS. It's always recommended that you send this flag with any cookies that originated over HTTPS. It's important to realize, though, that the weak point of a cookie is and always will be the client. If the client is compromised, any data in stored cookies is also compromised. The level of disaster this can cause, though, is largely mitigated by never sending anything sensitive in a cookie, e.g. things like usernames and passwords are obviously a bad idea.
Cookies are domain-bound. That means that not just anyone can request them; it has to be the domain that originally set the cookie. That, then, leaves two points of compromise: on the server itself and on the client machine. If your server is compromised, exposed cookies is the least of your concerns. If the client's machine is compromised, that's outside of your control anyways. The best mitigating factor here is revolving sessions, assuming rightly that the only thing that ever comes down in a cookie is a session id. In other words, the user's session should timeout at some reasonable amount of time. This alone makes compromise much more difficult as a malicious user must catch the client's cookie when it's fresh, or the stolen data is useless anyways.
Yes, it is technically possible, but with the proper safeguarding practices the risk of this happening is very small. The key points to check are:
Enforce SSL
Use an established framework or commercial product (ASP.NET forms auth, SiteMinder, etc.)
Disable auth cookie persistence (i.e. "Remember Me" or "Save my credentials" feature)
Enable CSRF checking (look here for details)
A few more here.
Cookies are pretty much the industry standard for maintaining authentication session in a browser. If you don't use them, you might as well give up on the idea of publishing a public site.
I have ASP.NET MVC app that uses Forms Authentication. After user is authenticated, in response he will receive forms cookie that contains auth information. Now regarding the forms cookie: It is encrypted by a machine key and it is protected from tampering by signature. I also use HTTPS... However, what if somehow I get the cookie and try to make request from another client (meaning that the request will be made from another IP address)?
It seems to me that this scenario will work. Are there any ways to defend from this kind of attack?
If you are using HTTPS everywhere on your site and set requireSSL="true" on your system.web/authentication/forms element in web.config, you are instructing the browser to only pass that cookie back over an HTTPS connection. This will protect against the vast majority of traffic sniffing-based session hijacking attacks and you should definitely use it if your site is HTTPS only.
Forms Authentication is inherently stateless. The server is encrypting the following information and storing it client-side: CookiePath, Expiration, Expired, IsPersistent, IssueDate, Name, UserData, Version. Assuming your machineKey hasn't been compromised, the client will just see this as a blob of encrypted data. When it presents that blob to the server again, the server decrypts it and converts it back into a FormsAuthenticationTicket, validates the fields in the ticket against config, verifies that the ticket isn't expired, etc. and decides whether to treat the request as authenticated. It doesn't 'remember' anything about which tickets are outstanding. Also note that it doesn't include the IP address anywhere.
The only real attack vector I can think of if you are HTTPS-only, take care to protect your machineKey, and set the forms auth cookie to requireSSL would be for an attacker to target the client's browser and/or computer. Theoretically they could steal the cookie from memory or disk out of the browser's space. It might be possible for a virus/trojan to do this or even a malicious browser extension. In short, if a user could get their hands on a valid, non-expired Forms Auth cookie, they could present it from any machine they wanted to until it expired. You can reduce the risk here by not allowing persistent auth cookies and keeping your timeouts to a minimum.
If they had the machineKey, they could create FormsAuth cookies from scratch whenever they wanted to.
Oh.. Can't forget Heartbleed. If you had a load balancer or reverse proxy that was using an insecure version of OpenSSL, it's possible an attacker could compromise your private key and intercept traffic over HTTPS connections. ASP.NET doesn't use OpenSSL, so you're safe from this in a pure-MS stack. If you ever hear anything about a vulnerability in MS' SSL implementation, you'd want to patch it ASAP and get your passwords changed and certificates re-issued.
If you are concerned about the browser/machine based hijacking, you might want to take a look at a project I started [and abandoned] called Sholo.Web.Security (https://github.com/scottt732/SholoWebSecurity). It's goal was to strengthen Forms Authentication by maintaining state on the server at the expense of some overhead on each request. You get the ability to do things like revoke tickets server-side (kick/logout a user) and prevent users from moving tickets between IP addresses. It can get annoying in the traveling mobile user scenario that Wiktor describes (it's optional). Feel free to fork it or submit pull requests.
The Anti-CSRF features that 0leg refers to apply to the UI/form mechanism that initiates the login process, but to my knowledge there is nothing in the Forms Authentication process itself that relates to CSRF. That is, once the cookie is issued to the client, the only thing protecting it from being bounced between servers is the fact that cookies are restricted to the domains/subdomain they were issued for. Your stackoverflow.com cookies won't be presented to serverfault.com. The browser takes care of that stuff for you.
Are there any ways to defend from that kind of attacks?
You shouldn't. Years ago we have had implemented such feature and abandoned it soon. It turned out that:
a single user making requests from the very same browser/machine but switching between http/https can sometimes be seen from different IP adresses
a single user traveling and using her mobile phone sometimes makes consecutive requests from different IP addresses when her phone switches between BTSes
Just to clarify the terminology, session hijacking is usually referred to the vulnerability where an unauthorized user accesses the session state on the server.
Authentication cookies are different from session cookies. ASP.NET puts a great deal more precautions in safeguarding authentication cookies. What you describe is better described by the term CSRF (Cross Site Request Forgery). As #Wiktor indicated in his response, restricting access by IP is not practical. Plus, if you read how CSRF works, the exploit can run in the user browser from the original IP address.
The good news is that ASP.NET MVC has built in support for CSRF prevention that is pretty easy to implement. Read here.
For username/pwd verification - the good websites use https - to avoid sending cleartext password over the wire. If I have a site where I want to do this - i.e. login over https. However - after logging in the rest of the stuff should be over http. Is this possible - if yes, why don't we see too many websites doing this. If not, why not?
You might want to read up on Firesheep. The short form is that this technique allows malicious people to hijack the session.
if yes, why don't we see too many websites doing this
The usual excuse for not using end-to-end TLS/SSL is that it causes the web app to take a performance hit, slow response times etc. This is a very flawed argument for https-sometimes security policy. Not entirely unfounded, but still unjustifiable.
If not, why not?
The thinking is that the only inherently vulnerable aspect of user access control is the authentication phase, i.e. where you supply your username and password to prove you are who you say you are. Organizations are aware of the risk of transmitting the credentials in clear text. After this process however, authorization is carried out server side and the web app trusts you from there on out and there are no credentials to protect any more.
Or are there?
As jszakmeister pointed out very succinctly, the session cookie is every bit as security critical as a username/password pair. Should someone get a hold of that, they might as well have seen the password and username on post-it.
So feel free to not only answer this question but to throw out suggestions or improvements. I've never put together a large scale web application before. Here's my thought process:
Persistence Layer: Standard Database (MySQL right now)
Business Logic Layer: REST-like structure (PHP, Java Servlets, etc...)
Presentation Layer: Web Browser, Android devices (application not browser), and others
The reason I selected this architecture is so that devices can devise their own custom UI's and tap into the REST-like functionality by using GET, POST, and what not to interact with the server.
Problem 1:
The problem is, how do you secure user's information? You can authenticate the user over an SSL connection and return a special HASH so that the user can manipulate their account but if someone is listening on the network, all they have to do is listen for a REST call and steal the HASH. One solution is that all REST-like calls have to be over SSL, but this causes another problem.
Problem 2:
If the REST procedures are in SSL, the browser has to use SSL for everything which from my understanding can be slow and cumbersome when unnecessary. Also, SOP makes it impossible to use SSL ajax calls to the REST procedures from an unsecure browser. HTTP and HTTPS are considered different origins even though its the same origin, different protocol.
Is this solution viable? How would I solve these two problems? Or possibly (probably) is there a better architecture I should look into for my web application. Thanks in advance for all suggestions.
If you want to secure the information you have to use SSL, since anybody can listen the network, and see the user information. If you want to secure the access, then use HTTP authentication RFC2617. Over SSL, Basic is secure enough, but if you don't want to use SSL for every request, Digest is the way to go:
your application can be stateless: i.e. more restful, easier load balancing, ...
the authentication token can hardly be reused if listen (no session hijacking)
almost every HTTP client (browser or lib) can use basic or digest HTTP authentication.
As it turns out, there is actually no great solution out there for this answer. You can either protect everything with SSL or devise your own home brew authentication system. A common method is to send the user a unique HASH, store the HASH in the database and in a cookie on the client's machine. Then only that user's IP, User-Agent, etc.. will be authenticated to that cookie.
So the answer is yes, the solution is viable. Extra security precautions will need to be maintained in order to disallow account hijacking. SSL for login will protected the password. A unique hash will allow the user to continue being authenticated without giving away their password to the account. Storing a large amount of information about the user such as IP, browser agent, etc... will disallow easy hijacking of an account.
Is there any way (apart from HTTP authentication, which I gather is inherently insecure over the Internet?) for a "real life" website to handle logins and authentication rather than the traditional way, using session cookies?
HTTP digest authentication (which is quite a different beast from HTTP basic authentication) is quite secure over straight HTTP, and not at all difficult to implement on the server. Nothing is sent over the wire that could reveal what the password is, just information that allows the client to demonstrate to the server that they have the correct password.
If you want a decent explanation of how to implement HTTP digest authentication in your application, Paul James has an excellent article on it.
The only real problem with HTTP authentication is in the browsers themselves: the UI is terrible, but that can be overcome with some Javascript.
Addendum: This answer is almost a decade old. These days, you should really be using HTTPS regardless of any other considerations.
HTTP basic authentication is perfectly safe when used with a SSL (https://) website since all HTTP traffic including the credentials will be encrypted. One subjective drawback though is when using this method your users will need to interact with their browser's authentication popup in order to log in to your site.
To be clear, the only REAL way to do this is through HTTPS.
But, since I assume this is not an option, and I also assume you are looking for a "fully managed login" system, I continue:
Other than HTTPS it is possible to use JavaScript to do secure hashing of passwords on the client side, to prevent revealing plain text passwords over-the-wire, but this is only a half-solution.
The problems with this approach are:
A replay attack is still a viable option.
Only users with JavaScript enabled would be able to auth in this way.
Another approach is a more complicated challenge / response mechanism:
Send a "Challenge" along with the login page.
Calculate the hash of the Password + Challenge client side.
Submit the login.
Calculate the hash of the Password + Challenge (which MUST NOT be trusted in the page request) on the server side, and compare.
And the problems with that:
Only users with JavaScript enabled would be able to auth in this way.
The PLAINTEXT password must be stored on the server to validate the challenge response, and must be encrypted on disk or otherwise protected.
Now, to be fair, problem #2 is not as big of a danger as it sounds. In fact when you instead use HASH authentication, the hash itself is raised to the level of "key".
At this point it is fairly secure to use a cookie to store a randomly generated login ReferrenceID, similar to their session ID, but the server may want to encrypt using the referring IP as part of the IV or KEY to prevent other users from Hijacking the ReferrenceID.
Anyways, I hope that provides a little bit of direction in the way of your design.
HTTP authentication is not insecure when using HTTPs.
Firstly, HTTP Auth is secure over SSL other than the fact that you can't implement a true "Logout" functionality. User need to close their browser, which is pretty bad.
Secondly, It you need to use HTTPS in all cases to make it secure, after that you got Basic Auth similar stuff such as "Digest" and "NTLM Auth".
When you're using https, you can also install a certificate in your client's browser and verify that. myopenid offers this for their OpenID accounts. I have one and it works really well (from the client-side point of view).
Using SSL for encryption in combination with HttpOnly Cookies to help prevent XSS is your best bet for using cookies. I'm not going to say it is bullet-proof, though.