Public Key Pinning Extension for HTTP
tools.ietf.org
tools.ietf.org
It's not a perfect fix to the CA problem, but it is a huge step in the right direction (which is towards decentralization and peer trust).
Trevor stopped paying for the TACK test server so Im guessing the push has died. Trust agility and certificate transparency really need to come about...yesterday.
People inside of Google were putting together HPKP at the same time that we were putting together TACK, so that was pretty much the end of TACK. HPKP is really simple for Google (just pin their own CA), but isn't as clean for most other major sites (who are stuck with many CAs). It also doesn't offer a layer of indirection away from CAs, which again, is not an issue for Google (they already have a layer of indirection in the form of their own CA), but is less ideal for the rest of us.
It's better than only being able to hardcode pins in the browser binary, but it's a shame that it doesn't take on some of the other pain that's come up with pinning.
- For TACK, the pinned key is a custom key created just for that, and is transmitted in TLS
- For HPKP, the pinned key is a CA cert key (one of the CA on the chain), and is transmitted in HTTP
I think pinning the CA cert key makes more sense, because this is what they were created for: certs certify, the matter is in how you transport them. OTOH putting all the pinning information directly in the certificate makes more sense to me. We should have every domain owner running its own CA, with a cert that has all required pinning data, signing all TLS keys of the servers, and then sending the minimal chain "server cert" <- "CA cert", and then browsers would pin that cert.
[1] http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.11.6...
Chrome has been doing public key pinning out of the box for about three years now, though the feature has only been active for some Google properties and a couple of hand-picked high-profile sites [2]. Firefox has recently added support for static pins, plans to support the HTTP extensions exist [3].
Alternative or complementary proposals include DANE/TLSA [4] (DNS-based Authentication of Named Entities; stores certificate infos for any protocols in a new DNS record; requires DNSSEC) and TACK [5] (Trust Assertions for Certificate Keys; a similar mechanism to the one proposed in this draft but implemented as a TLS extension; possibly discontinued).
[1] https://tools.ietf.org/html/draft-ietf-websec-key-pinning-21
[2] https://www.imperialviolet.org/2011/05/04/pinning.html
[3] https://wiki.mozilla.org/SecurityEngineering/Public_Key_Pinn...
[4] https://en.wikipedia.org/wiki/DNS-based_Authentication_of_Na...
[5] http://tack.io
Also, your second link point to a 404.
There is a 'g' missing in the link to Mozilla Wiki: https://wiki.mozilla.org/SecurityEngineering/Public_Key_Pinn... .
And https://tack.io doesn't respond for me whereas http://tack.io does.
[1] https://bugzilla.mozilla.org/show_bug.cgi?id=787133 [2] https://developer.mozilla.org/en-US/docs/Web/Security/Public...
https://addons.mozilla.org/en-US/firefox/addon/certificate-p...
It does exactly the most useful thing possible within the current state of the internet: it remembers the certs you've seen before (gasp!) and tells you if they've changed. Simple.
Say a user visits a website for the first time and the site's key is pinned in their browser. Then the user doesn't visit for a long time and the pinned key expires. Later, the user visits again but now the pinned key is no longer being used. What should happen? According to the document:
> The UA MUST ignore any expired Known Pinned Hosts in its cache.
This is unfortunate, since the point of pinning keys is to minimize the risk of hijacked CAs down to the very first connection. With this system that risk occurs every time the key expires, and with several pushes to shorten the expiry times of public keys this could be quite often.
In the example above, could the expired key be used to sign the new one? It wouldn't be used to secure the connection, but only to update the pinned key, where the chain of trust is unbroken from that very first visit.
Key pinning is a trust-on-first-use (TOFU) mechanism. The first time
a UA connects to a host, it lacks the information necessary to
perform Pin Validation; UAs can only apply their normal cryptographic
identity validation. (In this document, it is assumed that UAs apply
X.509 certificate chain validation in accord with [RFC5280].)
The UA will not be able to detect and thwart a MITM attacking the
UA's first connection to the host. (However, the requirement that
the MITM provide an X.509 certificate chain that can pass the UA's
validation requirements, without error, mitigates this risk
somewhat.) Worse, such a MITM can inject its own PKP header into the
HTTP stream, and pin the UA to its own keys. To avoid post facto
detection, the attacker would have to be in a position to intercept
all future requests to the host from that UA.
Thus, key pinning as described in this document is not a perfect
defense against MITM attackers capable of passing certificate chain
validation procedures -- nothing short of pre-shared keys can be.
I think for most of us, this is still a big improvement. But for people under repressive regimes, isn't there a high chance that you get the MITM great-firewall-of-wherever the first time, and then you're stuck with it from then onwards even if you can tunnel out at some later time (this is assuming the government has control over at least one CA)?Any out of band key exchange is.
The infrastructure is already in place. Do a good deed and publish your records today, if you haven't already.
The sslstrip problem seems impossible to make secure using the existing web. The inherent problem is that the web allows both insecure and secure connections; if https doesn't work, people [or browsers] will just try http, and there is no way to determine if a site is supposed to use https or not. (It would be nice if we required a 'ssl.' subdomain be used for https-only connections, but nobody seems to like that suggestion, and there's some scaling issues)
I think the most permanent, flexible solution for all these problems is twofold: one, a protocol which makes secure connections mandatory, and two, mandatory multiple identity verification.
Unlike SPDY, which allows non-SSL connections and used to allow compressed headers to be encrypted, another protocol (or layer?) should be introduced that makes it impossible to have a connection which isn't encrypted and signed by a CA (no self-signed certs allowed). This would ensure that no communication with a host over this protocol would be of questionable integrity. Users could decide for themselves that if this connection doesn't work, they simply won't try to contact the host via lesser means (like https).
Going further, it seems to me there's two logical ways to prevent a hijacked CA from feeding you spoofed certs on the initial connection: Convergence, and/or multiple CA verification.
Convergence stops the initial-connection attack by requiring multiple independent parties agree on the data you're getting. The hijacker would have to also hijack all the Convergence peers for this to succeed, which is effectively very difficult. But this requires a highly available public network of peers to work, which is problematic in many cases.
Instead, one could provide a certificate chain on the initial connection to the destination host with the same certificate signed by multiple independent CAs. IMO this is a better solution than Convergence because it doesn't require the consensus of a live public network or multiple hosts, but does still provide a guarantee of authenticity verified by multiple independent parties, which would again be very difficult to hijack all at once.
To provide this second method you'd need to do several things: One, send the same CSR to multiple CAs and collect the certs (this already works). Two, require a protocol identifier that mandates only secured connections (something other than http/https, so users don't get confused). Three, mandate no self-signed certs. Four, require a certain minimum 'assurance index' be reached by using a set of heuristics to classify the certs received and determine if they're from enough CAs (or CAs different enough from each other, like one from the UK, one from Iran and one from Brazil). Five, make sure all the certs match and are all signed by the same origin host key.
Then all you'd have to do as a user is type in 'rfsp://mybank.com' and your connection would either succeed securely the first time, or irreversibly fail. The server admin would just tack on a bunch of different certs from different CAs into the chain and provide the new encryption layer, under which HTTP (or whatever) would pass.
(It would be nice if we required a 'ssl.' subdomain be
used for https-only connections, but nobody seems to like
that suggestion, and there's some scaling issues)
Fun fact: the .trust gTLD requires all connections to be made over HTTPS:https://www.nccgroupdomainservices.com/wp-content/uploads/20...
and this Langley post from july indicates that there's interest from chromium in enforcing that in the browser: (section 6.1)
And how does your proposal solve that? Nothing will stop people from trying 'http://mybank.com' if 'rfsp://mybank.com' fails. You could try to have the browser stop the user, e.g. "You tried to visit 'mybank.com' over a secure connection, but failed. Are you sure you wish to visit 'mybank.com' over an insecure connection?" But that could also just be displayed after a user attempts an HTTPS connection to 'mybank.com'.
I don't see any advantage of RFSP that we couldn't just roll into HTTPS to avoid creating an entirely new protocol and to not undo the great effort that's been put forth into attempting to get people to use HTTPS.
1. The https protocol allows self-signed certs, which defeats the purpose of a guaranteed secure connection.
2. The https protocol doesn't have any way of differentiating between a normal connection and one which mandates multiple certificates all verify the same identity if the host has been mitm'd. You'd go back to the chicken-and-egg that is HSTS and your initial connection is hijacked again.
3. Because https is inherently broken (for the edge cases discussed here), the users will not be able to rely on it. Yes, it would require re-training everyone in the world to always use this other protocol for their secure communications. But it would guarantee a secure connection every time without having to think about it. I'll bet that's a tradeoff most people are willing to make.
The idea is to never allow the user to make an insecure connection. Give a user enough rope and they'll hang themselves.
I just do a 301 redirect to HTTPS on any requests that hit port 80. What makes that insecure?
If the client has visited the server previously and obtained an HSTS header, it'll refuse to connect to make an insecure connection.
All hobbyists and small shops will be out of luck however (and there are a lot of those), they have to go back to sending plain text in the clear.