|
Message-ID: <CAJpd-bFvTNQK=qGCPdnB1ec=yJ+jZuzaoR9pNbn01pgim=0aLg@mail.gmail.com> Date: Thu, 26 Nov 2015 00:14:16 +0100 From: Salva Peiró <speirofr@...il.com> To: kernel-hardening@...ts.openwall.com Subject: On techniques for preventing commit_creds() user-space abuse A complete version of the technique can be found at http://speirofr.appspot.com/category/techniques/ # Analysis Given the typical path for kernel exploitation is the `commit_creds(prepare_kernel_cred(0))` being called from user space as detailed in [References]. Why is not a check placed in commit_creds() that checks the return address of the call to ensure the call is a legit one coming from kernel space?. This blocks direct calls to commit_creds from user space, however, it remains vulnerable to alternative exploit routes. The alternatives to bypass this protection are: - *Indirect jump* An attacker can perform an indirect jump to a kernel location that does the commit_creds() for him, but it complicates the task of the attacker. To prevent indirect calls check the rest of the stack trace. - *Direct override* Another route to bypass would be to figure out the location of the process creds in memory, and perform the change directly in memory, but AFAIK SMAP and its ARM equivalent would deter this route. Therefore, I started implementing some exploits for testing it, and implemented the `commit_cred` protection checks technique to check if it is viable for preventing the commit_creds abuse. The [Implementation] provides a patch that implements the discussed approach. The [Evaluation] provides the tests performed showing it effectively blocks commit_creds abuse from user space. # Threat Model The steps involved in commit_creds() exploits: - Prepare user code to get root: user_addr = commit_creds(prepare_creds(0)) - Override kernel code with: kernel_struct.fptr = user_addr (1st vuln point SMAP) - Trigger a syscall that calls kernel_struct.fptr - Invoke syscall from user - Results in kernel_struct.fptr() being called Calls user-space code from kernel code (2nd vuln point this point we're already toasted SMEP) Then call commit_creds (kernel_code) from user At this point the can detect commit_creds called from user (3rd vuln: fix check return address) # Implementation The patch implementing the commit_creds() abuse prevention: From: Salva Peiró <speirofr AT gmail.com> Date: Wed, 25 Nov 2015 14:03:50 +0100 Subject: [PATCH] cred: Prevent commit_creds() user-space abuse Signed-off-by: Salva Peiró <speirofr AT gmail.com> --- kernel/cred.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/kernel/cred.c b/kernel/cred.c index 71179a0..7191db3 100644 --- a/kernel/cred.c +++ b/kernel/cred.c @@ -428,6 +428,13 @@ int commit_creds(struct cred *new) atomic_read(&new->usage), read_cred_subscribers(new)); + /* block attempts to use commit_creds from user space */ + if (__builtin_return_address(0) < PAGE_OFFSET) { + printk(KERN_ERR "CRED: BUG commit_creds called from user space\n"); + WARN_ON(1); + return -1; + } + # Evaluation The `dmesg(1)` output below shows the prevention of an exploit attempt using [References] where commit_creds is being called from user-space. [ 1979.132453] exploit[8549]: segfault at 0 ip 08048719 sp bf8ff430 error 6 in exploit[8048000+1000] [ 1981.658186] BUG: commit_creds called from user space [ 1981.658201] ------------[ cut here ]------------ [ 1981.658207] WARNING: CPU: 0 PID: 8552 at kernel/cred.c:436 commit_creds+0x1e5/0x210() [ 1981.658209] Modules linked in: nullderef(O) nls_utf8 isofs udf crc_itu_ # References - Much ado about NULL: Exploiting a kernel NULL dereference, by Nelson Elhage https://blogs.oracle.com/ksplice/entry/much_ado_about_null_exploiting1. -- Salva Peiró @ https://speirofr.appspot.com Content of type "text/html" skipped View attachment "0001-cred-Prevent-commit_creds-user-space-abuse.patch" of type "text/x-patch" (1010 bytes)
Powered by blists - more mailing lists
Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.