Cookie security when passed over SSL - security

Am I correct in thinking that if you pass a session cookie over an SSL encrypted request that the cookie could only be read by an attacker who had direct access to the computer that the cookie had been sent to, or the server it has been sent from, provided they are unable to crack the encryption?

SSL encrypts all traffic, including the header (which contains the cookie value).
On the other hand, the cookie can be accessed via Javascript on the client machine, unless you have marked it as HttpOnly. A hacker could potentially get this script to run via an XSS attack.
In addition, there are ways to hijack the cookie with a carefully crafted email or web page. This is known as session riding or CSRF.
Finally, cookies are visible on the wire for any network connection beyond the point of SSL termination, e.g. if you data center uses SSL offloading and/or deep packet inspection.
Oh, and one more thing. If SSL isn't configured correctly it is easily vulnerable to MITM attack, e.g. your server is configured to accept a null protocol. In this case a hacker can of course read the cookie plain as day.
I think that's it. That should be enough to keep you up at night.

To add to #John Wu's answer you can also protect against another type of MITM attack by setting the Secure Flag. This will make sure that the cookie is only transmitted by the browser when the request is sent encrypted over HTTPS.
Even though the cookie can only be set by your site, you should still encode if it is output to guard against XSS. See my other answer here for more details: https://security.stackexchange.com/a/44976/8340

Correct, SSL encrypts all HTTP on the wire.

Related

how do https prevent session hijacking

I have read some articles about preventing session hijacking, and most said to use https on your site, but I don't understand how https can prevent session hijacking
how do https prevent session hijacking?
Session hijacking can also be performed by someone sniffing your network traffic. For example, imagine that you're connected to Stackoverflow via HTTP, and there's someone reading every request you send to the server. Every time you access to a different page, you'll send your authentication cookies, along with your request to Stackoverflow, so it'll know that you're logged in, and it'll not ask you to log in again.
The problem is that since your communication is being performed as plaintext, that attacker can read your requests, he'll be able to grab your authentication cookies, and he'll be able to impersonate you.
Now, if you're using HTTPS, you're communicating over an encrypted channel. Even if an attacker is sniffing all your requests, he'll not be able to get any meaningful information, because he'll only see encrypted text. That's the reason why HTTPS is good to prevent session hijacking.
Of course, there are different ways to hijack a session, and a man in the middle is just one of them, so maybe you should take a look at this: https://www.owasp.org/index.php/Session_hijacking_attack
Also, just as a side-note, "just using HTTPS" is not a panacea, it needs to be properly configured and implemented, so if you're the one who'll be performing some server-side configurations, I highly recommend you to read more about the protocol and attacks on the protocol, to avoid some common mistakes (like enabling old versions of SSL, or using broken algorithms, like RC4).

Sanity Check: SSL+ POST vs. un-encrypted GET

A classic dumb thing to do is pass something security related info via a GET on the query string ala:
http://foo?SecretFilterUsedForSecurity=username
...any yahoo can just use Fiddler or somesuch to see what's going on....
How safe is it to pass this info to an app server(running SSL) via a POST, however? This link from the Fiddler website seems to indicate one can decrypt HTTPS traffic:
http://fiddler2.com/documentation/Configure-Fiddler/Tasks/DecryptHTTPS
So is this equally dumb if the goal is to make sure the client can't capture / read information you'd prefer them not to? It seems like it is.
Thanks.
Yes, it's "equally dumb". SSL only protects data from being read by a third party; it does not prevent the client (or the server) from reading it. If you do not trust the client to read some data, they should not be given access to that data, even just to make a POST.
Yes, any user can easily examine the data in a POST request, even over HTTPS/SSL, using software like Burp Suite, Webscarab, or Paros Proxy. These proxies will complete the SSL transaction with the server, and then pass on the data to the client. All data passing through the proxy is stored and is visible to the client.
Perhaps you are trying to store sensitive/secret data on the client-side to lighten the load on your server? the way to do this so that the user cannot look at it (or change it) even with a proxy, is to encrypt it with a strong symmetrical secret key known only to the server. If you want to be sure that the encrypted data is not tampered with, throw on an HMAC. Make sure you use a sufficiently random key and a strong encryption algorithm and key length such as AES 256.
If you do this you can offload the storage of this data to the client but still have assurance that it has not changed since the server last saw it, and the client was not able to look at it.
This depends on who you're trying to protect your data from, and how much control you have over the client software. Fundamentally, in any client-server application the client must know what it is sending to the server.
If implemented properly, SSL will prevent any intermediary sniffing or altering the traffic without modifying the client. However, this relies on the connection being encrypted with a valid certificate for the server domain, and on the client refusing to act if this is not the case. Given that condition, the connection can only be decrypted by someone holding the private key for that SSL certificate.
If your "client" is just a web browser, this means that third parties (e.g. at a public wi-fi location) can't intercept the data without alerting the person using the site that something is suspicious. However, it doesn't stop a user deliberately by-passing that prompt in their browser in order to sniff the traffic themselves.
If your client is a custom, binary, application, things are a little safer against "nosy" users: in order to inspect the traffic, they would have to modify the client to by-pass your certificate checks (e.g. by changing the target URL, or tricking the app to trust a forged certificate).
In short, nothing can completely stop a determined user sniffing their own traffic (although you can make it harder) but properly implemented SSL will stop third-parties intercepting traffic.
The other, more important reason not to add confidential information into URL with GET requests is that the web server and any proxies on the way will log it. POST parameters don't get logged by default.
You don't want your passwords to show up in server logs - logs are usually protected much, much less than, for example, the password database itself.

