Researcher: Chilik Tamir (@_coreDump)
Recently, Zimperium blogged about the new WhatsApp vulnerability disclosed by Facebook on May 13th. This vulnerability was reportedly exploited in the wild, and it was designated as CVE-2019-3568. A previous post by Zimperium gave some preliminary information about the vulnerability, impacted WhatsApp products, an alleged exploit and how Zimperium could help with the risks and threats associated with the vulnerability.
This post is the result of additional zLabs research and is designed to add technical details and show a PoC demonstration of what a Remote Code Execution (RCE) on WhatsApp can do by exploiting the vulnerability.
First, A Word of Caution:
In the report of the vulnerability and the patch, Facebook disclosed that the vulnerability was a Remote Code Execution (RCE) affecting both iOS and Android versions of the WhatsApp Client. The targeted platform was not mentioned, and a patch was delivered to all versions: (Android vs. iOS updates)
Since technical details of the vulnerability were not reported publicly, and in order to be consistent with facts, this blog post will be educational in nature. I will selectively focus on several theoretical aspects of the patch that was released.
I will try to deduce some insight on the overall vulnerability, its characteristics, logic, and, most importantly, the possible effect of an RCE in a WhatsApp client running on an iOS device and what could be accomplished by an adversary exploiting the vulnerability.
It is important to note this analysis is only preliminary, and other aspects of the patch will have to be reviewed as well, in order to fully understand the impact of the patched vulnerability.
Habeas Corpus – Patch Analysis
Since this vulnerability was patched on both platforms, and due to the fact that iOS application analysis and reversing blog posts are scarce, I have chosen to target the iOS version of the app in this blog. I hope you will benefit from the process and it will be an educational and good use of your time.
I will be going over the iOS version of the WhatsApp Client. If you wish to follow along, be sure to have versions 2.19.50 (unpatched) and 2.19.51 (patched). Examining both versions (IDA and BinDiff or Ghidra), yields several changes in what appears to be the packet processing functions, of which two functions are dominant (0x100c236b4 and 0x100c25b78). I will go over these functions one at a time.
First, we will inspect the function at 0x0100C236B4 (named here processBrustPackets). The function appears to be in charge of processing STUN and other packet bursts as part of the WhatsApp VoIP stack. Here are the main function parts that were removed in the patched version:
At line 716, there is a size check on packetSize and _Asize both controlled by the caller.
If packetSize is bigger than the 0x7A120, it will cause an integer underflow and the following block would be ignored:
Which leads to what appears to be two-caller controlled calls to memcpy (highlighted).
This execution block had been removed in the updated patched version:
Below is a BinDiff call graph representation of the patched function:
Habeas Corpus – Part Two
The next patched function that caught our attention is at 0x0100C25B78, named handle_incoming_traffic. Here is the part of the function that has been patched:
At line 60, memcpy is called on supplied caller arguments, size is not checked, and this could lead to a buffer overflow vulnerability.
In the patched version, a size check is introduced to make sure that size is <=0x5c8:
This size check was also added in the first function which we covered previously (Annotated below):
To conclude the second part, we understand another potential memory overflow vulnerability had been patched by the introduction of a size checks in these two functions.
It is interesting to point out both of the patched functions play a key role in the communication processing inside WhatsApp application, as can be seen by the caller graph:
At this point, we know the patched version has removed potential buffer overflow and integer underflow vulnerabilities, which could have been exploited into a caller-controlled remote code execution in the WhatsApp application. Next, we will need to validate this function is indeed a part of the reported voice-call functionality that was reportedly used in the attack.
Poking the Bear with an Axe(code)
In order to validate this function is invoked during voice call, use Xcode to connect to the vulnerable WhatsApp application running on a jailbroken device:
Set a breakpoint on the function address (image base and function location), or use Jonatan Levin’s Jtool2 to create a breakpoint command for xCode:
Like this:
Now, initiate a voice call to the account, and, as we assumed, we hit the breakpoint:
Now, let’s step back from the rest of the dynamic analysis and understand what we’ve learned up to this point.
A Red Herring – Not Jumping to Conclusions
Up until now, there has been no publications of the full exploit payload, nor any technical review of the exploit analysis. Could this be a Red Herring?
Without jumping to conclusions, we have been able to validate the following aspects:
- Citizen Lab reported about the possible vulnerability, alongside with The Financial Times.
- WhatsApp patched at least one (possibly more) potential memory corruption vulnerabilities in their iOS client.
- These patches were made in at least two functions that are linked to voice call functionality.
- User interaction was not needed for our breakpoint to hit.
- Google Project Zero included this attack as “suspected” to be used in the wild for remote code execution.
- The iOS operating system was not patched due to this vulnerability disclosure.
The possibility exists that the actual attack did not take place. It may be possible that, for some reason, this vulnerability was tipped off, just to create a wild goose chase and generate eyeballs. This would explain why no payload was disclosed and no analysis was made public to date.
Then again, if the attack took place and was real, while taking all of the above points into consideration, it is safe to surmise a complicated payload was created for the WhatsApp Client application, to be triggered without user interaction resulting in remote code execution capabilities within WhatsApp.
One may linger on how an RCE in WhatsApp could benefit an attacker. Of course, WhatsApp has access to the microphone, camera, location and photos, making it a very rich target for privacy aspects. However, accessing all of that content will require many hoops to jump through, including bypassing PAC on new devices, Stack-Checks, and other mitigations that were introduced to iOS. Moreover, the attacker will need to achieve persistency across reboots. Such an effort would probably be very noisy, draining batteries, abnormal restarts, voice-calls from unknown numbers.
If some entity went through all the effort of reversing, pivoting and patching, crafting payloads, debugging and testing until they got to the result of a remote code execution, they would have to establish a read/write/execute primitives, use info-leaks and runtime calculations in order to succeed in their journey.
They would probably not risk it all, just to be disclosed by the target; hence, we could only imagine that for a perfect attack, other aspects of WhatsApp may have been targeted.
Could there be some quick and effective way of achieving persistency? Some path that would use the command execution capabilities in the application logic that will be as silent as possible, but would give leverage to the adversary, would survive reboots, and offer remote monitoring of the targeted WhatsApp account activity?
Again, as no official data was reported, with regards to the practical exploit mechanism, we are left to our own guesses.
My guess, one that would perfectly fit that description, is exploiting the “WhatsApp Web” feature.
WhatsApp Web – A Trophy for the Adversary
WhatsApp has a popular web client feature, called “WhatsApp Web.” It enables users to connect to their WhatsApp account from anywhere in the world using a simple browser, to send and receive messages, to create new groups, review old messages and much more, as if they are working from their device.
In order to establish this remote-login functionality, the user needs to follow the simple steps of browsing to https://web.whatsapp.com from a computer and scanning a QR-code generated challenge with their WhatsApp application.
Once the challenge has been scanned, the browser is authenticated:
From now on, the remote browser client can read every message, send messages and act as if they are connected to the application, on the device:
Now here is a fact for you to linger on: On Android devices, the user gets a notification for each connected account such as the following:
However, on iOS, the WhatsApp client has less visibility (up until now). If a remote web session is active or if someone has hijacked the WhatsApp session, you will not be prompted for any notification on iOS. If you wish to see if anyone is lurking in your account, you will need to go to Settings:
WhatsApp Web:
And then, you will be presented by a list of connected browsers:
No IP or other identifiers are provided on iOS; just the Browser User-Agent.
Hence, if your account is remotely hijacked, on iOS you receive no notifications.
Oh, and there is more. WhatsApp Web can be persistent indefinitely, as long as the user has connectivity. Even if the target reboots their device.
Sounds like a perfect goal to be used, if you have an RCE vulnerability in WhatsApp.
Enough Talk – Demo Time
By reversing the authorization process, I found that a device can be used to silently authorize a remote web session by invoking one function on the target device:
-[WASettingsViewController qrCodeScannerViewController:didFinishWithCode: ]
This function is responsible for authenticating the challenge presented in a new web session. If this call is executed, it can authorize a remote session connection to the current WhatsApp account.
This can be simulated with a one liner on Xcode:
- Open WhatsApp web by browsing to https://web.whatsapp.com
- Copy the QR-Code challenge and decode it to a string
- In Xcode, pause WhatsApp and paste the following command:
(lldb) po [[WASettingsViewController new] qrCodeScannerViewController:[WAWebClientQRCodeScannerViewController new] didFinishWithCode:@”PUT_TARGET_TOKEN_HERE” ]
- Congratulations, you have just silently hijacked the target account.
Here is a video that demonstrates how an attacker with a remote-code-execution capabilities (Simulated here as a simple debug session) in the WhatsApp Application can use it to execute ANY code in the client application. In this case, hijacking the client WhatsApp session, without any notification:
Conclusions
Whether the attack took place as suggested, whether it was targeting Android or iOS, we are still missing some facts. That said, I hope this blog has given you a good example of looking at a potential iOS attack vector, and understanding its characteristics and limitations, as well as a better understanding of how application security vulnerabilities (such as RCE) can be exploited on an updated iOS device to provide stalking capabilities without affecting the device state, and leaving little to no trace.