Meet WiFiDemon: iOS 0-day/0-click vulnerability that was silently patched

Jamf Threat Labs team investigates the 0-click vulnerability affecting Wi-Fi that permits remote code execution (RCE) if exploited, triggering a Denial of Service (DoS) attack, among others. In this blog, the researchers identify what makes the vulnerability possible, how it works and deep dive into the technical details, as well as how to fix the issue to keep your iOS-based fleet protected.

July 17 2021 by

Jamf Threat Labs

Stone carving of a demon's head

TL;DR

Jamf Threat Labs team investigated if the recently announced WiFi format-string bug in wifid was exploited in the wild.

This research led us to interesting discoveries:

  • Recently a silently patched 0-click WiFi proximity vulnerability on iOS 14-iOS 14.4 without any assigned CVE
  • The publicly announced WiFi Denial of Service (DoS) bug, which is currently a 0-day, is more than just a DoS and actually allows Remote Code Execution (RCE).
  • Analysis, if any, of the two bugs were exploited across our cloud user base.

Introduction

There’s a new WiFi vulnerability in town. You probably already saw it but didn’t realize the implication. The recently disclosed “non-dangerous” WiFi bug is potent.

This vulnerability allows an attacker to infect a phone/tablet without any user interaction. This type of attack is known as 0-click (or “zero-click”). The vulnerability was only partially patched.

Prerequisites to the Wifidemon 0-click attack

  • Requires the WiFi to be open with Auto-Join (enabled by default)
  • Vulnerable iOS Version for 0-click: Since iOS 14.0
  • The 0-click vulnerability was patched on iOS 14.4

Solutions

  • Update to the latest version, 14.6 at the time of writing, to avoid the risk of Wifidemon in its 0-click form.
  • Consider disabling WiFi Auto-Join Feature via Settings > WiFi > Auto-Join Hotspot > Never.
  • Perform a risk and compromise assessment of your mobile/tablet security using Jamf in case you suspect you were targeted.

Prerequisites to the WiFi 0-day Format Strings attack

Unlike initial research publications at the time of writing, the WiFi Format Strings seem to be an RCE when joining a malicious SSID.

Solutions

  • Do not join unknown WiFi networks.
  • Consider disabling WiFi Auto-Join Feature via Settings > WiFi > Auto-Join Hotspot > Never.
  • Perform a risk and compromise assessment of your mobile/tablet security using Jamf in case you suspect that you were targeted.
  • This vulnerability is still a 0-day at the time of writing, July 4th. iOS 14.6 is vulnerable when connecting to a specially crafted SSID.
  • Wait for an official update from Apple and apply it as soon as possible.

WiFi D(a)emon?

Wifid is a system daemon that handles protocols associated with a WIFI connection. Wifid runs as root, with most of the handling functions defined in the CoreWiFi framework. These services are not accessible from within the sandbox. Wifid is a sensitive daemon that may lead to a whole system compromise.

Recently, researcher Carl Schou discovered that wifid has a format string problem when handling SSID. Schou’s original tweet suggests that this Wifid bug could permanently disable iPhone’s WiFi functionality, as well as the Hotspot feature. This WiFi DoS is happening since Wifid writes known WiFi SSIDs into the following three files on the disk:

  • /var/preferences/com.apple.WiFi.known-networks.plist
  • /var/preferences/SystemConfiguration/com.apple.WiFi-networks.plist.backup
  • /var/preferences/SystemConfiguration/com.apple.WiFi-private-mac-networks.plist

Every time that Wifid respawns, it reads the bad SSID from a file and crashes again. Even a reboot cannot fix this issue.

However, this bug can be “fixed” by taking the following steps according to Forbes:

“The fix is simple: Simply reset your network settings by going to Settings > General > Reset > Reset Network Settings.”

This bug currently affects the latest iOS 14.6, and Apple has not yet released any fixes for this bug.

Further analysis claims: This is only a Denial of Service

Followed by another researcher, Zhi (@CodeColorist) published a quick analysis. His conclusion was:

“For the exploitability, it doesn’t echo and the rest of the parameters don’t seem like to be controllable. Thus I don’t think this case is exploitable.

