SSL Pinning and certificate expiry - ssl

This question relates to the use of SSL Pinning in a client app against a web api and certificate
expiry.
Scenario:
I own example.com and have a subdomain where an api is hosted, as such: api.example.com
I wish to use the api over SSL, so an SSL Certificate is created for the subdomain.
After the certificate has been acquired, I have:
A Public Certificate
A Intermediate Certificate
A Private Key
It's my understanding that I install these certificates on my webserver.
I then wish for my client app to connect to the api. To mitigate against man-in-the-middle style
attacks, I wish to use SSL Pinning, so that the client will only communicate with my api, not
someone spoofing it.
In order to pin in the client app, I have two choices, either pin against the public or intermediate
certificate.
Let's say I implement this.
What happens when the certificate on api.example.com expires?
It's my understanding that the client app would no longer work.
Do I need to regenerate a complete set of public/intermediate/private items again? and then
put a new public or intermediate certificate in the app?
Question:
I would still like the client app to work until the certificate on api.example.com was updated.
Of course, a new certificate can be put in the client app, but things like roll-out take time.
How can I handle this?
I've read that Google updates their certificate every month, but somehow manages to keep the public key the same: How to pin the Public key of a certificate on iOS
If that's possible, then the solution is to simply extract the public key from the server and check it against the locally stored public key...but how do Google do it?
Thanks
Chris

Note: I'm more familiar with browser to server pinning (HTTP Public Key Pinning - HPKP) rather than app to server pinning, but I presume the principal is the same. In HPKP the pinning policy is provided by the server as a HTTP header but understand this is often built into the app rather than read from the HTTP response. So read below answer with all that in mind:
Pinning is usually against the key not the cert and can be a multiple levels. So you've several choices:
Reuse the same key/crt to generate a new cert. Some (rightly in my opinion!) recommend generating a new key each time you renew your cert but this is complicated when you use pinning. So does pinning encourage poor security habits like key reuse?
Have several back up keys in your pinning policy and rotate them around on cert renewal discarding your oldest and adding a new one with plenty of time and updates to never be caught short. Personally I prefer to generate the key at cert renewal time rather than have some backups around which may or may have been compromised so I'm not a particular fan of this either. And how many backups should you have? E.g. If you need to reissue a cert because of compromise around renewal and also mess it up? So 2? 3? 100?
Pin further up. Say the first intermediate or the root CA cert. So any newly issued cert is still trusted (providing it's issued by same cert path) The downside of this is four fold: i) You still leave yourself open to miss-issued certs issued by that pinned cert (not a massive deal IMHO as you've still massively reduced your attack surface but still a concern to some people), ii) you cannot guarantee the client will use that intermediate cert as there are sometimes multiple valid paths. This second one is a much bigger deal. You'd think that providing the intermediate cert would guarantee this would be used but that's not the case (plenty of sha-1 examples of this). iii) There's no guarantee new cert will be issued by same intermediate or root (especially when technologies change like introduction of sha2), so to me this whole option is a non-starter iv) It ties you in to using same cert provider (perhaps not a big deal but I like the freedom to move). Not sure if apps support this feature natively anyway but browsers certainly do.
Renew in advance and do not use the new key until policy cache expires. For example if you have one year certs and a 30 day pinning policy then you can renew after 11 months, add the new key to the policy, then wait 30 days so you can be sure everyone will have picked up new policy or at least the old policy will have expired, then switch keys and certs. Depends on a short policy and potentially wastes a portion of that though (at least 30 days in this example), unless cert provider provides cert in advance starting on day after old policy expires. For an app, if pinning policy is hard coded into it, then this might involve the length of time it takes to push out an update.
Ultimately, because certs do require renewing, I'm not a big fan of pinning. I don't think making something that is subject to periodic renewal, semi-permanent is the right answer. And there are even some talk of pre-loading pinning policies in browsers which just makes me shudder.
Pinning provides assurance that a rogue CA is not issuing certs for your domain but how likely is that really compared to the hassle of pinning? Something like Certificate Transparency - or even report only pinning may be a better answer to that problem even if they don't actually stop that attack.
Finally locally installed roots (e.g. for antivirus scanners or corporate proxies), bypass pinning checks (on the browser at least) which again reduces its effectiveness in my eyes.
So think carefully before using pinning and make sure you understand all the consequences.

