SSL Kill Switch and Twitter iOS

Some time ago, SSL Kill Switch somehow stopped working on the Twitter iOS App, preventing the interception and decryption of the App’s HTTPS traffic for reverse-engineering purposes. Twitter was actually one of the first iOS Apps to implement SSL pinning, and I remember using it as a test App when I started working on the first version of , a few years ago.

I finally took the time to investigate this issue and just released v0.10 of SSL Kill Switch, which will work on Twitter iOS again (and any CocoaSPDY App).

Why it stopped working

SSL Kill Switch broke when Twitter updated their iOS App to use the SPDY protocol to replace HTTPS when connecting to its server endpoints. This explains why this specific App was not affected by SSL Kill Switch, although the tool was able to disable SSL pinning in every other App on the Store and even Apple daemons and services.

Twitter open-sourced their SPDY implementation for iOS/OS X, , which helped me figure out what wasn’t working.

Act 1: CocoaSPDY and SSL Validation

At a very high level, SSL Kill Switch disables SSL validation and pinning by preventing Apps from being able to set the SecureTransport callback for validating the server’s certificate chain; it instead sets a callback that skips all SSL validation, making it easy to intercept and decrypt the App’s HTTPS traffic using a proxy like Burp or Charles.

However, CocoaSPDY does not rely on this callback mechanism, and instead always retrieves and validates the server certificate at the end of the TLS handshake, using the CFStream APIs:


This is why SSL Kill Switch did not affect CocoaSPDY (and Twitter iOS) at all and a new strategy was needed in order to disable SSL validation. Unfortunately, I did not find a way to disable SSL validation in a generic fashion, for code that validates the certificate by retrieving it with kCFStreamPropertySSLPeerTrust. Hence, I had to implement a CocaSPDY-specific workaround.

Within the library, certificate validation can be customized by creating a class that conforms to theSPDYTLSTrustEvaluator Objective-C protocol, and setting an instance of this class as SPDYProtocol’s trust evaluator, using the + setTLSTrustEvaluator: method. Then, all SPDY connections call into this trust evaluator when the server’s certificate chain needs to be validated.

To disable this mechanism, I simply had to update SSL Kill Switch override the + setTLSTrustEvaluator:method to force a nil trust evaluator (which CocoaSPDY sees as a trust-all evaluator):


This ensured that CocoaSPDY connections would not validate SSL certificates as soon as SSL Kill Switch was loaded in the App. However, I ran into another problem as I was still not able to intercept Twitter’s HTTPS traffic using the Burp proxy.

Act 2: SPDY Proxy-ing

After disabling SSL validation, I was still not able to see the traffic in Burp for a very simple reason: Burp does not support the SPDY protocol. Although I later realized that there are other proxy tools that do support SPDY (such as SSLSplit), I wanted to use Burp for what I needed to do.

Luckily, I noticed that CocoaSPDY is implemented in a way that makes it very easy to deploy SPDY within any App: it leverages the powerful NSURLProtocol API in order to transparently transform the App’s outgoing HTTPS requests into SPDY requests. Hence, all it takes to turn any iOS App into a SPDY App is a few lines of code:


This is very neat, and also gave me the idea to just disable these initialization routines in SSL Kill Switch in order to turn the App’s traffic back into HTTPS, which Burp obviously supports. For example, this is how SSL Kill Switch downgrades NSURLSession connections from SPDY to HTTPS:


After disabling CocoaSPDY’s initialization methods in SSL Kill Switch, I was finally able to use Burp to intercept Twitter iOS’ network traffic:

Try it out!

You can get the latest version of SSL Kill Switch on the project’s page.

转载自:    原文作者:nabla_c0d3