After all, to trigger this bug, you need to connect to that WiFi, where the SSID is visible to the victim. A phishing Wi-Fi portal page might as well be more effective.”

The plot thickens

We checked Jamf endpoint security software to see if this bug was exploited in the past. We noticed that two of our EMEA users had an event related to this bug.

Note: we only have access to our cloud data and couldn’t check other on-premises clients.

We asked ourselves:

  1. Why would a person, aware of dangerous threats, connect to a network with such an odd name as “%s%s…”? Our determination is that it was unlikely.
  2. Why would an attacker bring a tactical team to target a VIP, only to cause a DoS? That too, does not make sense.

Remotely exploitable, 0-click, under the hood!

Further analysis revealed that:

  1. Attackers did not need to force the user to connect. This vulnerability could be launched as a 0-click without any user interaction. A victim only needed to have their WiFi turned on to trigger the vulnerable code.
  2. This is not a DoS, but actually an RCE vulnerability for both the recently patched 0-click format strings vulnerability and the malicious SSID format strings 0-day vulnerability.

This 0-click bug was patched on iOS 14.4 and credits “an anonymous researcher” for assisting. Although this is a potent 0-click bug, a CVE was not assigned.

Technical details: Analysis of a zero-click WiFi vulnerability – Wifidemon

Let’s do a deeper dive into the technical details behind this vulnerability.

Considering the possible impact of triggering this vulnerability as a 0-click, as well as the potential RCE implications, we investigated the Wifid vulnerability in depth.

When we tested this format strings bug on an older version, similar to our clients, we noticed that Wifid has intriguing logs when it is not connected to any WiFi.

These logs contain SSIDs, which indicates that they may be affected by the same format string bug.

We tested it and voilà, it is affected by the same format string bug, meaning that this is a zero-click vulnerability and can be triggered without the end-user connecting to a strangely named WiFi. Also, this log relates to a common smart device behavior: automatically scan and join known networks.

Zero-click, even when the screen is off

The iPhone scans WiFi to join every ~3 seconds while the user is actively using the phone. Furthermore, even if the user’s phone screen has been turned off, it still scans for WiFi but at a relatively lower frequency. The waiting time for the following scan will be longer and longer – from ~10 seconds to 1+ minute.

This vulnerability can be triggered as long as the WiFi is turned on. If the user is connected to an existing WiFi network, an attacker can launch another attack to disconnect/disassociate the device and then launch this 0-click attack. Disconnecting a device from WiFi is well-documented and will not be covered as part of the scope of this blog.

This 0-click vulnerability is powerful!

If a malicious access point has password protection and the user never joins the network, nothing will be saved to the disk. After turning off the malicious access point, the user’s WIFI function will be normal. A user could hardly notice if they have been attacked.

Exploiting this vulnerability

We further analyzed whether this vulnerability can be exploited and how.

This post assumes that the reader is aware of the concept of format string bugs and how to exploit them. However, this bug is slightly different from the “traditional” printf format string bugs because it uses [NSString stringWithFormat:] which was implemented by Apple. They removed support for %n for security reasons. That’s how an attacker would have been able to write to the memory in an exploitation of a traditional format string bug.

Where you at? %@ is handy

Since we cannot use %n, we looked for another way to exploit this 0-click, n-day, as well as the 1-click, 0-day wifid bug. Another possible use is %@, which is uniquely used by Objective-C.

Since an SSID length is limited to 32 bytes, we can only put up to sixteen escape characters in a single SSID. Then the escape characters we placed will process the corresponding data on the stack.

A potential exploit opportunity is if we can find an object that has been released on the stack, in that case, we can find a spray method to control the content of that memory and then use %@ to treat it as an Objective-C object, like a typical use-after-free that could lead to code execution.

Step 1: Find possible spraying opportunities on the stack

First, we need to design an automatic method to detect whether it is possible to tweak the data on the stack. lldb breakpoint handling script perfectly fits that purpose. Set a breakpoint right before the format string bug and link to an lldb script that will automatically scan and observe changes in the stack.

Step 2: Find an efficient spraying method

Then, we need a spray method that can interfere with wifid’s memory over the air.

An interesting strategy is called Beacon Flooding Attack. It broadcasts countless beacon frames and results in many access points appearing on the victim’s device.

