Desync in Entitlement (DER) Parsing leading to Privilege Escalation

We discussed this vulnerability during Episode 179 on 16 January 2023

A post by project zero on a vuln in a new library used for DER entitlements. Entitlements are Apple’s fine-grained permission system and essentially define what capabilities an app or service has. Third party apps can request a limited subset of entitlements, which are signed off by Apple before making its way to the app store. Previously, entitlements were XML-based and subject to parsing bugs as it was quite complicated and there were 4-5 different parsers. In iOS 15, Distinguished Encoding Rule (DER) entitlements were introduced, which use the X.690 binary format of tag-length-data rules.

Vulnerability While this simplified parsing down from 4-5 parsers to 1, it still had a few different methods that would traverse the entitlements (recursivelyValidateEntitlements(), der_vm_iterate(), and der_vm_execute_nocopy()). The problem is that there were differences in how each of these algorithms processed the a malformed SEQUENCE inside of the entitlements blob. There are two length values that matter for this issue. First, in DER every entity being encoded has a length value representing the number of bytes the entity takes up. Then specifically for a SEQUENCE the value starts with the count of entities in the sequence. The vulnerability happens in a mismatch between how the parsers handle a sequence with sequence whose contents are smaller than the length in bytes provided earlier.

In the case of der_vm_iterate() it would jump ahead from where the sequence ended to where its Length value indicated it ended. Ignoring any of the extra content. der_vm_execute_nocopy however would continue processing from the end of the last entity in the sequence.

This bug effectively allows you to smuggle entitlements by embedding them as children of other entitlements. They’d be visible to der_vm_execute_nocopy() for querying the entitlements, but hidden from functions that use der_vm_iterate() like CEContextIsSubset(). Exploiting this involved getting around a few roadblocks in the DER structure (such as the fact they had to be alphabetical), and the entitlements they could use were limited as many userspace daemons use the legacy XML-based entitlement system. However, the kernel was a viable target, and they were able to invoke kext_request API methods for kernel extensions, which is a highly privileged functionality.

Patch This bug was fixed by accident when Apple refactored DER entitlement parsing to take the parent DERs as input. However, Apple also put out a patch that adds some additional validation to ensure a key/value sequence doesn’t contain other elements.