Certificate Pinning - Refresh Pinned Certificate Mechanism - ssl

I am working on a client architecture where we plan to pin our clients against our servers. My server leaf certificates can change throughout our product lifecycle, which is why we would need a refresh mechanism to support our older released clients with embedded certs.
Here are two approaches I have planned:
Plan on using a set of backup public/private key pair, private being kept with us in a HSM. public key is embedded in client.
approach 1 :
On leaf expiry
Issue a leaf certificate pinset which could be downloaded on public internet.
On Client, download this leaf pinset with pinned root certificate.
if download successful, use this new leaf pinset and pin it for all subsequent HTTP calls.
If Leaf + Root expired
If for some reason, root also expired, or root was changed to a new provider.
On client, download leaf pinset with root certificate -> Failure because root expired.
Refresh root, download new root pinset signed by backup private key. This is an unpinned call.
After downloading verify signature using client embedded backup public key.
If successful, use this root pinset, pin it to download leaf.
Use downloaded leaf and pin it for subsequent http calls.
approach 2 :
Make above approach more streamlined and avoid root pinset altogether.
Sign leaf pinset with backup private key and keep pinset which could be downloaded in public internet.
while refresh downloading it on client, download using unpinned call.
After download successful, verify using backup pub key and use it for all http calls.
My question with above 2 approaches is, does approach 2 leave any room for security exploit, overall I feel like having to deal with less number of artefacts on client is the way to go, but I do not want to compromise security in anyway.

Related

Can the ACME version 2 protocol be used to distribute SSL certificates (and keys) or only send new certificates?

ACME is used by some certificate authorities to process automated signing of certificate requests and issue resulting certificates.
An increasing number of applications (Eg Traefik) now have builtin support for ACME. This is very useful for managing certificate cycling without tracking where every deployed application stores its certificates.
However "free" certificates from letsencrypt and similar certificate authorities are not always appropriate for all applications. Such examples include some software requiring the exact same certificate being installed in multiple layers of an application's edge gateway (yes this does happen).
I'm wondering if, hypothetically, ACME v2 can be used to redistribute existing SSL certificates and associated private keys. Or is it only capable if responding to CSRs where the private key is never transferred between ACME server and client?
ACME is defined by RFC8555 currently.
There is nothing that prevents other CA to use it, besides Let's Encrypt, and indeed there are other CAs existing using it, and others adding it to their existing API.
The key associated to a certificate should never travel. The CA shouldn't know it. As such, there are no operations in ACME that would allow a CA to send the key, besides the certificate, and that is a good thing.
Retrieving a certificate is a core operation, see "7.4.2. Downloading the Certificate". It could happen separately/outside of a previous certificate request. The problem being then: how does the client know which URL to use to download a specific certificate (an information that it receives when doing the normal authorization/validation steps)?
There are other protocols to manage communication of cryptographic materials such as X509 certificates.
Still in ACME, you might be interested in RFC 8739 "Support for Short-Term, Automatically Renewed (STAR) Certificates in the Automated Certificate Management Environment (ACME)" which allows the CA to pre-generate certificates.
And the related RFC 9115 "An Automatic Certificate Management Environment (ACME) Profile for Generating Delegated Certificates",
Outside of ACME, but very similar, you have RFC 8894 "Simple Certificate Enrolment Protocol" (but still no transmission of private key).
But you are not clearly describing the problem you have around "redistribute existing SSL(sic) certificates and associated private keys". What else do you really need besides an URL that gives back that data if it is that you want to send back to client (but again: making the private key travel is, in general, a bad idea)? Is authenticating the client the problem? Discoverability of the URL to use to download a specific certificate/key?

DDS Security certificate storage

I am currently developing using DDS with the security plugins enable.
When the application starts, it looks for the path to the CA certificate, Local certificate and private key and load them in memory for future usage.
Certificates containing the public keys are not sensitive as they are usually sent in clear and checked using the CA certificate. So an attacker has no need to get access to it. Is that correct?
However, on a Ubuntu filesystem, how can I protect the private key? The only way I see is to put the key as Read-Only only for a specific user that will run the application. But because of privilege escalation, this seems insecure.
Are there secure way to secure private keys on a filesystem ?
About the permissions_ca and Governance/Permissions documents, if those are updated by an attacker (which would create its own CA and sign new Governance/Permissions documents), then, can an application could have more permissions? Meaning that those documents should be secured on the filesystem?
Most of your questions are not specific to DDS Security, but are about general Public Key Infrastructure (PKI) mechanisms as leveraged by DDS Security.
Certificates containing the public keys are not sensitive as they are
usually sent in clear and checked using the CA certificate. So an
attacker has no need to get access to it. Is that correct?
Yes, that is correct. The built-in plugins as defined by the DDS Security specification use a PKI. The public key certificate does normally not contain any confidential information.
However, on a Ubuntu filesystem, how can I protect the private key?
Using "traditional" Unix permissions to allow only the owner of the file to access it is common practice. For example, SSH on Ubuntu by default stores private keys that way, in ~/.ssh. Additionally, the specification allows for encryption of the private key using a passphrase. That too is common practice.
Whether this is good enough for your scenario depends on your system's requirements. It is possible to integrate with existing, stronger key storage solutions like Windows certificate stores or macOS keychains by implementing customize security plugins. The pluggable architecture as defined in the spec was intended to allow for that, but the actual availability of such solutions depends on the DDS product that you are using.
About the permissions_ca and Governance/Permissions documents, if
those are updated by an attacker (which would create its own CA and
sign new Governance/Permissions documents), then, can an application
could have more permissions?
Both the Governance and Permissions documents have to be signed by a signing authority. Tampering with those files would break the signature verification and therefore would be detected by other Participants in the Domain.
All participants in the secured DDS Domain need to trust the same signing authority to make this mechanism work. For an attacker to successfully modify a Governance or Permissions document, it would have to have access to the private keys of the signing authority. Again, this is a common technique used in public key infrastructures similar to the public key certificate signing.
In spite of the tamper protection, it still makes sense to protect those files. The actual result of tampering or deletion of those files would be a denial of service, which is harmful as well.

