Securing parts of an HTTP request? - security

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.

Related

Best practice to secure request payload between client / server during post request transmission node/express js

Narrowing down from a broad topic, i have a specific question (maybe a little bit 'tin-foil hat').
This question is regarding the best practices of securing data transmitted in a post request between the client and server. The background is a web app I'm developing to learn more about node and express js.
Although the example i'm using is for login credentials it really could be about any information being transmitted in a post request from a form submit to an express server.
example:
client submits form data through a button click event on the client. I'm using vue for the front end, but this is a generic question. On the client page i'm also using (inside an async function):
const resp = await axios.post("http://someurl.com/login", {client:email, pw:pw});
in chrome developer tools on the network tab i can see the request payload. In the example it looks like:
{client:"some email address", pw:"some password"}
Would it be better to transmit the payload already encrypted / encoded? Then have it decrypted / de-encoded on the server?
For transmitting sensitive information, is it better to use a signed cookie?
The plan, should i ever get through all of this is to use let'sEncrypt for HTTPS.
Is it reasonable to only rely on HTTPS for protecting this type of payload?
For reference, on the express server, password gets hashed and compared with a hashed version from a database. I've read about Helmet, and csurf and intend to use them in the final product as well. There's a lot of great information in this answer. Which is incredibly awesome and talks about the importance of HTTPS over HTTP.
Any additional references / thoughts / practical considerations are appreciated.
Using HTTPS will encrypt your payload between your client and the server.
Any javascript handling on the front end can be circumvented by users with enough knowledge so all frontend is mainly there for is to facilitate a better user experience. Password confirmation checking, correct fields filled out etc.
Your main source of security will be your eventual LetsEncrypt HTTPS certificate and your hashing and salting applied at the server end. As you correctly surmised HTTP send passwords in clear text which is bad. As a warning though even HTTPS can be defeated if somebody wants it bad enough with a number of techniques to high jack Certificate Authorities (I believe Root CAs should be offline anyway) or modify trusted certificates on a users PC.
Although it does depend on the amount of effort required by the hacker vs potential return hence the more you are trying to protect the greater the security required before it becomes not worth the effort for any potential hacker to attempt to circumvent the security of a particular site. (Reputation hacks aside of course)
Hope this helps.

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).

Cookie security when passed over SSL

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.

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.

How to pass credentials securely in a http url?

I have a public facing web page in .Net that I would like to put anchor tags in that go to a web page produced by a Java server in my distributed system. For example, Bob logs in from the WWW and goes to the home page. I would like to have a link to http://javaserver/form.jsp?username:Bob in the home page. But that would be insecure if someone on the internal network was snooping. They could just put in that url and act as Bob through a replay attack. Encoding the username is also open to a replay attack. Any ideas?
Thanks!
https://javaserver/form.jsp?username:Bob still opens me to a replay attack by just putting in that url.
Use https on the public and the private servers
Send the user id and add a long and random token that will validate the user (to be delegated to the original server if necessary).
Use POST requests if you can
The random token should be created with a cryptographically secure random number generator. It should also be changed/invalidated after a certain amount of time. If you are going to delegate the verification to the public server, you will also need to authenticate the delegating (local) server in a secure manner. To prevent brute-force attacks, block repeated invalid attempts.
There are quite a few pitfalls, so be wary of implementing any sort of security mechanism yourself.
Use cookies and SSL in your authentication. I'd be surprised if you aren't already.
hmmm - just thinking out loud - if its not https, its open to snooping. You could encrypt the username with a timestamp so that the window is brief. not a great answer, but since http is not secure....
I think the best solution is to use https. This way anything you send to Bob is secure from prying eyes.

Resources