appmattus/certificatetransparency

Issue when using CT on both an SDK and an app simultaneously

Closed this issue · 4 comments

Context:
My team develops SDKs that communicates with an backend.
Currently we use SSL Pinning to prevent MITM attacks and considering switch to CT.
I have an issue to report and a question. Somehow, I think both are related.

Issue:
When both an SDK and an app that uses that SDK installs CT, it crashes:
AndroidRuntime: java.lang.StackOverflowError: stack size 8188KB at javax.net.ssl.TrustManagerFactory.init(TrustManagerFactory.java:266) at com.appmattus.certificatetransparency.internal.verifier.CertificateTransparencyTrustManagerFactory.engineInit(CertificateTransparencyTrustManagerFactory.kt:30) at javax.net.ssl.TrustManagerFactory.init(TrustManagerFactory.java:266) at com.appmattus.certificatetransparency.internal.verifier.CertificateTransparencyTrustManagerFactory.engineInit(CertificateTransparencyTrustManagerFactory.kt:30) at javax.net.ssl.TrustManagerFactory.init(TrustManagerFactory.java:266) at com.appmattus.certificatetransparency.internal.verifier.CertificateTransparencyTrustManagerFactory.engineInit(CertificateTransparencyTrustManagerFactory.kt:30) at javax.net.ssl.TrustManagerFactory.init(TrustManagerFactory.java:266) at com.appmattus.certificatetransparency.internal.verifier.CertificateTransparencyTrustManagerFactory.engineInit(CertificateTransparencyTrustManagerFactory.kt:30) at javax.net.ssl.TrustManagerFactory.init(TrustManagerFactory.java:266) at com.appmattus.certificatetransparency.internal.verifier.CertificateTransparencyTrustManagerFactory.engineInit(CertificateTransparencyTrustManagerFactory.kt:30)

The setup we are using is pretty simple:
installCertificateTransparencyProvider { logger = BasicAndroidCTLogger(BuildConfig.DEBUG) }

It seems it is a collision issue. Maybe add the possibility to customize provider name would fix it?

Question:
A malicious app can easily deactivate CT installed by our SDK by using removeCertificateTransparencyProvider method.
What is the recommendation to avoid/hamper that scenario?

Maybe add the possibility to customize provider name could be an alternative?
That way our SDK could install a provider with a secret name.

Thanks.

Sample project illustrating the issue: https://github.com/rbrauwers/CT-Issue

Interesting problem. I'm hopeful we can come up with something sensible here. As you say being able to customise the name will help to an extent... although of course is never going to stop someone just calling Security.removeProvider with your new name.

The duplicate CT provider is a tricky problem to solve too. At the moment we delegate to the original provider so in that sense having multiple providers shouldn't be a problem, however, I make certain assumptions about the delegate that may not always be true, especially if that delegate is another CT provider.

I'll have to have a play and think

Hi @rbrauwers, from the SDK perspective you'd be better using the CT library through an OkHttp Interceptor or HostnameVerifier (dependent on how you are making network calls). These cannot be so simply removed like the CT provider.

This is a lot more controlled as you are only impacting the network calls you are making whereas with a CT provider you are impacting all network connections (dependent on your configuration - default would cover everything, sdk wise it should be configured to only protect your own urls)

If an SDK were to use a provider then there's always a risk of breaking a clients implementation, for example if they call a domain that doesn't support CT which will be blocked; they have no way of changing the configuration.

In terms of the stack overflow exception when installing two providers this isn't such a simple problem to overcome. There's no easy way of injecting data into a provider because of how the Java Security framework works so at the moment we use a singleton to store configuration. While I can stop the exception from occurring there's a lot of work to do to allow multiple CT providers.

Given the lack of control with providers from a client point of view I don't think the effort would be well spent for its use in SDKs. TLDR use interceptors for SDKs (you just won't have support for WebViews).

Something else that has come up when testing potential solutions is that whichever provider was installed last is the only one that matters because of how Java Security works.

So your SDK would likely install over the top of the clients CT provider and their settings thus ignored.