The mozilla developer site recommends to pin the certificate of the intermediate CA that signed the server certificate.
"it is recommended to place the pin on the intermediate certificate of the CA that issued the server certificate, to ease certificates renewals and rotations."
For more information on implementing and testing public key pinning you can refer Implementing and Testing HTTP Public Key Pinning (HPKP)

Your application can store multiple certificates in its pin list. The procedure for changing the cert would then be:
Some time before the certificate expires, release a new version of your app with a replacement cert in the pin list, as well as the original cert
when the old certificate expires, replace it on the server - the app should then still work as the new cert will already be in the pin list
Some time after the cert expires, release a new version of your app removing the old cert
Remember your users have to update the app before the old cert expires

Related

Public key pinning vs Certificate Pinning in mobile apps

Scenario :
I have pinned public key pin SHAs of 3 certificates : Root CA , Intermediate CA and Leaf CA in my android application.
What I have understood ( Please correct me if I'm wrong anyway here ) :
Public key pinning is used so that we can check if the public key of the cert that our server is issuing is changed or not. source
A certificate is valid if its public key SHA is the one which we have "pinned" in our application. To check the public key , first it will decrypt the signature using the public key and makes sure that the same public key is in the data of that signature also.
When the Leaf cert has expired but is corresponding to the valid "pinned" public key SHA, the chain of certificates is checked to see if they are valid and if one of them is valid , the certificate is accepted and the connection is established.
When the Leaf cert I got is having an invalid public key but is not expired , then that means I got a wrong certificate from someone which may be an attacker.
Question :
Does public key pinning in any way help in security , if an attacker compromises a client and installs his own trusted CA and then does an MITM on the client to intercept all communication by presenting his own forged certificate signed by the CA he has installed on the client device.
How does direct certificate pinning VS public key pinning make a difference here in any way ?
What is the implication of using a self signed certificate in the above questions.
Please help me understand this with as much detail as possible...
When the Leaf cert has expired but is corresponding to the valid "pinned" public key SHA, the chain of certificates is checked to see if they are valid and if one of them is valid , the certificate is accepted and the connection is established.
No. An expired certificate is not accepted. Pinning does not override that basic principal of TLS but enhances it to reduce the number of certificates accepted.
Does public key pinning in any way help in security , if an attacker compromises a client and installs his own trusted CA and then does an MITM on the client to intercept all communication by presenting his own forged certificate signed by the CA he has installed on the client device.
For browsers, manually installed trusted CAs are exempt from pinning requirements. To me this is a fundamental flaw in pinning. Though to be honest once you have access to install root certs on a machine it’s pretty much game over. Anyway, this exception is necessary to allow Virus scanners, Corporate proxies and other intercepting proxies to work - otherwise any pinned site could not be accessed when behind one of these proxies though it does weaken HPKP (HTTP Public Key Pining) in my mind.
For apps (your use case) pinning can be useful to prevent MITM attacks.
How does direct certificate pinning VS public key pinning make a difference here in any way ?
Don’t understand? When you pin a direct certificate you basically pin the public key of that certificate (well actually the SHA of the private key that cert is linked too).
This means you can reissue the certificate from same private key (bad practice in IMHO) and not have to update pins.
You can also pin from the intermediate or even root public key. This means you can get your CA to reissue a cert and again not have to update the pin. That of course ties you into that CA but at least doesn’t allow some random CA to issue a cert for your site.
What is the implication of using a self-signed certificate in the above questions.
For browsers, pinning basically can’t be used with a self-signed cert. because either it’s not recognised by browser (so pining won’t work) or its is by trusting by manually installing the issuer - at which point pinning is ignored as per point above.
For apps (again your use case), I understand self-signed certificates can be pinned. Though it depends on which HTTP library you use and how that can be configured.
One of the downsides of pinning the certificate itself (which might be the only way to do it, if it's a single leak self-signed certificate), is that reissuing the certificate will invalidate the old pins (unless you reuse the same private key but this may not be possible if the re-issue reason is due to key compromise). So if you app makes an HTTP call home to check if there is a new version or such like, then that call might fail if certificate is re-issued and new version of the app has not been downloaded yet.
Nearly browsers have deprecated HPKP as it was massively high risk compared to the benefits and there were numerous cases of breakages due to pinning. See Wikipedia: https://en.m.wikipedia.org/wiki/HTTP_Public_Key_Pinning. Monitoring for mis-issued certificates through Certificate Transparency is seen as a safer option.
Pinning still seems somewhat popular in mobile app space because you have greater control over an app and can re-release a new version in case of issues. But it is still complicated and risky.
My Answer Context
Scenario :
I have pinned public key pin SHAs of 3 certificates : Root CA , Intermediate CA and Leaf CA in my android application.
My answer will be in the context of pinning in a mobile app. anyway the new browsers don't support pinning any-more.
Pinning and Security
Does public key pinning in any way help in security
It helps a lot, because your mobile app only communicates with a server that presents the certificate with a matching pin. For example, if you do public key pinning and you rotate the certificates in your backend while signing it with a different private/public key pair then your mobile app will refuse to connect to your own server until you release a new version of the mobile app with the new pins.
MitM attack and Pinning
if an attacker compromises a client and installs his own trusted CA and then does an MITM on the client to intercept all communication by presenting his own forged certificate signed by the CA he has installed on the client device.
When you are pinning the connection the attacker will not succeed, because this is for what pinning was designed for, to protect against manipulation of the certificates trust store on the device in order to carry on a MitM attack. From Android API 24 user provided certificates are not trusted by default, unless the developer opts-in to trust on them via the network security config file:
<base-config cleartextTrafficPermitted="false">
<trust-anchors>
<!-- THE DEFAULT BEHAVIOUR -->
<certificates src="system" />
<!-- DEVELOPER ENABLES TRUST IN USER PROVIDED CERTIFICATES -->
<certificates src="user" />
</trust-anchors>
</base-config>
You can read the article I wrote to see pinning in action and not allowing for a MitM attack to succeed:
Securing HTTPS with Certificate Pinning:
In order to demonstrate how to use certificate pinning for protecting the https traffic between your mobile app and your API server, we will use the same Currency Converter Demo mobile app that I used in the previous article.
In this article we will learn what certificate pinning is, when to use it, how to implement it in an Android app, and how it can prevent a MitM attack.
In the article I go into detail how to implement pinning, but nowadays I recommend instead the use of the Mobile Certificate Pinning Generator online tool, that will generate the correct network security config file to add to your Android app. For more details on how to use this tool I recommend you to read the section Preventing MitM Attacks in this answer I gave to another question where you will learn how to implement static certificate pinning and how to bypass it:
The easiest and quick way you can go about implementing static certificate pinning in a mobile app is by using the [Mobile Certificate Pinning Generator](Mobile Certificate Pinning Generator) that accepts a list of domains you want to pin against and generates for you the correct certificate pinning configurations to use on Android and iOS.
Give it a list of domains to pin:
And the tool generates for you the Android configuration:
The tool even as instructions how to go about adding the configurations to your mobile app, that you can find below the certificate pinning configuration box. They also provide an hands on example Pin Test App for Android and for iOS that are a step by step tutorial.
This approach will not require a release of a new mobile app each time the certificate is renewed with the same private/public key pair.
Certificate Pinning vs Public Key Pinning
How does direct certificate pinning VS public key pinning make a difference here in any way ?
When using certificate pinning a new mobile app needs to be released and users forced to update each time the server certificate is rotated, while with public key pinning no need for this unless the private/public key pair used to sign the certificate changes. For example, if your server uses LetsEncrypt for the certificates you don't need to release a new mobile app version each time they are renewed.
Self Signed Certificates
What is the implication of using a self signed certificate in the above questions.
You will need to opt-in via the network security config file for the Android OS to trust in user provided certificates and instruct the user to add it to his mobile device. This will make an attacker life easier if pinning is not being used. I would recommend you to stay away of using self signed certificates.

What is the difference between SSL pinning (embedded in host) and normal certificates (presented by server)

I'm not quite understanding the necessity of certificate pinning in SSL connection establishment (to avoid Man in the Middle attacks).
SSL cert pinning requires embedding original server certificate in the host to verify with the one presented by server. what is the difference between the server certificate embedded in the host and the one presented by server to be validated by client?
What is that I am missing here?
what is the difference between the server certificate embedded in the host and the one presented by server to be validated by client?
There should be none and that's exactly the point of certificate pinning.
Without certificate pinning an application commonly accepts any certificate which matches the requested hostname and is issued by a locally trusted CA (certificate authority). Given that there are usually more than 100 CA in the local trust store it is sufficient that one of these got successfully attacked as in the case of DigiNotar in 2011. Thus it makes sense to limit the certificate you accept to a specific one, i.e. pinning.
Besides the certificate pinning by comparing the certificate received with a locally stored certificate there are other ways of pinning: for example one might just check against a fingerprint (hash) and not the full certificate. In case the certificate can expire it might be more useful to check only the public key and not the whole certificate because the public key is often kept on certificate renewal. Or one might pin to a specific CA which one considers trusted to issue certificates for this domain.
Note that to understand pinning you might need to understand how the authentication of the server works. One part of this is that the server certificate is validated (hostname, expiration, trust chain ...). But this is not enough since the certificate itself is public, i.e. everybody can get it and could send it inside the TLS handshake. Thus the other major part of the authentication is that the server proves that it is the owner of the certificate. This is done by signing some data using the private key matching the certificate. Since only the owner of the certificate should have the private key this proves ownership. Because of this anybody could embed the servers certificate for pinning but only the server itself can prove ownership of the certificate.
What is SSL pinning
Applications are configured to trust a select few certificates or certificate authority (CA), instead of the default behaviour: to trust all CAs that are pre-configured on the device/ machine. SSL pinning is not required.
Why use SSL Pinning (Why not to)
In many cases, the certificate returned by a server could be tampered as long as any Root (or intermediate root) CA was compromised (happens very rarely). Threat actors could use this compromised CA to generate a certificate for your website, and show visitors their website instead. This is bad. SSL pinning was designed to prevent this in some cases, but there are better ways (IMHO).
Having said that, I don' t know any website which uses SSL pinning so SSL pinning seems primarily discussed for mobile apps. It seems like SSL pinning only works when you can trust the source of the application (e.g. App Store, Play Store) Why? Because if you have to visit a website to get the cert, by then its too late (you might have already used a dodgy cert and accessed the fake website or was MITM'd). Therefore, it seems like the benefits Steffen mentioned are not so compelling, especially when there are better solutions already:
Better solution
I'm not sure if any-CA-compromise is a threat vector, even for banks. Instead, banks and other security conscious organisations will pick their CA wisely, and also configure a CAA record.
By using a CAA DNS record, they can restrict clients (e.g. browsers, mobile apps) to trust only certain certificates when accessing their specific website.
They pick the CA and create a cert only from this CA
They will have a backup plan for if a CA is compromised. Don't want to go into that here, but the backup plan for CAA records is IMHO much better than that of SSL pinning.
For example, Monzo.com (I used whatsmydns to find this) has a CAA record which restricts certificates to only 4 CAs (digicert, amazon, comodoca, buypass):
0 iodef "mailto:security#monzo.com"
0 issue "amazon.com"
0 issue "buypass.com"
0 issue "comodoca.com"
0 issue "digicert.com"
0 issue "letsencrypt.org"
0 issuewild "amazon.com"
0 issuewild "comodoca.com"
0 issuewild "digicert.com"
0 issuewild "letsencrypt.org"
These are popular CAs which people trust, we hope they don't let us down. If they do, the whole internet would be a free for all. The only way to prevent this is to be your own CA/ use self-signed certificates.
Summary
I don't see how SSL pinning will become ubiquitous, especially since it adds more overhead (maintenance regarding ssl expiry, or trusting one CA anyway - SPoF, or emulating what a CAA record does but with additional code/ maintenance burden). It also only supports your pre-installed applications, not websites.

How to prevent clients from retrieving my server's certificate

I have a secure API for mobile clients. I would like to perform certificate pinning and I achieved it. The problem is if run the command openssl s_client -connect xxx.xxxxxxxxx.com:443 then I can see my certificate. I believe whoever have the URL, they can also see the certificate and they connect to my APIs.
How I can prevent access to my certificate, so that only my mobile can access but not public?
Anyone who connects to an SSL / TLS server can view the server's certificate because is public. This is normal behavior.
But that does not mean it can connect to your API. Normally an authentication mechanism is added where the one that connects has to present credentials, for example user/password.
With SSL/TLS is also possible to require a client certificate to stablish the secure channel. This is called two ways authentication. But it is not usually used from mobile devices because of the difficulty of distributing the electronic certificates
I suggest adding authentication to your api if you have not already done so
Public key cryptography works by having one part (the certificate) freely available publicly. The corresponding private key is needed to decrypt and it should be kept secret.
Therefore there is no problem with openssl having access to the certificate - that's exactly how it should work! A web browser will also be able to grab the certificate for a website it had not been too.
Pinning adds a further layer of security that this but limiting the certificates that a website can use to those certificates that are "pinned" to the site. As discussed without the private key, someone can decrypt the traffic. However there are certain, reasonably sophisticated attacks that involve intercepting traffic and replacing the certificate with another using their own certificate/private key combination so they can read the traffic. Pinning prevents this by explicitly stating which certificate(s) should be allowed in this site.
Pinning does not stop the need for the key to be public, nor does it limit connections from your mobile app only - there are other solutions for that but pinning is not it. It merely is used to address one type of attack against the server.
Pinning is an advanced topic and it is easy to accidentally cut off access to your site by pinning a certificate and then not updating the pins when renewing, or otherwise changing, the certificate. Due to that risk, you should ensure you have a much greater understanding of how all this works before implementing pinning. At the moment you seem to have a misunderstanding of the basics so would advise against advanced topics like pinning.

SSL signed certificates for internal use

I have a distributed application consisting of many components that communicate over TCP (for examle JMS) and HTTP. All components run on internal hardware, with internal IP addresses, and are not accessible to the public.
I want to make the communication secure using SSL. Does it make sense to purchase signed certificates from a well-known certificate authority? Or should I just use self-signed certs?
My understanding of the advantage of trusted certs is that the authority is an entity that can be trusted by the general public - but that is only an issue when the general public needs to be sure that the entity at a particular domain is who they say they are.
Therefore, in my case, where the same organization is responsible for the components at both ends of the communication, and everything in between, a publicly trusted authority would be pointless. In other words, if I generate and sign a certificate for my own server, I know that it's trustworthy. And no one from outside the organization will ever be asked to trust this certificate. That is my reasoning - am I correct, or is there some potential advantage to using certs from a known authority?
There is no need for you to use an external public CA for a closed community project. In many larger organisations they operate an internal PKI to issue certs for internal projects like this. An advantage of using a PKI is that you can setup a trust relationship between the various components based on a single securely distributed root certificate / trust anchor.
However, if the project allowed internal users to connect securely to an internal service via their web browser you may want to consider using a public CA issued cert. The alternative is to make sure that every browser that may need to connect to your service trusted your root cert; this is to prevent browser warning messages.
I'd say it's reasonably safe, unless you think a ninja infiltrator is going to swap your server on you.
The 3rd party is there to make it harder to just 'up & generate' a new cert. Someone could re-create a self-signed cert on a new machine with the same details, it wouldn't be the same cert, you'd have to add an exception for it too, but your users probably wouldn't know the difference.
As long as your system is running inside your group and there are no plans to expand it (and plans do change, so keep that in mind), it is just fine to setup your own simple PKI infrastructure.
If you do end up expanding beyond your organization, all you need to do is distribute your root certificate to the parties you will be communicating. This gives actually a fine grained control to your partners how much trust they want to put in you vs the public CA infrastructure.

What SSL certificate do I need?

I'm developing software which will be deployed using clickonce (on the website foo.com), and which will then connect to my server using WCF with an encrypted transport
So I need an SSL certificate which will :
Identify my foo.com website has really being my website
Identify the exe I deploy using clickonce as being genuine
Identify my application server has really being my application server.
I also want my SSL certificate to be signed by an authority known to the public (ie, firefox or windows won't ask the user to install the authority's certificate first !)
What SSL certificate would you buy?
I've browsed the Verisign website, the "Secure Site EV" certificate costs 1150€ a year (the "Pro" version seems useful only for compatibility with older browsers)
It sounds like you're looking for two different types of certificates:
1 - SSL Certificate - for authentication of your website/application server.
2 - Code Signing Certificate - for integrity/authentication of the exe you deliver.
Typically those are two different certificates, with two different certificate profiles. At the very least, you need one certificate with two different key usages or extended key usages.
A few thoughts in no specific order:
Check your targeted browsers, they should each have a set of preconfigured root certificates - those are the most widely recognized public certificate sources. I'd probably check both Firefox and IE. Certificate vendors known to me as big names are - Versign, GeoTrust, RSA, Thawte, Entrust. But there's also GoDaddy and many others. Anything that comes in the delivered browser as a Trusted Root Certificate, will allow you to connect to your users without additional greif.
I suggest Googling for both "code signing certificate" and "SSL certificate".
How you configure your site will determine whether or not your website is validated or your authentication server is validated. If the certificate is stored on the apps server, then your user is getting SSL encryption all the way to the server. But many sites put the SSL certificate a little farther forward - like on a firewall, and then stage a collection of apps servers behind it. I don't see a security flaw in that, so long as the networking is carefully configured. To the outside users, both configurations will look the same - they'll get the lock on their browsers and a certificate that tells them that www.foo.com is offering it's credentials.
I'm seeing pretty great deals for SSL Certificates:
- GoDaddy - $12.99
- Register.com - $14.99
But they aren't necessarily code signing certifiates. For example, while GoDaddy's SSL Cert is $12.99, their code signing certs are $199.99! That's part of many certificate vendors business models - lure you in with cheap SSL Certs, and make you pay for code signing. A case could be made that code signing certificates are relatively higher liability. But also... they have to subsidize the cheap SSL certs somehow.
Theoretically, it should be possible to make a certificate that does both code signing and SSL, but I'm not sure you want that. If something should happen, it would be nice to be able to isolate the two functions. Also, I'm pretty sure you'd have to call the certificate vendors and ask if they did this, and if they don't, having them do it will likely jack up the price quite high.
As far as vendor, things to consider:
The technology is pretty much all the same. These days, aim for a minimum of 128 bit keys, I'd probably bump it up to 256, but I'm paranoid.
Beyond browser acceptabiliy, the only reason to pay more would be name recognition. Among the paranoid security wonks, I'd expect RSA, Thawte, Verisign and GeoTrust to have very good reputations. Probably EnTrust, too. This probably only matters if you are dealing with a security focused product. I think your average user will not be so aware.
From a security geek perspective - you're only as safe as the security of your Root CA (Certificate Authority). For the truly paranoid, the thing to do would be to dig into the background material of how the company hosts its root and issuing CAs, how are they physically securited? network security? personnel access control? Also - do they have public CRLs (Certificate Revocation Lists), how do you get a cert revoked? Do they offer OCSP (Online Certificate Status Protocol)? How do they check out certificate requestors to be sure they are giving the right cert to the right person? ... All this stuff really matters if you are offering something that must be highly secure. Things like medical records, financial managment applications, tax information, etc should be highly protected. Most web apps aren't so high risk and probably don't require this degree of scrutiny.
On that last bullet - if you dig into the Verisigns of the world - the very expensive certs - you're likely to see the value. They have a massive infrastructure and take the security of their CAs very seriously. I'm not so sure about the super-cheap hosting services. That said, if your risk is low, US$300 for an SSL Cert doesn't make much sense compared to US$12.99!!
So for web site / application servers you need an SSL certificate. You do not need an EV certificate. I've used ones from QuickSSL for this, as unlike some of the other cheap certificate providers they don't require the installation of an intermediate certificate on the server - that's a no-one for me.
For signing applications that's a different type of certificate altogether (kind of, it's still an X509 certificate, but the one you use for your web site is not one you can use to sign an application). You need an authenticode signing certificate from the likes of Verisign or Globalsign. These are a magnitude more expensive than a plain old SSL certificate and require you to be an incorporated company and produce those documents.