We did not exploit the kernel extension itself. Instead, we use a less known macOS userspace logical flaw (feature?).
It doesn’t even need to smash one single byte, and the whole exploit is userland only.
In this challenge, SIP has been disabled to load the vulnerable kernel extension.
By default dyld prunes all DYLD_*
environment variables, when binary is code signed with entitlement.
sProcessIsRestricted = processRestricted(mainExecutableMH);
if ( sProcessIsRestricted ) {
#if SUPPORT_LC_DYLD_ENVIRONMENT
checkLoadCommandEnvironmentVariables();
#if SUPPORT_VERSIONED_PATHS
checkVersionedPaths();
#endif
#endif
pruneEnvironmentVariables(envp, &apple);
But after SIP has been introduced, this behavior can be manually disabled with SIP: https://opensource.apple.com/source/dyld/dyld-519.2.2/src/dyld.cpp.auto.html
bool usingSIP = (csr_check(CSR_ALLOW_TASK_FOR_PID) != 0);
uint32_t flags;
if ( csops(0, CS_OPS_STATUS, &flags, sizeof(flags)) != -1 ) {
// On OS X CS_RESTRICT means the program was signed with entitlements
if ( ((flags & CS_RESTRICT) == CS_RESTRICT) && usingSIP ) {
gLinkContext.processIsRestricted = true;
}
The most common IPC mechanism on macOS is XPC.
Most XPC services rely on codesign and entitlement validation to check if the caller is whitelisted to perform certain restricted operations.
Turning off SIP is to open pandora's box.
So the exploit is extremely easy: Use DYLD_INSERT_LIBRARIES
to inject an apple signed, entitled binary, then talk to privileged XPC services and profit.
In the exploit, we chose /System/Library/CoreServices/Setup Assistant.app/Contents/MacOS/Setup Assistant
to borrow its com.apple.private.mbsystemadministration
entitlement, so we are able to communicate with com.apple.mbsystemadministration
.
This service runs as root:
~ ps aux | grep systemadministration
root 1763 0.0 0.2 4383484 28312 ?? Ss 3:48PM 0:00.14 /System/Library/CoreServices/Setup Assistant.app/Contents/Resources/mbsystemadministration
The exported XPC protocol has a method to create arbitrary user with administrator privilege (sudoer):
@protocol MBSAProtocol <NSObject>
- (void)createUserWithInfo:(NSDictionary *)arg1
completionBlock:(void (^)(unsigned int))arg2;
@end
Now use the administrator account to get root.
Here's apple's response for the trick:
After examining your report we do not see any actual security implications. SIP is enabled by default and disabling it puts a user at risk. You can find additional information here -> https://support.apple.com/en-us/HT204899