CVE: CVE-2021-30745

Tested Versions:

  • macOS Catalina 10.15.5 (19F101)

Product URL(s):

Description of the vulnerability

This vulnerability exists in QuartzCore Framework, which is used by _windowserver process that allows other applications to interact with OS by mach message that allows attacker can bypass sandbox to get system privilege on the victim’s computer.

_windowserver is a process run as higher privilege act as a server to receive any messages from other applications and handle some system privilege actions for them.

QuartzCore is a Framework that allows users to do anything about animation, image processing, and drawing in _windowserver process.

Communication with _windowserver, the application must use mach message to send data to it.

The vulnerability exists in CA::Render::decode_commands .

while ( 2 )
  {
    v8 = v7;
    v9 = v2;
    v10 = CA::Render::Decoder::decode_int8(v2);
    v11 = v10;
    LOBYTE(v7) = 1;
    switch ( v10 ){
      ...
      case 9:
              v30 = CFStringGetTypeID(v3, v7);
              v31 = (const __CFString *)CA::Render::Decoder::decode_cfobject(v3, v30);
              if ( !(*((_BYTE *)v3 + 10) & 1) )
              {
                v7 = (__int64)v31;
                v8 = COERCE_DOUBLE(CA::Render::Context::set_client_annotation((CA::Render::Context *)v6, v31));
      LABEL_60:
                v9 = v10;
      LABEL_61:
    }

The problem is CA::Render trying to decode opcode 9 command which trigger another decode action CA::Render::Decoder::decode_cfobject

 case 9:
    lVar9 = 0;
    *(long *)((long)&local_38 + lVar4) = 0x1d278f;
    cg_image = decode_object(this,0,*(undefined *)((long)&local_38 + lVar4));
    if (cg_image == 0) goto LAB_001d282a;
    *(long *)((long)&local_38 + lVar4) = 0x1d27a3;
    lVar9 = copy_cgimage(cg_image,*(undefined *)((long)&local_38 + lVar4));
    *(long *)((long)&local_38 + lVar4) = 0x1d27ae;
    unref(cg_image,*(undefined *)((long)&local_38 + lVar4));
    break;

If cfobject decodes is CGImage, CA::Render::Decoder::decode_cfobject will call CA::Render::Decoder::decode_object to decode binary form of this cfobject.

As we can see the above decompiled code after call CA::Render::Decoder::decode_cfobject the code only checks cg_image to null, but it does not validate cg_image object type.

Attacker can control what object to be decoded by CA::Render::Decoder::decode_object, and as a result it leads to Type Confusion.

Proof Of Concept

$ ps aux | grep _windowserver
_windowserver      284   5.8  0.4  9690784  70756   ??  Ss   18Jun20 402:26.17 /System/Library/PrivateFrameworks/SkyLight.framework/Resources/WindowServer -daemon

$ sudo lldb
(lldb) attach -p 284
# switch to other terminal
$ clang poc.c -o poc && ./poc ./msg.bin
# wait a few seconds _windowserver will crash
(lldb) attach 284
Target 0: (WindowServer) stopped. 
(lldb)

RAX: 0xE2CA0B29816000D3  RBX: 0x000070000F1F6CE0  RBP: 0x000070000F1F2C90  RSP: 0x000070000F1F2C20  o d I t S z a p c
RDI: 0x00007F9353205FC0  RSI: 0x0000000000009503  RDX: 0x0000000000000001  RCX: 0x0000000000000002
RIP: 0x00007FFF4559BDF2  R8 : 0x000000000000A768  R9 : 0x00007F9353205FC0  R10: 0x00000000FFFFFEFF
R11: 0x0000000000000202  R12: 0x000000000006B897  R13: 0x000000000006B897  R14: 0x0000000000000005
R15: 0x000000000006B897
CS : 002B  GS : 0000  FS : 0000

0x7fff4559bdf2 (0x115df2): 48 3b 45 d0        cmp   rax, qword ptr [rbp - 0x30]
0x7fff4559bdf6 (0x115df6): 0f 85 45 01 00 00  jne   0x7fff4559bf41 ; <+497>
0x7fff4559bdfc (0x115dfc): 48 83 c4 48        add   rsp, 0x48
0x7fff4559be00 (0x115e00): 5b                 pop   rbx
0x7fff4559be01 (0x115e01): 41 5c              pop   r12
0x7fff4559be03 (0x115e03): 41 5d              pop   r13
0x7fff4559be05 (0x115e05): 41 5e              pop   r14
0x7fff4559be07 (0x115e07): 41 5f              pop   r15 
Process 284 stopped

* thread #3, name = 'com.apple.coreanimation.render-server', stop reason = EXC_BAD_ACCESS (code=1, address=0x3000000003)
frame #0: 0x00007fff39e1eff7 CoreGraphics`ERROR_CGDataProviderCreateWithData_BufferIsNotReadable + 39
Target 0: (WindowServer) stopped.
(lldbinit) bt
* thread #3, name = 'com.apple.coreanimation.render-server', stop reason = EXC_BAD_ACCESS (code=1, address=0x3000000003)
* frame #0: 0x00007fff39e1eff7 CoreGraphics`ERROR_CGDataProviderCreateWithData_BufferIsNotReadable + 39
frame #1: 0x00007fff39e1ef8e CoreGraphics`CGDataProviderCreateWithData + 83
frame #2: 0x00007fff45559eb8 QuartzCore`CA::Render::Image::copy_cgimage() const + 202
frame #3: 0x00007fff456587a3 QuartzCore`CA::Render::Decoder::decode_cfobject(unsigned long) + 763
frame #4: 0x00007fff45659b6b QuartzCore`CA::Render::decode_commands(CA::Render::Decoder*) + 622
frame #5: 0x00007fff45609850 QuartzCore`CA::Render::Server::ReceivedMessage::run_command_stream() + 776
frame #6: 0x00007fff454d132c QuartzCore`CA::Render::Server::server_thread(void*) + 1438
frame #7: 0x00007fff454d0d87 QuartzCore`thread_fun(void*) + 25
frame #8: 0x00007fff73a2b109 libsystem_pthread.dylib`_pthread_start + 148
frame #9: 0x00007fff73a26b8b libsystem_pthread.dylib`thread_start + 15 

Suggested Mitigations

  • Do not run any untrusted application.
  • Update to newest macOS if Apple releases the patch.

Timeline

  • 2020-12-18 - Vulnerability reported to vendor
  • 2021-05-20 - Coordinated public release of advisory
  • 2021-05-20 - Advisory Updated