This article suggests pinning ones own cert, and perhaps an intermediate up the chain. It seems that even pinning one root cert would be an improvement, because then that specific CA would have to compromised to MITM. As opposed to the situation now, in which compromising any trusted CA can permit MITM.
If you pin to a root CA you're vulnerable to MITM if an intermediate CA that has the root in its chain of trust is compromised. Because that compromised CA would be able to sign a cert for an arbitrary domain while still satisfying your pinning directives.
By pinning to a public key you're saying "is this public key in this certificate's chain of trust?". Pinning to a root you have the most flexibility but the least amount of protection against MITM.
"user agents (UAs) will require that the host presents a certificate chain including at least one Subject Public Key Info structure whose fingerprint matches one of the pinned fingerprints for that host."
This makes it easier to deploy. If an org repeatedly gets their certs from a single CA they can just pin that CA. It does of course open you up to being compromised if anyone compromises that CA. But, like you said it's a big improvement over nothing.
Yes, key pinning allows a domain owner to choose who certifies them, instead of potentially accepting anyone to certify them. It's a kind of "reverse" certification.
> A flaw in this system is that any compromised root certificate can in turn subvert the entire identity model. If I steal the Crap Authority's private key and your browser trusts their certificate, I can forge valid certificates for any website.
You don't have to compromise the root. This could still happen if a trusted intermediate CA's private key is compromised, because that CA's certificate was signed by the CA in the chain of trust that ultimately terminates with a trusted root.
Also, how does rfc7469 work with respect to CRLs and OCSP?
From what I understand neither is possible, even though this was added to Firefox 1.5 years ago. Which really makes you go Hmm. I'd expect I'm not the only one who wants to pin few certs for sites that I visit frequently.
> I'd expect I'm not the only one who wants to pin few certs for sites that I visit frequently.
How can you tell what the backup pin for those websites would be without the owner publishing the HKPK headers? How do you know the max-age of their current pin?
It sound a bit like trying to stuff things into the browser's cache - a road to disaster.
You can get their certs pinned into your browser by adding the HKPK header to them. It'll also mitigate risks for your other visitors (if any; may not be a public site).
I feel stupid having to ask this question, but is a backup key literally just a different SSL certificate issued by the same or another CA for the same domain(s)? You keep it on standby in case your primary certificate is compromised? Do I use the same CSR and private key or do I generate new ones?
EDIT: Okay, the coffee is flowing and the gears are starting to turn. I guess if I'm going to pin my cert, I should generate a new private key for the backup, and if I'm going to pin the intermediate cert, I should use a different CA. And for maximum protection, do both, and not keep both private keys on the same servers. Does that make sense?
It's the hash of the SubjectPublicKeyInfo field of an X.509 SSL cert. A different pin == a different public key, so you will need to generate a new CSR with a new key pair, as the public key is embedded in the CSR.
Yes. You want everything to be completely separate. In a way, It's kinda like falling over to a failover machine -- different storage, different network connection, etc.
If your "primary" certificate or any of the others in the chain is compromised -- for whatever reason -- you want the ability to immediately switch over to your "backup" certificate without problems or affecting your users.
I'm not sure if this had been mitigated in the standard, but the pinning implementations I've seen used in Android apps rely on client-side (i.e. app) verification. It's an inconvenience, for sure, for someone trying to emulate the app (in order to connect to the server API). But it's not sufficient to stop a determined attacker with a bytecode decompiler.
EDIT: Just to clarify given the comment below (and downvotes...), I'm talking about a different attack scenario. Here's a decent source on some of pinning's weaknesses for your standard MITM scenario: https://www.owasp.org/index.php/Certificate_and_Public_Key_P...
I'm not sure I quite understand your point, but wouldn't an attacker with the ability to modify an app on someone's device have access to the plaintext anyway?
Oh sorry, I probably should have been a little clearer. I'm thinking of a different attack scenario where the attacker wants to MITM your app to inspect traffic and utilise your server-side API for unintended purposes. So it looks like:
So you could use this to pull down real-estate listings from a real-estate app in an easily parsed format (usually JSON). Or write an app that pull down the odds from various sports betting app APIs, detects arbitrage opportunities and automatically places bets using their APIs...
EDIT: Oh and on the plaintext thing, generally no. Most apps will use TLS for app-to-server comms. Pinning in this context means they bundle the cert (or signature) with their app. By the looks of this (http://security.stackexchange.com/questions/29988/what-is-ce...) it's a similar story with chrome: they pre-bundle some signatures. The alternative is to pin on the first interaction, but this leaves you potentially vulnerable if an attacker is listening in on that first interaction. It also raises the question: what happens if the website needs to revoke and re-issue? Wouldn't pre-bundling mean you'd have to wait for the next browser update (and for out of band commms to have occurred between google and the website)?
Right, but the purpose of key pinning is to prevent a MitM from learning the plaintext, not Alice or Bob. There are any number of means an attacker could employ to reverse-engineer an API (decompilation, memory dumps, debuggers, ...). This is asking for more of a DRM-like solution (with all the issues that come with it).
I might be misunderstanding you, but I don't think Public Key Pinning is intended to prevent this scenario at all. Public Key Pinning is a method for a client to authenticate a server. If you decompile the app and recompile it with the public key of your MITM server, the app would of course connect to your MITM server. Or, it seems to me, if you have that level of control over the client, you could just disable public key pinning checks completely.
In addition to the other comments on this subthread, a point I think is worth making:
If you're providing both an app and a server for the app to talk to you, you control both ends of the TLS connection and can pin however you'd like; you're not limited to HPKP and key-continuity. Secure apps have been doing custom pins of TLS keys long before HPKP got rolled out.
So now the flip side question. How would say a corporate SSL/TLS proxy, which is effectively a MITM, bypass this security feature? I can see the TOFU is easy to defeat by dropping the header before it gets to the client, but what if they're allowed to roam on and off the proxy?
I guess the proxy would add both its own key and upstream keys, as is allowed by the spec; in a way the proxy key will act as the normal key and the true site key will act as a backup key.
The fun begins with report uris, it doesn't seem like there's a way to specify multiple of them.
Google Chrome allows TLS MITM proxies to override HPKP settings (which is not without controversy):
We deem this acceptable because the proxy or MITM can only be effective if the client machine has already been configured to trust the proxy’s issuing certificate — that is, the client is already under the control of the person who controls the proxy (e.g. the enterprise’s IT administrator). If the client does not trust the private trust anchor, the proxy’s attempt to mediate the connection will fail as it should.
I'm personally fine with this. MITM proxies are a valid use case. I do think that all parties should be made aware of it, but that's probably something that has to be fixed via laws (I think some European countries forbid this practice unless it's been made clear that there can be no expectation of privacy on a company-provided device).
25 comments
[ 2.8 ms ] story [ 54.2 ms ] threadDo I have that right?
By pinning to a public key you're saying "is this public key in this certificate's chain of trust?". Pinning to a root you have the most flexibility but the least amount of protection against MITM.
"user agents (UAs) will require that the host presents a certificate chain including at least one Subject Public Key Info structure whose fingerprint matches one of the pinned fingerprints for that host."
This makes it easier to deploy. If an org repeatedly gets their certs from a single CA they can just pin that CA. It does of course open you up to being compromised if anyone compromises that CA. But, like you said it's a big improvement over nothing.
You don't have to compromise the root. This could still happen if a trusted intermediate CA's private key is compromised, because that CA's certificate was signed by the CA in the chain of trust that ultimately terminates with a trusted root.
Also, how does rfc7469 work with respect to CRLs and OCSP?
1. View pinned certificates/keys?
2. Pin one manually, from the browser?
From what I understand neither is possible, even though this was added to Firefox 1.5 years ago. Which really makes you go Hmm. I'd expect I'm not the only one who wants to pin few certs for sites that I visit frequently.
How can you tell what the backup pin for those websites would be without the owner publishing the HKPK headers? How do you know the max-age of their current pin?
It sound a bit like trying to stuff things into the browser's cache - a road to disaster.
If you don't control the sites, it is not a good idea to pin them "from the browser" as you suggest.
EDIT: Okay, the coffee is flowing and the gears are starting to turn. I guess if I'm going to pin my cert, I should generate a new private key for the backup, and if I'm going to pin the intermediate cert, I should use a different CA. And for maximum protection, do both, and not keep both private keys on the same servers. Does that make sense?
If your "primary" certificate or any of the others in the chain is compromised -- for whatever reason -- you want the ability to immediately switch over to your "backup" certificate without problems or affecting your users.
For instance: http://randywestergren.com/reverse-engineering-the-subway-an...
EDIT: Just to clarify given the comment below (and downvotes...), I'm talking about a different attack scenario. Here's a decent source on some of pinning's weaknesses for your standard MITM scenario: https://www.owasp.org/index.php/Certificate_and_Public_Key_P...
Attacker --> Attacker's Phone --> App --> MITM proxy --> API/Server
So you could use this to pull down real-estate listings from a real-estate app in an easily parsed format (usually JSON). Or write an app that pull down the odds from various sports betting app APIs, detects arbitrage opportunities and automatically places bets using their APIs...
EDIT: Oh and on the plaintext thing, generally no. Most apps will use TLS for app-to-server comms. Pinning in this context means they bundle the cert (or signature) with their app. By the looks of this (http://security.stackexchange.com/questions/29988/what-is-ce...) it's a similar story with chrome: they pre-bundle some signatures. The alternative is to pin on the first interaction, but this leaves you potentially vulnerable if an attacker is listening in on that first interaction. It also raises the question: what happens if the website needs to revoke and re-issue? Wouldn't pre-bundling mean you'd have to wait for the next browser update (and for out of band commms to have occurred between google and the website)?
If you're providing both an app and a server for the app to talk to you, you control both ends of the TLS connection and can pin however you'd like; you're not limited to HPKP and key-continuity. Secure apps have been doing custom pins of TLS keys long before HPKP got rolled out.
The fun begins with report uris, it doesn't seem like there's a way to specify multiple of them.
We deem this acceptable because the proxy or MITM can only be effective if the client machine has already been configured to trust the proxy’s issuing certificate — that is, the client is already under the control of the person who controls the proxy (e.g. the enterprise’s IT administrator). If the client does not trust the private trust anchor, the proxy’s attempt to mediate the connection will fail as it should.
https://www.chromium.org/Home/chromium-security/security-faq...
https://code.google.com/p/chromium/issues/detail?id=561646
I'm personally fine with this. MITM proxies are a valid use case. I do think that all parties should be made aware of it, but that's probably something that has to be fixed via laws (I think some European countries forbid this practice unless it's been made clear that there can be no expectation of privacy on a company-provided device).
[1]: https://wiki.mozilla.org/SecurityEngineering/Public_Key_Pinn...
The whole idea of this security feature is that MITMs can't bypass it. It would be worthless if proxies could bypass it.