Working around phoney SSL certificates on iOS (...or not!)
UPDATE: We have developed a more effective workaround documented here.
A few weeks ago, researchers at TrustWave’s SpiderLabs announced that they had discovered a severe flaw in the way Apple iOS devices validate SSL certificates. In particular, iOS failed to check a particular field - basicConstraints - in certificates that indicates whether or not they are permitted to sign other certificates. This flaw could potentially allow an attacker to intercept and decrypt all traffic between an iOS device and any SSL server, with no indication to the device’s end-user.
Although this flaw is conceptually identical to one initially reported by Moxie Marlinspike in Internet Explorer nearly a decade ago, this was excellent work: it is easy to fall into a trap of complacency in which we assume that, because a class of vulnerabilities was identified and widely publicized/patched long ago, it is now dead and buried. Clearly, these sorts of assumptions are dangerous and need to be challenged regularly.
Apple has since released iOS updates to patch this flaw (although it does appear that updates for some older devices are not currently available). For all iPhone, iPod, and iPad users for whom updates are available, we strongly recommend installing these updates immediately.
In addition, on Sunday (at DEFCON 19), researchers from SpiderLabs announced a potential workaround that would allow individual app developers to ensure that their apps communicate securely over SSL, even on devices running vulnerable versions of iOS.
Unfortunately, this workaround appears not to work.
(Note: To better understand the rest of this post, we suggest first reading Moxie’s original explanation of the flaw).
To be more precise, the workaround - if implemented in exactly the form suggested by SpiderLabs - may indeed reject certificates crafted using attacks that exploit the basicConstraints vulnerability, but it also appears that it will reject any certificates which use an intermediate CA certificate at all (unless the intermediate CA is somehow cached by the system). This would therefore affect a substantial fraction - if not a vast majority - of SSL-enabled sites on the internet.
We performed a few tests to confirm this, using two iOS devices:
- A vulnerable device: a second-generation iPod Touch, running iOS 4.2.1. Notably, this still appears to be the latest iOS version available for a second-generation iPod Touch, so there is no (official?) way to patch it.
- A patched device: an iPhone 4 running iOS 4.3.5
For our first test, we fetched the certificate chain currently used to identify https://encrypted.google.com. It consists of three certificates:
- A root CA: Equifax Secure Certificate Authority
- An intermediate CA: Google Internet Authority
- A leaf certificate: *.google.com
We then attempted to use the provided isCertValid function to validate only the leaf certificate, as suggested by the SpiderLabs post. On both devices, this certificate - a valid certificate (if my laptop is to be believed) - failed to validate on both devices. We then followed Apple’s documentation to change the call to SecTrustCreateWithCertificates from passing only a leaf certificate to passing an array containing both the leaf certificate and the intermediate CA, at which point, the certificate validated successfully on both devices.
Second, we created a few certificate chains of our own for testing. Again, each chain had three certificates: a root CA, an intermediate CA, and a leaf certificate. In addition, while one of these chains was perfectly valid, the other contained an intermediate certificate with its basicConstraints extension set to CA:FALSE. A correct implementation should reject this second chain, but an implementation that fails to check basicConstraints would accept it as valid.
Because we were using a custom-generated test root certificate, we had to install it as a trusted root on both devices before proceeding. This is easy to do on an iOS device (though not in the simulator): you merely need to open a link to download the certificate in Safari, and the OS will prompt you to install/trust it.
With the root certificate installed, we performed the same tests as we had done with the Google certificate chain. We began by attempting to validate only the leaf certificate on each chain: this failed for both chains, on both devices.
Next, we attempted validation, for each chain, with both the leaf certificate and the intermediate certificate. On the vulnerable device, both chains validated successfully. On the patched device, only the chain with the correct basicConstraints flag validated successfully. This is exactly the behavior we would have expected to see with no workaround in place.
Even though their workaround appears incorrect, the motivations suggested by the SpiderLabs researchers in developing it are entirely valid. We do believe it may be possible to construct a successful workaround, though it may have to be rather more complicated than the code they provided. In particular, a successful workaround could require replacing - or at least augmenting - the actual chain-validation implementation. (One possibility might be to cross-compile OpenSSL for iOS/ARM, and write a custom handler that grabs all the DER data for the certificates in the SSL peer’s chain, and uses OpenSSL’s validation rather than - or in addition to - iOS’s.) We will continue investigating these possibilities, and we encourage others to do so as well.
Otherwise, the one bit of good news is that uptake for iOS updates is much faster than on just about any other mobile platform. It would be nice if Apple provided patches for older devices, though…