What is it and why should I care?
HTTP Strict Transport Security (HSTS) is a new(ish) technology that allows an application to force browsers to only use SSL/TLS (HTTPS, not HTTP) when visiting their application. This occurs when the application sets an HSTS specific HTTP response header. Browsers that support HSTS recognize the response header and only communicate with that application over HTTPS for the specified time. Here are the basic steps of the flow:
Step 1: A user visits application, either over HTTP or HTTPS. For most users this will be HTTP as they often forget (or don’t know) to type in https://
Step 2: The application renders the response, including the HSTS response header that specifies the site should be loaded over HTTPS only for the next 90 days.
Step 3: Supporting browser will not issue a non-SSL request to that application for the next 90 days.
What should I do about it?
Set the header! This is another no-brainer. There are no backwards compatibility issues and it only enhances your security posture. By adding the header, you give your users greater security with very little effort on your part. Here’s a quick example of what setting the header might look like if you happen to code in Java.
HttpServletResponse ...; response.setHeader("Strict-Transport-Security", "max-age=7776000; includeSubdomains");
The snippet above sets the amount of time that the browser should only use HTTPS when accessing the application (or any subdomains) to the next 90 days.
The max-age attribute is required and sets the number of seconds that only HTTPS should be used. This can be set to whatever you want. Setting this to 0 tells the browser to delete the existing policy and not require HTTPS.
The includeSubdomains attribute is optional. It does not take a value; its’ presence signifies that any sub-domains should abide by the same HSTS policy.
The time length (90 days in our example above) should be reset (overwritten) by the supporting browser every time the HSTS response header is received. What this means is that if you set the length to 90 days, and a person never goes more than 90 days without visiting your site, they’ll always be visiting over HTTPS since the 90 days starts over every time they visit. Just keep in mind that if you change the setting, all browsers that access your site (post-change) will get the update. If you set it to 90 days today and 10 tomorrow, the browser throws away the 90 days and replaces it with 10.
The HSTS spec also recommends (though the current spec doesn’t seem to require) that the browser not send any data to the server if the channel is insecure for any reason (certificate issues, domain issues, etc.). This appears to be the route being taken by current browser implementers, which is the most secure option. This means that those warning pop-ups users often see over HTTPS connections (mixed content, expired cert) don’t appear any more and instead the user is simply shown an error.
Pre-loaded HSTS Lists
If you want to have even more assurance that your site is only ever visited over HTTPS, you can even request that your site be pre-loaded into a list of HSTS sites. This means the browser will require you to got that site over HTTPS on your very first visit! Paypal is one such well-known site that does this.
HSTS is a simple and effective control to let an application further protect its’ users by forcing them over HTTPS. If your site is (or at least should be) HTTPS only, then implementing HSTS can provide you and your users with enhanced assurance.
This article will describe how to protect your J2EE application from Insecure Communications attacks using ESAPI and other techniques. As with all of the detail articles in this series, if you need a refresher on OWASP or ESAPI, please see the intro article The OWASP Top Ten and ESAPI.
What does Insecure Communications mean? As usual, let’s check in with what OWASP says it is:
“Applications frequently fail to encrypt network traffic when it is necessary to protect sensitive communications. Encryption (usually SSL) must be used for all authenticated connections, especially Internet-accessible web pages, but backend connections as well. Otherwise, the application will expose an authentication or session token. In addition, encryption should be used whenever sensitive data, such as credit card or health information is transmitted. Applications that fall back or can be forced out of an encrypting mode can be abused by attackers.” [from here]
Insecure communications is an issue any time data traverses a communications path. For many standard J2EE apps, you’ve got a setup like the following you have to worry about:
- client browser -> web server
- web server -> app server
- app server -> DB server
-> LDAP server
-> JMS server
This is a simple but very common setup for J2EE apps. There are many more layers that could be added, and even a few could be taken away. Here’s the point: you need to think about insecure communications at every tier. You could make the argument that the browser -> web server connection is the most important, and I might even partially agree with that since that’s where the most nefarious things tend to live: on the wide open web. Still, the app server -> DB server connection is pretty important due to the data being transmitted. The point is, all the layers are important since important data is moving from point A to point B.
We know we’ve got to protect the data “in transit”, ie. as it moves across the wire, so …
Protecting against insecure communications could take many forms, but in the web app/J2EE world, it primarily means SSL/TLS, so that’s what we’ll discuss here. That’s right, our good old friend SSL/TLS. For the uninformed or if you just need a good refresher, have a look at this great doc produced by the good people at OWASP.
The use of SSL/TLS is not as easy as flipping a switch, as you might hope or think. There are various issues that have to be taken into consideration. I don’t want to simply re-hash all of the recommendations provided by OWASP, so I’ll try to focus on those most commonly seen by the J2EE crowd. (All the issues called out are important, but not necessarily developer-oriented – some are more frequently handled by network/sys admins.)
Most of us know what SSL/TLS does, but in case you don’t, the intent is to encrypt the data as it is in transit between points A and B. Note: There is no protection provided at the endpoints, but the issue at hand is protecting data while in transit, so SSL/TLS fits the bill.
Now that we know we need SSL/TLS, how do we implement it correctly? There are millions of pages dedicated to setting up SSL/TLS, so let’s assume you’ve gone through that and now need to require it for your particular application. There are various ways to do this. Let’s talk about a few.
1. Setup your web/app server to only have an SSL/TLS (https) enabled service listening, ie. no standard http service running, or at least block that port on the firewall. This option is fine if you can do it, but there’s usually a reason you can’t, and in addition, it doesn’t help if anyone ever comes along and adds http back in – at that point – you’re back at square one.
2. The standard Java way is to add a transport guarantee to the web.xml file. The following snippet shows an example.
<security-constraint> <web-resource-collection> <url-pattern>/admin/*</url-pattern> </web-resource-collection> <user-data-constraint> <transport-guarantee>CONFIDENTIAL</transport-guarantee> </user-data-constraint> </security-constraint>
This snippet requires all requests that match the pattern “/admin/*” to go over SSL/TLS. If they are requested over standard http, the request will be redirected over https. This is a fine solution if your application is structured in a manner that you can protect the appropriate urls by using simple url pattern matching. If that’s not true, this method can lead to a rather verbose configuration.
3. The ESAPI way of performing this task is also very simple. This can be done by using the assertSecureChannel method as in the following snippet.
//this method can throw an AccessControlException //uses the current http request - there is an overloaded method that accepts //a specified http request object as a parameter ESAPI.httpUtilities().assertSecureChannel();
If this method finds that SSL/TLS is not being used, it does not attempt to redirect you there. Rather it throws an AccessControlException, which can then be caught and dealt with appropriately. If you’d like all of your pages to require SSL, this code could simply be added to a J2EE filter configured to execute on all requests (“/*”).
4. Other frameworks … there are tons of frameworks, or even custom code that could be used to perform this task.
Ok, now we’ve seen a bit about how to require SSL/TLS in the J2EE environment, let’s talk about a few of the relevant gotchas that J2EE folks have to deal with.
1. Make sure you use SSL/TLS between all tiers. Don’t cover just the browser -> web server. Ensure every path is protected.
2. Require SSL/TLS for all login (including page you login from) pages as well as any authenticated pages after login.
3. Use http POST as opposed to http GET for any sensitive information. This is always true, but makes even more sense with SSL/TLS as the POST data is protected by SSL/TLS, but the url is not as that is required to make the request. This means others viewing your request can still see your sensitive data since it’s part of the url.
4. Mark all your user cookies secure: this prevents your browser providing the session cookie to an attacker in the event of an attack that causes you to request a non-SSL/TLS url from the application. If the cookie is not secure, your browser will still happily provide the cookie even if the site doesn’t support http … protect your users.
5. Don’t put any insecure content on your secure pages. This could allow an attacker to “inject” content into the page and have that information presented to a user as if it came over the SSL/TLS connection.
6. Often times it is just easier to protect the entire site with SSL/TLS. This is fine, but be aware of any performance concerns. SSL/TLS does require overhead. It’s gotten pretty optimized over the years, but it will always be slower than http. If you are on a high volume site, think about what data you are presenting, and test both with and without SSL/TLS to verify any performance differences. However, no matter the performance difference, always follow the other rules listed here. Protection of data is better than a slightly faster site (since we are talking about security here :>).
7. Stay educated and patch when necessary. SSL/TLS has been a standard technology for many years now. However, just within the past few months, there have been reasonably large bugs found and resolved. Largely, these bugs have to do with implementation and not design, however you need to stay educated nonetheless.
8. Comply with policy / legal regulations. For some types of data (credit cards and SSN’s for instance), there are legal requirements imposing the use of SSL/TLS to protect the data in transit. These may or may not apply to you, but be sure you know, because failing to meet them could be a very bad thing indeed.
So there you have it. SSL/TLS is fairly well known, but there are some things to look out for when building a site that uses it.
Note: In very recent days, news came out that Robert “RSnake” Hansen and Josh Sokol were able to poke some pretty major holes in SSL. I have not had the time to adequately research their findings, but you should. I do assume, based on the credence of the researchers, that the research is sound, so pay attention. This does however point to the fact that a defense-in-depth approach to security as well as building security in at every layer are best practices.
For some additional background and information on SSL/TLS, see the Transport Layer Protection Cheat Sheet referenced above.
Well, that’s it. Hope you’ve found this article helpful. Let me know if you have any questions or suggestions. Feel free to comment.
Other articles in this series:
Part 0: The OWASP Top Ten and ESAPI
Part 1: The OWASP Top Ten and ESAPI – Part 1 – Cross Site Scripting (XSS)
Part 2: The OWASP Top Ten and ESAPI – Part 2 – Injection Flaws
Part 3: The OWASP Top Ten and ESAPI – Part 3 – Malicious File Execution
Part 4: The OWASP Top Ten and ESAPI – Part 4 – Insecure Direct Object Reference
Part 5: The OWASP Top Ten and ESAPI – Part 5 – Cross Site Request Forgery (CSRF)
Part 6: The OWASP Top Ten and ESAPI – Part 6 – Information Leakage and Improper Error Handling
Part 7: The OWASP Top Ten and ESAPI – Part 7 – Broken Authentication and Session Management
Part 8: The OWASP Top Ten and ESAPI – Part 8 – Insecure Cryptographic Storage
Part 9: The OWASP Top Ten and ESAPI – Part 9 – Insecure Communications
Part 10: The OWASP Top Ten and ESAPI – Part 10 – Failure to Restrict URL Access