To perform a beacon flooding attack, you need a wireless Dongle that costs around $10 and a Linux VM. Install the corresponding dongle firmware and a tool called mdk3. For details, please refer to this article.

As part of the beacon frame mandatory field, SSID can store a string of up to 32 bytes. wifid assigns a string object for each detected SSID. You can observe that from the log. This is the most obvious thing we can use for spray.

Now attach a debugger to wifid and start flooding the device with a list of SSIDs that can be easily recognized. Turn on the iOS WiFi feature and wait until it begins automatically scanning for available WiFi. The breakpoint will get triggered and check through the stack to find traces of spray. Below is the output of the lldb script:

The thing that caught our eye is the pointer stored at stack + offset 0x18. Since the SSID can store up to 32 bytes, the shortest format string escape character such as %x will occupy two bytes, which means that we can reach the range of 16 pointers stored on the stack with a single SSID at most. So, stack + offset 0x18 could be reached by the fourth escape character. And the test results tell us that data at this offset could be controlled by the content we spray.

Step 3: Test the ability to remotely control the code execution flow

In the next test, we kept the Beacon Flooding Attack running. Meanwhile, we built a hotspot named “DDDD%x%x%x%@”. Notice that %@ is the fourth escape character. Unsurprisingly, wifid crashes as soon as it reads the name, and it automatically respawns and crashes again as long as the hotspot is still on.

Checking the crash, it appears that the x15 register is easily affected.

Now analyze where it crashed. As the effect of %@ format specifier, it’s trying to print Objective-C Object.

The code block highlighted in yellow is the desired code execution flow. x0 is the pointer stored at stack + offset 0x18. We try to control its content through the spray and lead the situation to the typical use-after-free scenario. x9 is the data x0 points to. It represents an isa pointer, which is the first member of the objc object data structure. As you can see in the figure, control x9 is critical to reaching that objc_msgSend call at the bottom. With more tests, we confirmed that stack + offset 0x18 indeed can be affected by the spray.

Now things have become more familiar. Pass a controlled/fake objc object to objc_msgSend to achieve arbitrary code execution. The next challenge is finding a way to spray memory filled with ROP/JOP payload.

Step 4: Achieving RCE

wifid deals with a lot of wireless features. Spraying large memory wirelessly is left as an exercise for the reader. Locally, this bug can be used to build a partial sandbox escape to help achieve jailbreaking.

Attacks in-the-wild?

Ironically, the events that triggered our interest in this vulnerability were not related to an attack and the two devices were only subject to a DoS issue that was fixed on iOS 14.6.

However, since this vulnerability was widely published and relatively easy to notice, we are highly confident that various threat actors have discovered the same information we did. We would like to encourage the issuance of a patch as soon as possible.

Jamf customers will identify attacks leveraging these vulnerabilities with the tag “Wifidemon”.

Generating an alert using Jamf

We have added generic rules for the detection of successful exploitation of our customer’s devices.

We also provided instructions to customers on how to create a rule to see failed spraying/ASLR bypass attempts.

Key takeaways:

  • A related vulnerability was exploitable as a 0-click until iOS 14.4. CVE was not assigned and the vulnerability was silently patched thanks to Apple and an anonymous researcher.
  • The publicly announced WiFi vulnerability is exploitable on 14.6 when connecting a maliciously crafted SSID.
  • We highly recommend issuing a patch for this vulnerability.
  • Older devices, e.g. iPhone 5s are still on iOS 12.x, which is not vulnerable to the 0-click vulnerability.

If you’d like to check your phone and monitor it, feel free to reach out to us Jamf, or your preferred reseller to discuss how we can help you increase your mobile visibility.

We would like to thank @08tc3wbb, @ihackbanme and SYMaster for assisting with this blog.

iOS 14.7 fix

The fix on iOS 14.7 is pretty straightforward, adding “%s” as a format string and the SSID-included string as a parameter resolves the issue.

Jamf protects against this and numerous other security threats impacting your enterprise fleet.

Subscribe to the Jamf Blog

Have market trends, Apple updates and Jamf news delivered directly to your inbox.

To learn more about how we collect, use, disclose, transfer, and store your information, please visit our Privacy Policy.