Apples On A Plane, or that was zealots on a plane?


Apple provides the following description about CFNetwork:

CFNetwork is a framework in the Core Services framework that provides a library of abstractions for network protocols.

CFNetwork fails to handle certain HTTP responses properly, causing the _CFNetConnectionWillEnqueueRequests() function to dereference a NULL pointer, leading to a denial of service condition exploitable by a server sending a crafted response to a client application making use of this API.

Affected versions

This issue has been verified with CFNetwork 129.19 on Mac OS X 10.4.8 (8L2127).

Proof of concept, exploit or instructions to reproduce

The provided proof of concept will listen at the specified port for incoming connections and send back the response necessary to reproduce the denial of service condition on any default CFNetwork-based client.

$ gcc MOAB-25-01-2007.c -o cfnet-http -framework Carbon
$ ruby MOAB-25-01-2007.rb 8080
++ Starting HTTP server at port 8080.
(once ./cfnet-http runs or CFNetwork client connects...)
++ Connected: CFNetwork/129.19

Note: the provided MOAB-25-01-2007.c is just an example of a CFNetwork-based application affected by the issue. Generally any application is affected unless it has implemented it's own handling for the redirections (ex. Software Update fortunately does this).

Debugging information

The following debugging information shows the example CFNetwork client triggering the issue:

(gdb) r
Starting program: .../cfnet-http 
Reading symbols for shared libraries ................................... done
Requesting URL

Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_PROTECTION_FAILURE at address: 0x00000008
0x910131ea in _CFNetConnectionWillEnqueueRequests ()

(gdb) i r
eax            0x0      0
ecx            0x1800038        25165880
edx            0xbfff754c       -1073777332
ebx            0x910127c3       -1862195261
esp            0xbfff7400       0xbfff7400
ebp            0xbfff7418       0xbfff7418
esi            0x12c    300
edi            0x0      0
eip            0x910131ea       0x910131ea <_CFNetConnectionWillEnqueueRequests+11>
eflags         0x10286  66182
cs             0x17     23
ss             0x1f     31
ds             0x1f     31
es             0x1f     31
fs             0x0      0
gs             0x37     55

(gdb) back
#0  0x910131ea in _CFNetConnectionWillEnqueueRequests ()
#1  0x910130f8 in addAuthenticationInfoToResponse1 ()
#2  0x91012a87 in checkHeaders ()
#3  0x91008c37 in httpRequestStateChanged ()
#4  0x9101022e in scheduleNewResponse ()
#5  0x91015386 in _CFNetConnectionResponseIsComplete ()
#6  0x9101469b in httpRequestRead ()
#7  0x9087875a in CFReadStreamRead ()
#8  0x910200c4 in _CFHTTPMessageSendRequest ()
#9  0x91020332 in _CFURLCreateDataAndPropertiesFromResource ()
#10 0x9082b5be in CFURLCreateDataAndPropertiesFromResource ()
#11 0x00001f28 in main ()

(gdb) disas _CFNetConnectionWillEnqueueRequests
Dump of assembler code for function _CFNetConnectionWillEnqueueRequests:
0x910131df <_CFNetConnectionWillEnqueueRequests+0>:     push   %ebp
0x910131e0 <_CFNetConnectionWillEnqueueRequests+1>:     mov    %esp,%ebp
0x910131e2 <_CFNetConnectionWillEnqueueRequests+3>:     push   %edi
0x910131e3 <_CFNetConnectionWillEnqueueRequests+4>:     push   %esi
0x910131e4 <_CFNetConnectionWillEnqueueRequests+5>:     sub    $0x10,%esp
0x910131e7 <_CFNetConnectionWillEnqueueRequests+8>:     mov    8(%ebp),%edi
0x910131ea <_CFNetConnectionWillEnqueueRequests+11>:    mov    8(%edi),%edx
0x910131ed <_CFNetConnectionWillEnqueueRequests+14>:    test   $0x1,%dl
0x910131f0 <_CFNetConnectionWillEnqueueRequests+17>:    je     0x91013200
0x910131f2 <_CFNetConnectionWillEnqueueRequests+19>:    lea    12(%edi),%eax
0x910131f5 <_CFNetConnectionWillEnqueueRequests+22>:    mov    %eax,(%esp)
0x910131f8 <_CFNetConnectionWillEnqueueRequests+25>:    call   0xa100649c
0x910131fd <_CFNetConnectionWillEnqueueRequests+30>:    mov    8(%edi),%edx
0x91013200 <_CFNetConnectionWillEnqueueRequests+33>:    mov    %edx,%eax
0x91013202 <_CFNetConnectionWillEnqueueRequests+35>:    shr    %eax
0x91013204 <_CFNetConnectionWillEnqueueRequests+37>:    and    $0x1,%al
0x91013206 <_CFNetConnectionWillEnqueueRequests+39>:    mov    %eax,%esi
0x91013208 <_CFNetConnectionWillEnqueueRequests+41>:    and    $0x1,%dl
0x9101320b <_CFNetConnectionWillEnqueueRequests+44>:    je     0x91013218
0x9101320d <_CFNetConnectionWillEnqueueRequests+46>:    lea    12(%edi),%eax
0x91013210 <_CFNetConnectionWillEnqueueRequests+49>:    mov    %eax,(%esp)
0x91013213 <_CFNetConnectionWillEnqueueRequests+52>:    call   0xa10064a6
0x91013218 <_CFNetConnectionWillEnqueueRequests+57>:    mov    %esi,%edx
0x9101321a <_CFNetConnectionWillEnqueueRequests+59>:    movzbl %dl,%eax
0x9101321d <_CFNetConnectionWillEnqueueRequests+62>:    add    $0x10,%esp
0x91013220 <_CFNetConnectionWillEnqueueRequests+65>:    pop    %esi
0x91013221 <_CFNetConnectionWillEnqueueRequests+66>:    pop    %edi
0x91013222 <_CFNetConnectionWillEnqueueRequests+67>:    pop    %ebp
0x91013223 <_CFNetConnectionWillEnqueueRequests+68>:    ret    
End of assembler dump.

(gdb) p (void *)$edi
$2 = (void *) 0x0
(gdb) p (void *)$edx
$4 = (void *) 0xbfff754c
(gdb) x/x $edx
0xbfff754c:     0x91009000
(gdb) x/i 0x91009000
0x91009000 <scheduleNewRequest+262>:    pop    %esi


Exploitation conditions

This issue will lead to a denial of service only. Arbitrary code execution isn't possible at all, as it's simply dereferencing a NULL pointer. It's worth noting that apparently CFNetwork doesn't perform any sanity checking over these responses and thus the application must take care of verifying them at it's own. For instance, Software Update isn't affected.

Then again, this issue, in couple with MOAB-22-01-2007 gets you another shiny root shell. And unlike certain people who-miss-the-point say, integrating it with a remote exploit is as simple as using a download+exec payload (ex. via fork(), execve() curl, wait for pid, then execve of downloaded file...).

Workaround or temporary solution

Perform sanity checking of HTTP responses received via CFNetwork API. Wait for Apple to add further checks and fix the _CFNetConnectionWillEnqueueRequests() API.