SSL Pinning and certificate expiry

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

Packaging and installing x509 certificate on client with clickonce app

I just got started programming WCF services and got my first service up and running for a local police department. They will be using this to lookup plates for overnight parking violations. It's running message security and an x509 certificate for encryption.
Is there a way to package the certificate with the installation or some how have the service create it and download it to the client depending on the authentication I am using?
Right now I am going to be manually installing it on each tough book but would like to automate the process more.
Certificate distribution is a standard task for most enterprise IT departments, applications modifying CA roots is somewhat taboo.
If you are talking about pushing the public key of a server certificate to each client, look at Add a trusted root certification authority to a Group Policy object. If you are talking about creating a client certificate for use of mutual TLS authentication, look at Deploy User Certificates.
If instead you are talking about an ephemeral certificate some other certificate which is only accessed by your application from code, you can add it as an Embedded Resource in your assembly and use it via the X509Certificate2(byte[]) constructor.
I would caution you against putting a private key in your application resources, since any user of the application can do whatever they wish with it. PKI is designed such that Private Keys do not need to be shared. Regardless, Jeff Valore shows a method to do so, which I have reproduced below:
var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("MyCert.cer");
var bytes = new byte[stream.Length];
stream.Read(bytes, 0, bytes.Length);
var cert = new X509Certificate2(bytes, "certPassword");

Some understanding gaps about Public Key Infrastructure workflow