Redirecting SSL to non-SSL after login authentication

I have a Cakephp 2+ site that needs certain actions to require an SSL connection, (i.e. login, password reset, etc.), but I don't require the entire site to be secure. While implementing this I found that the Session was not being saved when moving between the SSL and non-SSL pages. I found this question on stack https://stackoverflow.com/a/12068099/1353839 that solved the issue for me, but I am wondering at what cost.
The answer in the above question required commenting out a line in lib/Cake/Model/Datasource/ as follows:
if (!isset($sessionConfig['ini']['session.cookie_secure']) && env('HTTPS')){
// $sessionConfig['ini']['session.cookie_secure'] = 1; // <-- Commented Out
}
Are there any security ramifications to doing this? Also, is there a way to do this without affecting the cake core files since that is generally frowned upon?
Thanks in advance.
First off, modifying the core file is a bad idea, you should set 'session.cookie_secure' in your configuration instead.
The purpose of a session is to store critical information on the server and associate that information with a client via a session key. The session key is typically stored in a cookie and sent to the server with every request. Using secure cookies prevents the session key from being transmitted to non-SSL pages; that is why you cannot see the session data.
Turning off secure cookies allows the session key to be sent to non-SSL pages, however, it is sent as plain text so it you will be susceptible to session hijacking. Depending on what your doing, this may or may not be a big deal. Regardless, by using SSL for login, password reset, etc... you will protect the information that your users' actually enter (i.e. username, password, etc...).
You are going to authenticate users over SSL so that a MITM cannot intercept the authentication but then afterwards you want to let the session cookie be sent through plaintext HTTP so that the MITM has the opportunity to pick it up and use it for themselves?
Given that, what's the point of using SSL at all?
(Yes, I know your session cookies expire so getting one of those it not as good as getting the actual credentials, but this still sounds like a terrible idea security-wise.)
Don't modify the core files. You can specify the required configuration in your app/Config/core.php. Read the comments in there above the session configuration statement and it mentions how to specify required ini setting.

Safe to send login credentials using HTTP and not HTTPS?

Is it safe to submit an HTTP POST whose body contains plaintext username and password, or is HTTPS completely necessary?
HTTPS is required. All HTTP traffic can be sniffed.
No, HTTP alone does not give you any security at all. If someone is able to read the network traffic, they would be able to read the credentials too.
The network traffic might also be protected separately, but you can’t control the network. But you can control your application. So HTTPS ist a must.
It's never safe to send an unencrypted, plaintext username and password over a wire others have access to.
While it's safe to send encrypted data over HTTP, HTTPS does this for you, giving you the added benefit of TLS. Given how well it stands up theoretically and in practice, it's far more compelling to use than inventing your own algorithm.

Securing parts of an HTTP request?

How does one go about securing parts of an HTTP request, say their Session ID? I know you can use HTTPS, but then your servers must decrypt all of the request. Wouldn't it be ideal to only encrypt the required parts of a request?
Are there any frameworks or resources out that that allow you or inform you how to do this?
HTTPS is the correct tool to use. The computational load of decrypting the packets is very low. Google changed to HTTPS by default for the whole of GMail earlier this year, and they report that the CPU load on their servers for SSL encryption/decryption is around 1%.
If you only encrypt part of the stream then you still have the problem of man-in-the-middle and replay attacks. SSL is the only way to prevent these. It doesn't really matter if the session ID is encrypted. If a man-in-the-middle can capture it, he can reuse it in it's encrypted form, and the server wouldn't know the difference.
Here's a blog post about Google's experience since the GMail switch to 100% SSL.
HTTPS is all or nothing. If not all elements on a page are secured with HTTPS then users will get usually get a "broken lock" in the upper left corner. This is because an attacker could use this to inject an attack similar to xss and obtain the document.cookie value.
Further more if 1 request is sent with a session id then an attacker can obtain the value and authenticate as you.

Resources