Designing a new Security Header: Expect-Staple

I've talked about OCSP Stapling in the past and more recently about the new Must-Staple flag you can set in your certificates, but there's a bit of a problem. To go from not implementing Must-Staple straight to implementing it without any testing to see if you're ready is a bit dangerous so I'm hoping this new header will fill that gap.


OCSP Stapling

OCSP Stapling has been around for a long time and I covered it back in March 2014! You can read the blog, OCSP Stapling; SSL with added speed and privacy, for more details but the title basically gives you the TL;DR. OCSP Stapling fixes certain performance and privacy issues with OCSP revocation checking and everyone should be using it.


OCSP Must-Staple

The one shortcoming of OCSP Stapling was that the client didn't know if the server was supposed to OCSP Staple or not, there was no way to indicate that. Enter, OCSP Must-Staple. In short, this is a flag that you can request your CA to set in the certificate which tells the browser to only accept the certificate if it was served with a valid OCSP Staple. This is great because we can now ensure that reliable revocation checking will happen for our certificates, but what happens if your server doesn't reliably OCSP Staple? It could be failing to staple an OCSP response on 1% of connections and you have no real way of knowing. Those 1% of visitors won't get an OCSP Staple and the browser will fail the connection without you knowing that it ever even happened. This is the gap I'm trying to fill with the Expect-Staple header, you can find out if you're reliably providing a stapled OCSP response before you enable Must-Staple.


OCSP Expect-Staple

I've actually already talked about OCSP Expect-Staple before because Chrome does have the ability to do this right now. The problem is that the flag is set by making an addition to the HSTS Preload List. You can read more about HSTS Preloading and see what the list is, but this presents a couple of speed bumps to site owners. The first is that setting Expect-Staple is a manual process, there is no automatic submission like there is for HSTS. You have to get in touch with the Chromium team and ask them to either add the entry for your or update your existing entry if you're already preloaded. The other problem is that it's a slow process. After requesting your entry be added to the list it can easily be several weeks before it lands and the same again if you decide to remove it. The header alleviates both of these issues and gives the site owner much more control. I've already made the request and the change landed in Chrome v58. You can see my modified HSTS entry here but here is the before and after.

{ "name": "scotthelme.co.uk", "include_subdomains": true, "mode": "force-https" }
{ "name": "scotthelme.co.uk", "include_subdomains": true, "mode": "force-https", "expect_staple": true, "expect_staple_report_uri": "https://scotthelme.report-uri.io/r/default/staple/reportOnly", "include_subdomains_for_expect_staple": true }



It would be a lot nicer to not have to increase the burden on the size of the HSTS Preload List and to remove all of the requirements set by the list just to have Expect-Staple set, this is why I've drafted a spec for a HTTP response header instead.


The New Security Header

The new security header has been named Expect-Staple and I'm hoping the spec makes for easy reading. A huge shout-out has to go to Emily Stark as I based the Expect-Staple spec off her Expect-CT spec which basically laid all of the groundwork for me. You can see the new spec right here on GitHub.

For regular readers and those fond of other security headers like HSTS and HPKP there will be a lot of familiarity with the new header in terms of some of the directives. The basic idea of the header is that if the connection to the site didn't include an OCSP Staple, we want the browser to report that and let us know so we can see what went wrong and if we're ready for Must-Staple. At the time of publication we have the following directives:


report-uri

This is the location the browser will send our report to as a POST request with a JSON payload.


max-age

This is the number of seconds the browser should cache and apply this policy for.


preload

To indicate consent for addition to the HSTS Preload List.


includeSubDomains

Apply this policy to the current domain and all subdomains below it.



The spec gives some examples of what these headers may currently look like.

Expect-Staple: max-age=0; report-uri="https://example.com/report/staple"  
Expect-Staple: max-age=3600; report-uri="https://example.com/report/staple"  
Expect-Staple: max-age=31536000; report-uri="https://example.com/report/staple"; includSubDomains  
Expect-Staple: max-age=31536000; report-uri="https://example.com/report/staple"; includSubDomains; preload  



Please do take the time to read the spec and give me any feedback you have. As it stands I think the spec is ready for public input but I'm sure there are improvements that can be made. The one main change that I'm considering right now is a new directive, enforce.


Enforcing the policy

As the header currently stands it's basically a "report-only" header. That is, it will alert us when things aren't as we expected, but it won't take any action as a result. With a new enforce directive we could instruct the browser to block connections that didn't come with an OCSP Staple. Right now the Must-Staple flag in certificates would be set by the host when they obtain a certificate and prevent an attacker abusing that certificate after it has been revoked. There is another scenario though where an attacker could obtain their own rogue certificate from a compromised CA and not ask for the Must-Staple flag to be set. The attacker could then serve this certificate to visitors, who won't require an OCSP staple as the flag isn't set and most likely won't do their own online revocation checking anyway. Even if the host does pick the rogue certificate up in Certificate Transparency logs and request a revocation, the client still isn't likely to check and ever know. Enforce mode would protect our visitors in this scenario as their browser would know to expect a valid OCSP Staple whether or not the Must-Staple flag was set in the certificate because we'd previously served them an Expect-Staple header with the enforce flag set. I will see how the spec goes down and may make an addition at a later date to add the directive. For now, any feedback you have would be great!

Author image
About Scott
Researcher, blogger and international speaker. I'm the creator of report-uri.io and securityheaders.io, free tools to help improve online security.