Working Around Phoney SSL Certificates on iOS With OpenSSL
Following our last post on the basicConstraints vulnerability in Apple's iOS certificate validation, we developed a proof-of-concept app* that implements a better workaround, with some help from OpenSSL. The source code is available now at https://github.com/akgood/iOSBasicConstraintsWorkaround.
At a high level, our workaround functions by first using iOS's built-in frameworks to validate a certificate chain for an SSL connection, and then - if iOS determines that the chain is valid - double-checking its result using OpenSSL. In this case, both implementations are slightly incomplete: iOS, as we now know, fails to check basicConstraints; meanwhile, our relatively simplistic OpenSSL verification routine does not bother to - for example - check that the leaf certificate's hostname matches the URL request. Running these two checks in sequence, though, we should have everything covered.
The code we released contains a fully-functional test app, which both demonstrates how to use OpenSSL to double-check the results of Apple's security framework (i.e. from a SecTrustEvaluate function call), and one method to hook a Cocoa network I/O mechanism (in this case, NSURLRequest) to augment the default certificate validation mechanism. In the sample app, users can enter a URL and attempt to request it; the text area at the bottom will then show the result of the request. Requests to any site with an invalid certificate chain - including ones that attempt to exploit the basicConstraints flaw (for example, SpiderLabs' test site at https://ssltest.spiderlabs.com) - will fail.
There are a few notable drawbacks with this implementation:
- It requires OpenSSL. OpenSSL can be built for iOS, though doing so is a bit tricky. Additionally, the libraries we built (universal binaries for armv6, armv7, and i386) are about 10MB in total, so they could significantly increase the size of an app. (It's worth noting that OpenSSL is only one of a number of libraries which could probably accomplish the same goal here - others may be friendlier.)
- It replaces Apple's otherwise-stellar certificate error handling with something far more obtuse; when a certificate chain fails to validate for any reason, the system will only return generic error message along the lines of "The operation could not be completed". (Some comments in the source code offer an explanation and some possible avenues for improvement here, for anyone interested).
- For apps that use other APIs than NSURLConnection for SSL/TLS communication, different mechanisms will be required to override Apple's built-in certificate validation.
We hope that this code - or at least, the general approach it identifies - will be of some use to the community. Any suggestions for improvement are welcome!
* This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/), and includes cryptographic software written by Eric Young (email@example.com)