Kuboid
Open Luck·Kuboid.in
Black Hat2023
Open in YouTube ↗

Apple's Predicament: NSPredicate Exploits on iOS and macOS

Black Hat3,685 views36:07about 2 years ago

This talk demonstrates how the NSPredicate evaluation engine can be abused to achieve arbitrary code execution on iOS and macOS by bypassing security mitigations like Pointer Authentication Codes (PAC) and sandbox restrictions. The researcher shows how to manipulate NSPredicate objects to perform unauthorized method invocations and access sensitive system APIs. The presentation highlights the inherent dangers of using NSPredicate with untrusted input and provides techniques for bypassing Apple's denylist-based security controls. A live demo showcases the exploitation of system daemons to exfiltrate sensitive user data.

Bypassing iOS Sandbox Restrictions via NSPredicate Injection

TLDR: Austin Emmitt’s research reveals that the NSPredicate evaluation engine in iOS and macOS can be weaponized to achieve arbitrary code execution and sandbox escapes. By manipulating serialized NSPredicate objects sent over XPC, attackers can bypass security mitigations like Pointer Authentication Codes (PAC) and Apple’s denylist-based controls. This technique allows for the exploitation of system daemons to exfiltrate sensitive user data, making it a critical concern for anyone auditing Apple’s inter-process communication mechanisms.

Security researchers often overlook the seemingly benign utility classes that bridge the gap between high-level Objective-C logic and low-level system operations. NSPredicate is one such class, designed to filter collections of objects using logical conditions. While it appears to be a simple tool for developers, it is actually a powerful, dynamic scripting engine that, when exposed to untrusted input, becomes a massive security liability. This research demonstrates that NSPredicate is essentially an eval() function for Objective-C, capable of executing arbitrary methods and accessing sensitive APIs, effectively turning a data-filtering mechanism into a full-blown remote code execution primitive.

The Mechanics of the Injection

At its core, NSPredicate allows for the dynamic invocation of methods at runtime. When an application processes an NSPredicate object, it parses the predicate string into an expression tree. If an attacker can control the input to this parser, they can inject malicious expressions that the system will faithfully execute. The danger is compounded by the fact that NSPredicate objects are frequently serialized and passed across process boundaries via XPC, Apple’s primary inter-process communication mechanism.

The research highlights how an attacker can craft a malicious NSPredicate that utilizes the FUNCTION keyword. This keyword allows for the invocation of any method on an object with arbitrary arguments. By combining this with the CAST keyword, an attacker can obtain a reference to any class in the runtime, effectively bypassing the intended scope of the application. This is not merely a theoretical vulnerability; it is a direct path to executing code within the context of a privileged system daemon.

Bypassing PAC and Denylists

Apple attempted to mitigate these risks by implementing denylists of classes and methods that are considered inherently dangerous. However, these protections are fundamentally flawed because they rely on a single, mutable flag: _predicateSecurityFlags. By using the same injection primitive to call setDebugPredicateSecurityScoping, an attacker can simply unset this flag, effectively disabling all security checks for the remainder of the process lifecycle.

Furthermore, the research demonstrates a clever bypass for Pointer Authentication Codes (PAC), a hardware-based security feature designed to prevent code reuse attacks. By leveraging the dlopen and dlsym functionality exposed through CNFileServices or other system classes, an attacker can resolve the addresses of exported functions and obtain the necessary signed pointers to execute them. This effectively renders PAC useless against an attacker who can already control the execution flow via NSPredicate injection.

Real-World Impact and Exploitation

During a penetration test or a bug bounty engagement, you should look for any application or system daemon that accepts NSPredicate objects as input, especially those that receive them over XPC. The SpringBoard app, coreduetd, and OSLogService are prime targets. If you find a service that deserializes these objects without strict validation, you have a potential entry point.

The exploitation flow typically involves:

  1. Identifying an XPC interface that accepts NSPredicate objects.
  2. Crafting a malicious predicate string that uses FUNCTION or CAST to invoke sensitive methods.
  3. Bypassing the _predicateSecurityFlags check by overwriting the flag in memory.
  4. Using the resulting primitive to exfiltrate data or escalate privileges.

For instance, the demo shown in the research involved exfiltrating user notifications by forcing a target daemon to copy sensitive files to a location accessible by the attacker. This is a classic T1203 exploitation scenario where client-side execution is leveraged to gain unauthorized access to system resources.

Defensive Considerations

Defending against this class of vulnerability requires a shift in how we handle data-driven logic. If you are a developer, the most effective mitigation is to avoid using string-based predicates entirely. Instead, use block-based predicates, which are not susceptible to the same injection attacks. If you must use string-based predicates, ensure that the input is strictly validated and never derived from untrusted sources.

For blue teams, monitoring for unusual XPC traffic or unexpected method invocations within system daemons can provide early warning signs of an exploit attempt. However, given the dynamic nature of Objective-C and the flexibility of NSPredicate, detection is notoriously difficult. The best approach is to treat any process that evaluates NSPredicate objects as a high-risk component and apply the principle of least privilege to its sandbox profile.

Ultimately, this research serves as a stark reminder that even the most standard system libraries can harbor deep-seated vulnerabilities. When you are auditing iOS or macOS, do not assume that a class is safe just because it is part of the standard framework. Look for the places where data is transformed into code, and you will often find the most interesting bugs.

Talk Type
research presentation
Difficulty
expert
Has Demo Has Code Tool Released


Black Hat USA 2023

118 talks · 2023
Browse conference →
Premium Security Audit

We break your app before they do.

Professional penetration testing and vulnerability assessments by the Kuboid Secure Layer team. Securing your infrastructure at every layer.

Get in Touch
Official Security Partner
kuboid.in