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
Related
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
I have a website which requires user to login. And since all the content is not available over https, we have decided that we will use https only for the login page.
All other data's submitted on the page are not sensitive and needn't be encrypted.
Can this approach compromise user's login credentials? Having all other pages on http - can an attacker get access to the credentials from the user session cookies?
I could see many sites having this approach so I think it might be safe - but would like to understand the technicalities behind it.
Having https only on the login page is insecure:
It means you don't use HSTS, which is the only protection against SSLSrip
It means an attacker can replace on your http pages your link to the login page by something else (like a popin that submit credentials to his server)
Once the user is connected, the cookie must have the secure attribute (it's really easy to steal cookies without. see firesheep)
The only secure way is to use https in all pages of your domain, use HSTS and redirect all http requests to https.
Can this approach compromise user's login credentials? Having all other pages on http - can an attacker get access to the credentials from the user session cookies?
An attacker can steal the session cookie, so he probably can do a lot of harm (depending of your security measures, change the password, the email, extract personnal data...) and he can simulate disconnection and ask again for passwords on http webpages.
I could see many sites having this approach so I think it might be safe
No, it's not. They probably have website too big to turn on https everywhere, so they did what they could to limit damages. (Or they are just lazy)
HTTPS could be implemented only for login page provided Secure flag is enabled for application.
Secure flag will prevent transmission of cookies in plaintext.
Failure to use the "secure" flag enables an attacker to get the session cookie by tricking the user's browser into submitting a request to an Non-HTTPS page on the site.
HTTPS should be used for login page and all other authenticated pages. HTTPS on login page passes the credentials in encrypted format but all other authorized requests travels in unencrytped format means session ID will be transmitted in plaintext if any of the HTTP request uses the session ID.
Best way is to use HTTPS for all the pages which makes sure complete data transmits in encrypted format.
Ref: https://www.owasp.org/index.php/Transport_Layer_Protection_Cheat_Sheet
When browsers like IE 11, Firefox 26, Chrome 32 etc. receive a Cookie over an insecure (HTTP) connection which has the "Secure" attribute specified, they store the cookie and send it back once they do a request to the same server over a secure (HTTPS) connection.
While this probably accords with some specification (I guess Netscape Cookies), I wonder if this opens an additional security hole (Session Fixation) to SSL-secured sites.
Consider the following scenario:
A user (having a clean/malware-free client device) wants to access a website which has a username+password login, over a non-secure network (e.g. unencrypted WiFi hotspot) where an attacker can read and modify all data sent over that network. Let the DNS name of the website be www.example.com.
The user knows that when this website asks him to enter a password, to always look if the browser's address bar contains the SSL lock icon before entering the password.
The website:
provides access to all its pages and resources over SSL/TLS. That means once the user visits a page using https, every internal links on that page are https links so that they do not "downgrade" the connection from HTTPS to HTTP. Also it does not contain any mixed (HTTP/HTTPS) content.
redirects the user from HTTP to HTTPS with a 301 status code if a user accesses one of its pages over HTTP.
stores login information in a Session Cookie.
ensures that all Cookies (including session cookie) sent to the client are only sent over a secure (HTTPS) connection, and that they always have set the "Secure" and "HttpOnly" attributes.
only accepts session identifiers that have been generated by the site and have been sent from the client over a Cookie that has the "Secure" attribute set (the website doesn't accept session identifiers from URLs etc.)
is secured against CSRF by setting a user-specific token on HTML forms that is checked by the server when the user submits a POST request.
is secured against XSS by properly encoding all strings that are output as HTML.
does not implement HSTS, or the user's browser does not support HSTS (like IE, Safari).
does not change the Session Identifier (value of the Session Cookie) when the user logs in.
Now, imagine that the attacker runs a programm that intercepts all data sent over non-secure HTTP requests, and if these are HTML pages, insert a snipped that makes the browser send a HTTP request to www.example.com, like an invisible img or iframe tag:
<img src="http://www.example.com/" style="display: none;" />
The attacker then visits https://www.example.com/ by himself to obtain a session cookie generated by the server, and keeps browsing the site to keep the session alive.
He then also modifies HTTP requests from the user to www.example.com to include the same session cookie in the HTTP response that the attacker just got from the server. The cookie has the "Secure" flag set.
Now, imagine the user visiting some regular HTTP sites which don't transfer sensitive data and therefore do not have SSL. This means the user's browser will receive the session cookie sent by the attacker on these requests.
Later, the user wents to https://www.example.com/ and wants to log in. He looks at the address bar to ensure that the SSL icon is displayed, and because it is, logs in with his password. However, because the attacker fixated the user's session by sending a cookie with a "Secure" attribute over an insecure HTTP request earlier, the attacker now has access to the user's session state.
Note, that if the website was changing the session identifier when the users logs in, the attacker wouldn't have access to the user's session state, but it would still be possible for the attacker to login as himself and send his session cookie to the user, overwriting previous session/login cookies, so that the user does actions (e.g. write sensitive mails etc.) on behalf of the attacker.
My impression of this browser's behavior is that it introduces an additional Session Fixation scenario as described above. The only way that I can see to prevent this is to change the session identifier on each request (for a HTML page).
Am I missing something here?
My view would be that if a browser would reject cookies that have the "Secure" attribute set but were sent over an insecure HTTP connection, the attacker would not have been able to:
inject a session cookie in the user's browser having the "Secure" attribute set as the browser would reject it, and
(EDIT: not applicable) inject a session cookie in the user's browser which does not have the "Secure" attribute set, as the website would ignore cookies without the "Secure" attribute.
This would remove the need for the particular website from changing the session identifier with each request.
EDIT: Ok, one thing that I missed is that browsers do not seem to send the "Secure" attribute on the Cookie header back to the server, so the server has no way to determine if this cookie was set to the client's browser with the "Secure" attribute.
But this would mean, even if browsers would reject cookies with the "Secure" flag on non-SSL connections, it would be possible for the attacker to set a cookie without the "Secure" flag which then gets accepted by the website on HTTPS requests as it can't check the "Secure" flag of the cookie.
Any ideas?
Thanks!
You're correct, this is a known limitation of the secure flag. From https://www.rfc-editor.org/rfc/rfc6265#section-4.1.2.5
Although seemingly useful for protecting cookies from active network
attackers, the Secure attribute protects only the cookie's
confidentiality. An active network attacker can overwrite Secure
cookies from an insecure channel, disrupting their integrity (see
Section 8.6 for more details).
And then from https://www.rfc-editor.org/rfc/rfc6265#section-8.6
8.6. Weak Integrity
Cookies do not provide integrity guarantees for sibling domains (and
their subdomains). For example, consider foo.example.com and
bar.example.com. The foo.example.com server can set a cookie with a
Domain attribute of "example.com" (possibly overwriting an existing
"example.com" cookie set by bar.example.com), and the user agent will
include that cookie in HTTP requests to bar.example.com. In the
worst case, bar.example.com will be unable to distinguish this cookie
from a cookie it set itself. The foo.example.com server might be
able to leverage this ability to mount an attack against
bar.example.com.
I think your best option is not to rely too much on cookies for security-related requirements :b
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 have a website where users can signup and I want to provide some features using a chrome extension, I'm a bit concerned about security:
My idea is to show a login form in a popup and then send an ajax request to my server with username/password (using HTTPS) and then store a token into localStorage that is used for following ajax calls.
Is this insecure? Why? I don't understand how this is more insecure then using a form on my website for example or logging sending an ajax request from a client side js framework
This is secure, as long as you handle the token properly on the client side (i.e. only submit it to your site, and no other sites). The danger is that you are essentially going around the work that Google and the open source community has done to secure Chrome/Chromium from XSS, CSRF, and other token stealing attacks. Make sure that no other sites can request the token from your extension (this is done in the browser through same-domain enforcement). You will need to use certificate signing to verify the origination of the request (you should be able to reuse the private certificate that you use for SSL).
It is important that you treat all client requests as malicious even if they originate from your extension. The server must perform all secure processing as if the client were completely compromised. On the server side, you shouldn't even know if the user is using your extension or a regular browser, because security wise it doesn't matter.
As for the storing of the login credentials on the client side, you should never store the password in plain text. You should salt and hash it, and submit that hash to the server. Based on your question, it sounds like you wouldn't store the user's credentials anyway, just a token. If that is the case, and the token doesn't contain anything sensitive, you should have no problem storing it. Make sure though that you expire tokens on the server side and force re-authentication periodically.
Answer was edited for clarification and typos