‘Psychic Paper’, an Extraordinarily Powerful But Easily Understood iOS Exploit


Yesterday Apple released iOS 13.5 beta 3 (seemingly renaming iOS 13.4.5 to 13.5 there), and that killed one of my bugs. It wasn’t just any bug though, it was the first 0day I had ever found. And it was probably also the best one. Not necessarily for how much it gives you, but certainly for how much I’ve used it for, and also for how ridiculously simple it is. So simple, in fact, that the [proof-of-concept] I tweeted out looks like an absolute joke. But it’s 100% real.

I dubbed it “psychic paper” because, just like the item by that name that Doctor Who likes to carry, it allows you get past security checks and make others believe you have a wide range of credentials that you shouldn’t have.

In contrast to virtually any other bug and any other exploit I’ve had to do with, this one should be understandable without any background knowledge in iOS and/or exploitation. In that spirit, I’ll also try and write this post in a manner that assumes no iOS- or exploitation-specific knowledge. I do expect you however to loosely know what XML, public key encryption and hashes are, and understanding C code is certainly a big advantage.

So strap in for the story of what I’ll boldly claim to be the most elegant exploit for the most powerful sandbox escape on iOS yet.

What a crazy bug, and Siguza’s explanation is very cogent. Basically, it comes down to this:

  1. XML is terrible.
  2. iOS uses XML for Plists, and Plists are used everywhere in iOS (and MacOS).
  3. iOS’s sandboxing system depends upon three different XML parsers, which interpret slightly invalid XML input in slightly different ways.

So Siguza’s exploit — which granted an app full access to the entire file system, and more — uses malformed XML comments constructed in a way that one of iOS’s XML parsers sees its declaration of entitlements one way, and another XML parser sees it another way. The XML parser used to check whether an application should be allowed to launch doesn’t see the fishy entitlements because it thinks they’re inside a comment. The XML parser used to determine whether an already running application has permission to do things that require entitlements sees the fishy entitlements and grants permission.

(On a personal note, it pleases me greatly how nicely readable Siguza’s Markdown source is for this report.)

Saturday, 2 May 2020