If you tried to intercept requests from the Facebook app on iOS using a proxy, you will be hitting by their message alert The operation couldn’t be completed. That’s because of their SSL Certificate Pinning protection which must be bypassed to be able to intercept requests and responses from their server. In this blog, We will go through their iOS app trying to bypass their SSL Pinning.
DISCLAIMER: The articles, tutorials, and demos provided on this blog are for informational and educational purposes only, and for those who’re willing and curious to know and learn about Ethical Hacking, Cybersecurity, and Penetration Testing. You shall not misuse the information to gain unauthorized access or any other illegal use.
What is SSL Pinning?
The massive amount of sensitive data and transactions that transported on mobile communication channels made the security risks associated with untrusted communication very critical. An attacker can set up a fake Wi-Fi access point and fake Secure Sockets Layer (SSL) certificates to conduct man-in-the-middle (MITM) attack to capture and manipulate sensitive data.
The application with SSL pinning implemented is configured to trust only one or more predefined certificates. When the application connects to the server, it validates the server certificate with the pinned certificate(s). If they match, the server is trusted and the SSL connection is established, otherwise, it terminates and throws an error alert. SSL Certificate Pinning is mandatory to protect sensitive data from unauthorized interception or access in transmission and described remote attacks.
Tools like SSL Kill Switch won’t always help you in applications with complex SSL Certificate Pinning implementation, so you will have to reverse-engineer the mobile application to manually bypass the Secure Sockets Layer/Transport Layer Security (SSL/TLS) protection. This helps you gain a better insight into the application’s business logic and how it communicates with the server.
Now let’s download the latest version of the Facebook iOS app and step up an HTTP proxy from Wi-Fi settings.
Open Burp Suite and configure your proxy options. Then, open the Facebook app and trying to login. If you are using an older version of Burp Suite (e.g v1.7.36), this mysterious message will appear in your Alert tab:
Also, your Facebook app will show you this alert:
However, If you are using (v2.X.X or v2020.X) you will see a different message in your Dashboard -> Event log tab:
Also, your Facebook app will show you a different alert:
That’s happening because of Facebook Transport Layer Security (TLS) 1.3 implementation. In August 2018, Facebook announced that they have deployed the new generation of Transport Layer Security (TLS) 1.3 using their highly performant TLS library Fizz globally in their mobile apps, which includes a lot of security and performance improvements.
Fortunately, the latest version of Burp Proxy v2020.4 now supports TLS 1.3.
Also, there is a workaround to handle TLS 1.3 with the old Burp Suite v1.7.36, by running its JAR version with JDK 11.0.X using the following command on macOS:
1$ /Library/Java/JavaVirtualMachines/jdk-11.0.7.jdk/Contents/Home/bin/java \2-jar /Applications/Burp\ Suite\ Community\ Edition.app/Contents/java/app/burpsuite_community.jar
If you try to intercept the requests again, you find a new Burp Suite message:
A different alert on the app will show too:
Now we need to get the decrypted IPA for the app to reverse-engineer it. Using Frida iOS Dump you will be able to pull the app IPA from your jailbroken iPhone. After the script finish, change the app extension from .ipa to .zip then uncompress it.
1$ mv Facebook.ipa Facebook.zip2$ unzip Facebook.zip
We need to locate the binary that has the SSL Pinning implementation to reverse it. A good way to locate it by using a tools like grep or ack to search for strings that indicate the validation process inside the extracted Payload folder. A gift from the app alert message, we can use strings like OpenSSL, verify error, signed certificate, and verifier failure.
1$ grep -rins "verify error" .2Binary file ./Facebook.app/Frameworks/FBSharedFramework.framework/FBSharedFramework matches
We found a Mach-O 64-bit shared library binary file called FBSharedFramework. We will use Hopper Disassembler to open the binary file, it will take some time to fully disassemble the binary due to its large size.
A good start is to search with the alert error shown on the app. So, we will try to find the branch that responsible for OpenSSL cert verify error.
We found a match result for our string search. Click on it will navigate us to its location at the __cstring segment which contains all of the strings that are included in the application source code and their hexadecimal offsets.
To locate where the string is used in Hopper you can double-click on the cross-reference (XREF) to move to where the string is referenced in the binary.
Now we need to gain a better understanding of the code logic that responsible for SSL Pinning using the control flow graph (CFG).
Our mission is to avoid reaching the OpenSSL branch so that the app can work normally without any error alerts.
After analyzing the control flow graph (CFG) starting from your bottom branch, we can found an isolated branch that doesn’t reach the OpenSSL cert verify error branch.
We have to invert the b.ne (short for “Branch if Not Equal”) instruction which branches, or “jumps”, to the address specified if, and only if the zero flag is clear, to the b.eq (short for “Branch if Not Equal”) instruction which branches, or “jumps”, to the address specified if, and only if the zero flag is clear. So, instead of entering to loc_1491b4 branch that causing the OpenSSL cert verify error, it entering the valid branch.
A simple way to do this is by copying the hex encoding for the instruction that we want to change, then past it in an online HEX to ARM converter to get its ARM64 instruction.
Then, copy the instruction you got and change it from B.NE to B.EQ as we want it to be. Past it in an online ARM to HEX converter to get our new ARM64 HEX values.
Now, all we have to do is changing the instruction encoding for b.ne from 81 0A 00 54 to 80 0A 00 54 using the hex editor in hopper.
Then, save and extract our new binary, from File Menu -> Choose Produce New Executable and replace the new executable with the old one in the same app directory. Now, let’s compress our new Payload folder and change to an IPA again.
1$ zip -r Facebook.zip Payload2$ mv Facebook.zip Facebook.ipa
After a successful installation for the modified application, let’s open it and login when we intercepting the requests using Burp Suite.
Now we can intercept all the requests and find interesting vulnerabilities at new endpoints then submit them to Facebook Bug Bounty Program.