santad/SNTEventLog: log original path of translocated apps (#194)

* log original path of translocated apps

* made handle a local variable & fixed capitalization

* Removed superfluous CFError
This commit is contained in:
nguyen-phillip
2017-08-17 11:09:46 -04:00
committed by Tom Burgin
parent ff095bc53d
commit 79662d0dcf

View File

@@ -14,6 +14,7 @@
#import "SNTEventLog.h"
#include <dlfcn.h>
#include <grp.h>
#include <libproc.h>
#include <pwd.h>
@@ -208,6 +209,12 @@
message.gid, [self nameForGID:message.gid],
mode, [self sanitizeString:@(message.path)]];
// Check for app translocation by GateKeeper, and log original path if the case.
NSString *originalPath = [self originalPathForTranslocation:message];
if (originalPath) {
[outLog appendFormat:@"|origpath=%@", [self sanitizeString:originalPath]];
}
if (logArgs) {
[self addArgsForPid:message.pid toString:outLog];
}
@@ -497,4 +504,49 @@
return serial;
}
/**
Uses the executable path, uid, and gid from a given santa_message_t to determine if the path
has been translocated by GateKeeper and if so, returns the original path of the executable. This
requires macOS 10.12 or higher. We use dlopen to access the functions we need in
Security.framework so that we can still build against the 10.11 SDK. If the path has not been
translocated or if running on macOS prior to 10.12, this method returns nil.
*/
- (NSString *)originalPathForTranslocation:(santa_message_t)message {
// The first time this function is called, we attempt to find the addresses of
// SecTranslocateIsTranslocatedURL and SecTranslocateCreateOriginalPathForURL inside of the
// Security.framework library. If we were successful, handle will be non-NULL and is never
// closed.
static Boolean (*IsTranslocatedURL)(CFURLRef, bool *, CFErrorRef *) = NULL;
static CFURLRef __nullable (*CreateOriginalPathForURL)(CFURLRef, CFErrorRef *) = NULL;
static dispatch_once_t token;
dispatch_once(&token, ^{
void *handle = dlopen("/System/Library/Frameworks/Security.framework/Security", RTLD_LAZY);
if (handle) {
IsTranslocatedURL = dlsym(handle, "SecTranslocateIsTranslocatedURL");
CreateOriginalPathForURL = dlsym(handle, "SecTranslocateCreateOriginalPathForURL");
if (!IsTranslocatedURL || !CreateOriginalPathForURL) {
IsTranslocatedURL = NULL;
CreateOriginalPathForURL = NULL;
dlclose(handle);
}
}
});
// If we couldn't open the library or find the functions we need, don't do anything.
if (!IsTranslocatedURL || !CreateOriginalPathForURL) return nil;
// Determine if the executable URL has been translocated or not.
CFURLRef cfExecURL = (__bridge CFURLRef)[NSURL fileURLWithPath:@(message.path)];
bool isTranslocated = false;
if (!IsTranslocatedURL(cfExecURL, &isTranslocated, NULL) || !isTranslocated) return nil;
// SecTranslocateCreateOriginalPathForURL requires that our uid be the same as the user who
// launched the executable. So we temporarily drop from root down to this uid, then reset.
pthread_setugid_np(message.uid, message.gid);
NSURL *origURL = CFBridgingRelease(CreateOriginalPathForURL(cfExecURL, NULL));
pthread_setugid_np(KAUTH_UID_NONE, KAUTH_GID_NONE);
return [origURL path]; // this will be nil if there was an error
}
@end