Recently, I have stumbled upon the basic understanding about PKI work-in-action process. I have looked at major articles about the principles but still I feel quite dumb to understand this process. I understand that PKI is not for „My blog„ but for the sake of simplicity lets walk through simple example “My e-Shop” (for example apache and php) and simple concepts. I wrote some statements that might be vague or even wrong but that’s what I want to know about the process of PKI:
“My e-Shop” as a company needs to be “certified” at some third party CA. That means I need to buy some kind of 1 year membership at that CA, and then, they will register “My e-Shop” at their systems and issue me some stuff like a certificate and a pair of unique public and private keys. Will I get some certificate-file?
Issued certificate is filled with my info and public key and stored in some file at my webserver. The certificate verifies that “My e-shop” is not a bureau of thieves.
Every time users access “My e-shop” through “https” their browsers “silently” checks the presented certificate of “My e-shop” with the one that is registered at CA.
What about users? Do their browsers generate local public+private keys when entering “My e-shop” via https?
When some user enters “My e-shop” via https the following happens: “My e-shop” (webserver) gets the public key (PK1) of the user. The server silently presents the certificate of “My e-shop” to the user, so the users gets the public key (PK2) of “My e-shop”. After some silent checking the browser of the user validates presented certiticate and a secure pipe is established.
When a user sends a request via secure pipe the requests is encrypted with public key of “My e-shop”. Then, web server decrypts the request with its private key. Then, web server sends encrypted response with a public key of the user. At the end, the browser of the user decrypts the response with his private key.
Taking these question by question:
(1) “My e-Shop” as a company needs to be
“certified” at some third party CA.
That means I need to buy some kind of
1 year membership at that CA, and
then, they will register “My e-Shop”
at their systems and issue me some
stuff like a certificate and a pair
of unique public and private keys.
Will I get some certificate-file?
Yes. Also, this varies from CA to CA - some CAs, a 1 year membership and a valid credit card is enough (not to hard to get, even if you happen to be a band of theives), some CAs require a certain amount of paperwork to verify that you are who you say you are. A CA is only as good as it's customer-verification process, so generally the more onerous the process, the better (and more expensive) the CA.
When you have paid your money and done your paperwork, then you and the CA will generate at least 2 things:
A public/private key pair. Often this is generated by YOU, not by the CA. The quality of how you have generated and stored your key pair is also a factor in determining how much another entity can trust your website. Generally, for identification certificates (like SSL server certs) it's a good idea to have the customer (My e-Shop) generate the key.
You'll send a certificate request in a standard format (example: PKCS10) to the CA. It will include a bunch of information about My e-Shop and the public key.
The CA company will check your paperwork and make sure you are you. Then it will use it's CA to digitally sign a certificate for you. That certificate has a bunch of the information you just provided, some extra info that the CA provider sets for you, your public key and the digital signature generated by cryptographically binding all the aforementioned data with the CA's private key.
You get back one of two things:
just the certificate (if you generated your own key pair)
the certificate and the key pair - if the CA generated the key pair for you
(2) Issued certificate is filled with my
info and public key and stored in
some file at my webserver. The
certificate verifies that “My
e-shop” is not a bureau of thieves.
yes... sort of. Your webserver will need both the signed certificate AND the key pair. The key pair is used as part of the SSL handshake to the end user, and that exchange proves that you are in posession of the key pair, and not some band of theives that got their hands on the certificate. This is why you want to protect the key pair.
(3) Every time users access “My e-shop”
through “https” their browsers
“silently” checks the presented
certificate of “My e-shop” with the
one that is registered at CA.
For some definition of "silent". A baseline browser checks that the certificate:
- is currently valid
- is signed by a CA that the browser trusts (or it either denies access or gives you an annoying popup)
Browser add ons will go farther and do things like full path checking (all the way to the self signed root) and certificate status checking. The higher the risk of the info being shared over the pipe, the more checking needs to happen.
(4) When some user enters “My e-shop”
via https the following happens: “My
e-shop” (webserver) gets the public
key (PK1) of the user. The server
silently presents the certificate of
“My e-shop” to the user, so the
users gets the public key (PK2) of
“My e-shop”. After some silent
checking the browser of the user
validates presented certiticate and
a secure pipe is established.
What about users? Do their browsers generate local public+private keys when entering “My e-shop” via https?
OK - stuff is going off the rails here.
For details, check the SSL protocol - the handshake section will give you the hard facts.
The browser and the webserver do pass back and forth information that lets them create a session encryption key. The browser does generate some starting material used to set up the session, but it is not "the public key of the user (PK1)". The user does not need to have PKI credentials UNLESS the server has been configured for client authentication. In a regular, run of the mill My e-Shop, the server has a PKI credential, the browser is generating some key material on the fly for just that one session. The server has absolutely no idea who the browser user is, SSL-wise - all of the user identification comes from a password or something else at the application level.
NOTE: This is for a regular commercial transaction. The higher the risk, the greater the protection. High risk transactions frequently require client authentication.
(5) When a user sends a request via
secure pipe the requests is
encrypted with public key of “My
e-shop”. Then, web server decrypts
the request with its private key.
Then, web server sends encrypted
response with a public key of the
user. At the end, the browser of the
user decrypts the response with his
private key.
Not quite. This is the weeds - a developer of a web application is relatively abstracted from all of this. But - the session content is not encrypted with asymmetric keys - that would be excruciatingly CPU intensive. The PKI of the server and the on-the-fly browser generated handshake data are used to exchange the session encryption key. Part of this is that the client selects and sends a secret key encrypted in the server's public key. Since only the server has the private key, only the server can decrypt the data sent by the client.
This secret key is symmetric (exactly which algorithm is also part of the handshake) and is used for the remainder of the session.
Your steps are incorrect on a couple of different levels. Let me restate them, hopefully in a clear manner.
Your site needs to have an SSL certificate from a trusted third-party CA (Verisign, etc.). You will need to purchase it from them. You will generate the public/private key pair, provide them with your public key (it is part of the certificate request) and they will generate the certificate.
The certificate contains the domain name of your site, your public key, and some other additional information. It does not verify anything, particularly not that your site isn't "a bureau of thieves". All it typically certifies is that you own the domain name for which you are requesting a certificate. It does not mean that your site is trustworthy by any means.
When a user accesses your site via HTTPS, your server will send the certificate down to the client's browser. At no time does the client communicate with the CA to validate your certificate.
3.1. Typically, end users (clients, customers) would not need their own certificates and private keys. This is called mutually-authenticated SSL, and involves both parties (your customers and your site) having a certificate. This is rarely (if ever) used in e-commerce sites.
When a user accesses your site via HTTPS, your server sends down the certificate to the client browser. The client will use this to perform an SSL Handshake. This handshake between the browser and your site is what establishes the secure tunnel. The specifics of the handshake protocol are more technical than you need.
When a request is sent to the server over the SSL tunnel, the server handles it the same way it would any other request. The only difference is that the communication between your customers and your server is encrypted. Your webserver will likely handle the decryption of the data from the request and present it to your webserver for processing. Likewise, the response data is returned back to the client in an encrypted form via the SSL Tunnel.
Better?
Regarding point 3:
As far as I know this is not completely correct. Since there is not really a kind of established live testing infrastructure (in comparison to services like DNS), the web server will send the complete chain of certificates to the browser.
On the other hand the browser or operating system is delivered with a set of trusted root certificates (which need to be updated sometimes, windows update, new browser releases, etc.)
And yes the browser will be supposed to generate an "untrusted" key pair, since under normal circumstances a standard user will not generate his or her own certificate.
Regarding point 5:
Also this is not completely the truth. Computation of asynchronous encryption requires a great amount of time. So the RSA algorithm is just used to exchange keys for faster synchronous encryption standards (i.e. AES, 3TES).