Bypass macOS rootless by sandboxing
This bug has been fixed in Mojave Beta, but sill present in latest High Sierra (10.13.5). It’s a logical bug that an entitled binary tries to load an insecure external library controllable by environment variable. To exploit it we need to abuse sandbox, which is interesting that sometimes a mitigation could be turned to an exploit.
CoreSymbolication(/System/Library/PrivateFrameworks/CoreSymbolication.framework) has some private api for symbolication. When demangling swift application symbols, it tries to load external library in following order:
The function xcselect_get_developer_dir_path will return environ variable DEVELOPER_DIR if exists. Absolutely controllable.
Actually the first libswiftDemangle.dylib exists. Will it reach the last branch? I’ll talk about it later.
Apple has built-in com.apple.SamplingTools in:
And they are entitled:
➜ ~ jtool --ent `which symbols`
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
With this entitlement, SamplingTools can attach to SIP protected process with
task_for_pid, even without root privilege.
$ vmmap Finder | head -n 8
Process: Finder 
Load Address: 0x10515f000
Version: 10.13.5 (10.13.5)
Build Info: Finder_FE-1054005004000000~3
Code Type: X86–64
Parent Process: ??? 
LLDB fails even it’s rooted:
$ sudo lldb -n Finder
(lldb) process attach --name "Finder"
error: attach failed: cannot attach to process due to System Integrity Protection
So this seems like a “meta” entitlement. With it you can just inject to other entitled process and gain arbitrary entitlement.
Let’s just start an application compiled with swift, then run
symbols [pid] -printDemangling and it will call
CoreSymbolication!demangle, which has potential ability to load insecure code.
But there are two problems. First, the last branch looks impossible to be reached because /System/Library/PrivateFrameworks/Swift/libswiftDemangle.dylib exists.
Actually we can just block them with a sandbox. Yeah, use the security facility to trigger something insecure.
Then, spawn a child process with
symbols [pid] -printDemangling to trigger dylib hijack.
Now we have a second problem. It crashes.
System Integrity Protection: enabled
Crashed Thread: 0 Dispatch queue: com.apple.main-thread
Exception Type: EXC_BAD_ACCESS (Code Signature Invalid)
Exception Codes: 0x0000000000000032, 0x000000010d745000
Exception Note: EXC_CORPSE_NOTIFY
Termination Reason: Namespace CODESIGNING, Code 0x2
External Modification Warnings:
Process used task_for_pid().
VM Regions Near 0x10d745000:
MALLOC_LARGE 000000010d70a000-000000010d745000 [ 236K] rw-/rwx SM=PRV
--> mapped file 000000010d745000-000000010d746000 [ 4K] r-x/r-x SM=PRV Object_id=2929ab85
mapped file 000000010d748000-000000010d762000 [ 104K] r--/r-- SM=ALI Object_id=2af85085
Application Specific Information:
dyld: in dlopen()
12 libdyld.dylib 0x00007fff66c9fd86 dlopen + 86
13 com.apple.CoreSymbolication 0x00007fff52d15332 invocation function for block in call_external_demangle(char const*) + 348
14 libdispatch.dylib 0x00007fff66c64e08 _dispatch_client_callout + 8
15 libdispatch.dylib 0x00007fff66c64dbb dispatch_once_f + 41
16 com.apple.CoreSymbolication 0x00007fff52cb880f demangle + 298
17 com.apple.CoreSymbolication 0x00007fff52cb85e3 TRawSymbol<Pointer64>::name() + 75
18 com.apple.CoreSymbolication 0x00007fff52cbd88e CSSymbolGetName + 166
com.apple.SamplingTools in latest macOS are code signed with Library Validation flag, so loading unsigned dylib is prohibited.
➜ ~ codesign -dvvv `which symbols`
Format=Mach-O thin (x86_64)
CodeDirectory v=20100 size=1384 flags=0x2000(library-validation) hashes=36+5 location=embedded
I just had an El Capitan vm and I looked into it. Wow, the previous SamplingTools distribution has valid code signature, without the flag.
Only one trouble is that, the built-in binary can
task_for_pid without root, if target is running with the same uid. But our copy from old macOS will pop a dialog asking for administrative account, unless you have done sudo /usr/sbin/DevToolsSecurity -enable before.
What a pity that it almost archive EoP.
So just copy to High Sierra and it works. Abuse task_for_pid to inject to diskmanagementd and you’ll have the privilege to write to /System.
Didn’t know if Apple has realized it, but it has been fixed in Mojave Beta. No more external library, finally.