If I am serving all of my web content over SSL, do I need to do another layer of encryption and sign my cookie data?
SSL/TLS only offers protection against communications being intercepted and/or modified. It guarantees nothing about text files sitting on a client's hard drive (i.e. cookies).
If you want to prevent a user from presenting your web application with falsified cookie information, then yes, you need to sign your cookie data. If you want to prevent a user from seeing the cookie data, then you should encrypt it as well.
Related
My web application's authentication mechanism currently is quite simple.
When a user logs in, the website sends back a session cookie which is stored (using localStorage) on the user's browser.
However, this cookie can too easily be stolen and used to replay the session from another machine. I notice that other sites, like Gmail for example, have much stronger mechanisms in place to ensure that just copying a cookie won't allow you access to that session.
What are these mechanisms and are there ways for small companies or single developers to use them as well?
We ran into a similar issue. How do you store client-side data securely?
We ended up going with HttpOnly cookie that contains a UUID and an additional copy of that UUID (stored in localStorage). Every request, the user has to send both the UUID and the cookie back to the server, and the server will verify that the UUID match. I think this is how OWASP's double submit cookie works.
Essentially, the attacker needs to access the cookie and localStorage.
Here are a few ideas:
Always use https - and https only cookies.
Save the cookie in a storage system (nosql/cache system/db) and set it a TTL(expiry).
Never save the cookie as received into the storage but add salt and hash it before you save or check it just like you would with a password.
Always clean up expired sessions from the store.
Save issuing IP and IP2Location area. So you can check if the IP changes.
Exclusive session, one user one session.
Session collision detected (another ip) kick user and for next login request 2 way authentication, for instance send an SMS to a registered phone number so he can enter it in the login.
Under no circumstances load untrusted libraries. Better yet host all the libraries you use on your own server/cdn.
Check to not have injection vulnerabilities. Things like profiles or generally things that post back to the user what he entered in one way or another must be heavily sanitized, as they are a prime vector of compromise. Same goes for data sent to the server via anything: cookies,get,post,headers everything you may or may not use from the client must be sanitized.
Should I mention SQLInjections?
Double session either using a url session or storing an encrypted session id in the local store are nice and all but they ultimately are useless as both are accessible for a malicious code that is already included in your site like say a library loaded from a domain that that has been highjacked in one way or another(dns poison, complomised server, proxies, interceptors etc...). The effort is valiant but ultimately futile.
There are a few other options that further increase the difficulty of fetching and effectively using a session. For instance You could reissue session id's very frequently say reissue a session id if it is older then 1 minute even if you keep the user logged in he gets a new session id so a possible attacker has just 1 minute to do something with a highjacked session id.
Even if you apply all of these there is no guarantee that your session won't be highjacked one way or the other, you just make it incredibly hard to do so to the point of being impractical, but make no mistake making it 100% secure will be impossible.
There are loads of other security features you need to consider at server level like execution isolation, data isolation etc. This is a very large discussion. Security is not something you apply to a system it must be how the system is built from ground up!
Make sure you're absolutely not vulnerable to XSS attacks. Everything below is useless if you are!
Apparently, you mix two things: LocalStorage and Cookies.
They are absolutely two different storage mechanisms:
Cookies are a string of data, that is sent with every single request sent to your server. Cookies are sent as HTTP headers and can be read using JavaScript if HttpOnly is not set.
LocalStorage, on the other hand, is a key/value storage mechanism that is offered by the browser. The data is stored there, locally on the browser, and it's not sent anywhere. The only way to access this is using JavaScript.
Now I will assume you use a token (maybe JWT?) to authenticate users.
If you store your token in LocalStorage, then just make sure when you send it along to your server, send it as an HTTP header, and you'll be all done, you won't be vulnerable to anything virtually. This kind of storage/authentication technique is very good for Single-page applications (VueJS, ReactJS, etc.)
However, if you use cookies to store the token, then there comes the problem: while token can not be stolen by other websites, it can be used by them. This is called Cross-Site Request Forgery. (CSRF)
This kind of an attack basically works by adding something like:
<img src="https://yourdomain.com/account/delete">
When your browser loads their page, it'll attempt to load the image, and it'll send the authentication cookie along, too, and eventually, it'll delete the user's account.
Now there is an awesome CSRF prevention cheat sheet that lists possible ways to get around that kind of attacks.
One really good way is to use Synchronizer token method. It basically works by generating a token server-side, and then adding it as a hidden field to a form you're trying to secure. Then when the form is submitted, you simply verify that token before applying changes. This technique works well for websites that use templating engines with simple forms. (not AJAX)
The HttpOnly flag adds more security to cookies, too.
You can use 2 Step Authentication via phone number or email. Steam is also a good example. Every time you log in from a new computer, either you'll have to mark it as a "Safe Computer" or verify using Phone Number/Email.
I'm using the Cookie Middleware in ASP.NET Core for session cookies. The session cookie data is encrypted by the framework using the Data Protection API.
Just wanted to understand in detail what the level of protection is from this process. These are my current assumptions:
The cookie data cannot be viewed in transit or at rest in the browser and is tamper-proof
The cookie data can be replayed if sniffed over HTTP
The cookie data cannot be replayed if issued and sent only via HTTPS
If any of these assumptions are wrong or need more detail then I'd appreciate an answer.
Your assumptions are right: although authentication cookies are marked as HttpOnly by default, nothing prevents an attacker from stealing a cookie from browser's container and using it as-is to make malicious requests if he manages to install a malware on victim's machine.
In the future, ASP.NET Core will support a feature called "TLS token binding" that will make stealing authentication cookies much harder.
When supported by both the server and the user agent, this feature allows the server to bind sensitive data like authentication cookies or bearer tokens with a secret value only known by the original client (i.e by the browser).
In ASP.NET Core, this feature will be implemented at the cryptographic level: the secret transmitted by the browser will be used to derive the encryption/validation keys used by Data Protection to protect and unprotect the authentication cookies, so that no one will be able to use a stolen cookie without also sending the corresponding token.
I am developing several Web Services that will be accessed by a mobile application. I have several requirements:
Each user will need to sign in with their own User ID and Password (the same User ID and Password they use to sign into the website).
Every Web Service request will need to be authenticated to ensure that the request is coming from the mobile app(s).
Every Web Service request will need to authenticate the user, since there is user-specific fucntionality built in, and access will need to be blocked if the user's account is disabled.
Let's assume that OAuth is not an option.
In order to ensure that Web Service requests are coming only from the mobile app(s), I am planning to use HTTP Basic Authentication in IIS (the mobile app(s) will need to have a User Account setup in Windows Server and the mobile app will need to store the User Name & Password and pass these in the header).
Next is the User Authentication for each Web Service request. Would it be suitable to encrypt the User ID, Password, and some shared secret key (a "pepper", of sort) with AES-256, pass that encrypted string as a parameter with each request (over HTTPS, of course), and then decrypt and parse it on the server to authenticate? This is the existing plan, but something just doesnt seem right about it - like it's not "secure enough".
What else can I do to properly authenticate users for Web Service requests?
I recently went through this problem and asked opinions from a group of senior people about how they solve the problem. Opinions were varied, but one consistent feeling is that your level of security depends on the use case of your application. Are you doing online banking or storing medical records? Then your security needs may be quite high. Social networking? Maybe not so much.
Basic Authentication is generally fine when encrypted over SSL, ColdFusion works well with it. If you use Basic Auth, make sure to encrypt your traffic with 1024-bit keys or better. Don't authenticate every request with username/password - that's unnecessary. Authenticate the first request, set a session token, and rely on the session token for your identification of users.
Set a polling mechanism from the client to the server to keep the session alive - set the session timeout to 30 minutes and the polling frequency at 25 minutes, for example. Otherwise you may need to re-authenticate expired sessions. Again, how you approach this part of the solution depends on your paranoia level, which depends on what kind of data/app you are dealing with.
Cookies, and therefore sessions, should work fine in iOS apps. If you use sessions to verify identity after authentication, make sure your session cookies are memory-only (set at the server level).
Check the SSL implementation of your server against the Qualysis SSL Test:
https://www.ssllabs.com/ssltest/
The report will give you a surprising amount of detail about the strength of your SSL implementation.
Lastly, consider implementing two-factor authentication to combat password theft.
If you ignore the SSL advice and plan on encrypting your password and communicating over an insecure channel, look at the Kerberos protocol for a well-known example of how to authenticate securely:
http://en.wikipedia.org/wiki/Kerberos_%28protocol%29
Yes, you can use Basic Authentication but that means the client will need to store the username/password in plain text, and also send them over in plain text. Sending part is sort of fine if it's under HTTPS, but storing username/password in plain text may not be a good idea, unless you're using some secure key store.
Let's assume you have decided that Basic Authentication is the way to go, and you want to make use of the official CF way of supporting that, then you can use CFLOGIN.name & CFLOGIN.password. You may also check out Ask Ben: Manually Enforcing Basic HTTP Authorization In ColdFusion. In the remote cfc side, always validate the username/password, or return some sort of token and asks the client to use that token going forward. The token can be cfid+cftoken if you like, or even roll your own that never expires. If you use cfid+cftoken, and send them over as cookie or in body along with your web service call, I believe you can resume the session if you so choose.
Is there any sense to encrypt cookies (secure cookies) for HTTPS?
As far as I know in HTTPS whole request is encrypted, so do we need additional encryption of cookies?
That depends entirely on your security model. Some reasons why you would still need to encrypt cookies:
Do you care if the user of your application gets the contents of the cookie? In other words, do you store anything there that's internal and shouldn't be disclosed to the user?
Do you care if the user tampers with the contents of the cookie? Encryption can be a way to get integrity protection depending on how you do it. (There are, of course, other ways as well.)
What are the consequences of disclosure of the cookie? If it's a bearer token, whether it's encrypted or not won't make a lot of difference, but if it contains valuable data, encrypting it provides some protection against an attacker gaining access to the browser's stored cookies in some way (whether via a web attack or an attack on the actual system hosting the browser). You still may lose to an attacker in other ways, but it could provide some defense in depth.
The main thing that encrypting the cookie gives you is protection against the user who receives the cookie (or an attacker who can access that user's data), if you need that.
When setting Cookiee on the server with properties(httpOnly and secure=true), does that mean it will only be secured during the communication beween server and client, but not after that?
In other words, if the value was originally in plainText -will it also be stored on the client side with plainText (after traveling with https ) -making it unsafe/vulnerable?
1) Do passwords needs to be always encrypt befors sending (even when using https)?
2) Where is httpCookiee (with secure=true) stored? and is this storage access is protected?
You probably don't want store the password.
What you need is store some "user is already authenticated" flag.
After all, you should learn about "digest access authentification". Storing hashed data is always plus.
This answer is too short, mainly bacause here is too much possibilities - and too much open questions.
Handling returning users:
You can manage (server side) an session database. in the cookie you storing only session ID. when the user authenticate itself, you're store into your server side database his status: "logged in". when he log out, you change in the DB status: "logged off".
Handling returning users has nothing with "storing passwords" in any way. You for example can authenticate users by external auth-services, like open-id, twitter, facebook etc., you're only storing his status by some session-ID or similar.
Browsers usually can store user-names/passwords, but this all time should be the user responsibility. When the user want only remeber his passwords, you should not store it in any way.
Why you want complicating your app and security mechanisms with storing encrypted passwords in cookies - what is not a correct solution - from any point of view?
Simple flow:
When an new user comes to your site - you assign him an new session-ID and store the SID into a cookie
when he login (via https) - you're store in your DB = "sessionID" -> "logged in"
when he return after a week, you can (server side) either accept his session-ID from the cookie - and from DB you can get his "logged-in" status, or, you can force login him once again (for example because of expiration)
all of the above is without any risk storing passwords in any way
1) I think so. Because even with secure flag, cookie will be stored in browser cache in plain text
2) It depends on browsers and OS. For Safari in Mac, you can find it in your ~/Library/Cookies/Cookies.plist You can see cookies with Secure flag but in plain text. It may be protected so only owner can see, but it never be good idea to have plain password anywhere in your computer
Once the secure flag is set to true, the cookie will be stored encrypted in the client even after the browser is closed. As you say it is unsafe/vulnerable.
Resp. 1)
Passwords can be encrypted before sending using Javascript, but it doesn't make much sense because https is doing the encryption for you.
Resp. 2)
The cookies are stored in the browser folder. Anybody can open the folder and see the cookies with a text editor.
The browser will handle the passwords for you. Just using a <input type="password"> and using SSL is secure enough.
And, avoid at all costs storing passwords in cookies.