-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
badCertificateCallback is called with issuer certificate instead of leaf certificate for LetsEncrypt published certificate #39425
Comments
I also realized that flutter doesn't respect the platform trusted CA store (checked with android, added a Charles proxy cert). It bundles the app with its own trusted root store (at least that is what I assume). If that is the case then do I need to pin the SSL certificate or Public Key of LetsEncrypt (which is already trusted) to prevent Men in the middle attack? |
@mit-mit Could you answer the query in the comment? If I can go ahead with my hypothesis then I can publish my app. |
I hit this also. I dug into the code that calls badCertificateCallback. The dartlang code calls OpenSSL to perform the TSL connection. When OpenSSL cannot verify a certificate, it returns the certificate to dartlang, which passes it to the badCertificateCallback. This means that dartlang only sees the bad certificate, not the whole chain provided by the server. The fix will be non-trivial. |
I can confirm that this happens for all kinds of CAs, not just LetsCrypt. If the default behaviour of OpenSSL is to return the unverified certificate, and not the whole keychain then how does iOS does it in AFNetworking. The flow in iOS is pretty similar to this. We disable trusting of certificates, the system calls badCertificateCallback and we extract the public key. |
Is there any response for this issues. This seems very serious issues. Why would the certificate provided with only root CA instead of whole chain is not provided with parent,leaf or intermediated. Can we suspect that there is some configuration issues with LetsEncrypt ? |
@SahilPatel16 has confirmed that it is an issue with all CAs not just LetsEncrypt |
As Mentioned here: https://developer.android.com/training/articles/security-ssl#MissingCa The third case of SSLHandshakeException occurs due to a missing intermediate CA. Most public CAs don't sign server certificates directly. Instead, they use their main CA certificate, referred to as the root CA, to sign intermediate CAs. They do this so the root CA can be stored offline to reduce risk of compromise. However, operating systems like Android typically trust only root CAs directly, which leaves a short gap of trust between the server certificate—signed by the intermediate CA—and the certificate verifier, which knows the root CA. To solve this, the server doesn't send the client only it's certificate during the SSL handshake, but a chain of certificates from the server CA through any intermediates necessary to reach a trusted root CA. There are two approaches to solve this issue: Configure the server to include the intermediate CA in the server chain. Most CAs provide documentation on how to do this for all common web servers. This is the only approach if you need the site to work with default Android browsers at least through Android 4.2. Or, treat the intermediate CA like any other unknown CA, and create a TrustManager to trust it directly, as done in the previous two sections. I think adding these three things in the .conf file (Apache 2.4.8) file will solve the issues. |
@daadu you found any workaround? Having same issue, it is returning the intermediate certificate |
badCertificateCallback should not be used to trust root or intermediate CAs. Use setTrustedCertificates for that (although it is broken #35462). The point of badCertificateCallback is to facilitate certificate pinning. The purpose of certificate pinning is to avoid trusting the CA ecosystem or the device's list of trusted CAs. Until badCertificateCallback is changed to pass the leaf certificate, it remains useless for certificate pinning. |
@mleonhard Anyways, I am pinning public key of Also this article (I have quoted below) suggests that flutter relies on its own trusted CA bundle (embedded within app) and does not rely on platform's trusted CA (so say in Android, user importing custom CA would not cause MITM on our app)
If what the article says is true, that in a way setting Please point me if I am wrong, I am assuming for SSL cert signed by reputed CA, flutter does the "pinning" for you to prevent MINTM attack. (Although, as the article suggests it can be bypassed too! By modifying the |
@daadu @mleonhard only way I found to retrieve the correct certificate was using HttpClientResponse object
Here you can access:
Etc and it has the correct certificate, instead of CA certificate only. I somehow made this to be compatible with "http" by returning response like this:
I would prefer to do the pinning normally at badCertificateCallback, but until it is fixed, this was the only way I found to perform certificate pinning, at response level |
@mleonhard Any update on the badCertificateCallback-fix? You mentioned that it is non-trivial... |
Any update about this? |
Any progress on this? Yesterday Let's Encrypt root certificate expired and none of my apps can connect to the servers. Will this issue fix this problem as well? |
The same problem occured to me too today, as let's encrypt root certificate changed, the solution I have found is download the isrgrootx1.pem from https://letsencrypt.org/certificates/ And then read or provide it's path to Security context.defaultContext or your own context . I have tried this on my flutter app and worked fine! I don't know exactly what might the drawbacks can be here @xclud |
Any updates? |
any news on this? Is there a way to successfully implement ssl public key pinning or at least cert pinning? |
Hello ! |
@brianquinlan – anything you can look at? |
I want to do SSL pinning of server certificate that is issued by LetsEncrypt in my flutter code. Following is my code:
The issue is that the callback if returning with the issuer certificate instead of the leaf certificate. Following is the PEM formatted cert that is being called with:
Is this how it is supposed to be or is it a bug? If this is the correct behavior how can I validate the leaf certificate that is issued to my server?
Related: #35981
The text was updated successfully, but these errors were encountered: