lunes, septiembre 24, 2007

CVE-2007-4573 ptrace strikes again ;)

The problem discovered by Wojciech Purczynski is:
A 64bit user can say putreg(TIF_IA32) to kernel
and the kernel will enter at the if and do:

value &= 0xffffffff;

ok, lets practice 1100 & 1111 = 1100 The value remain Ok

What happens if we are in 64bits, 0xffffffff is actually 0x00000000ffffffff
Well, the beginning of value will be erased :/

Let see the explotation details.

#define TIF_IA32 17 /* 32bit process */

We know the constant value, lets see the sched function:

static inline int test_tsk_thread_flag
(struct task_struct *tsk, int flag)
return test_ti_thread_flag(task_thread_info(tsk), flag);

static inline int test_ti_thread_flag
(struct thread_info *ti, int flag)
return test_bit(flag,&ti->flags);

quite obvious the bypass :)

Let's see the ptrace call:

When we invoke the PTRACE_SETREGS, we can see that putreg is invoked for each register.

We can do
putreg(child, <register>, <value>);

by calling
ptrace(PTRACE_SETREGS, <somepid>, NULL, <user_regs_struct>)

The key: We can have a 64bits process ptracing a 32bits one, then we can exploit this flaw.

We can erase the registers, is that a potentially priviledge scalation?

Finally: Don't let the user give us a data we know yet, because the user is a motherfucker.