|
|
Message-ID: <1448535824.19858.42.camel@opteya.com>
Date: Thu, 26 Nov 2015 12:03:44 +0100
From: Yann Droneaud <ydroneaud@...eya.com>
To: kernel-hardening@...ts.openwall.com
Subject: Re: On techniques for preventing commit_creds()
user-space abuse
Hi,
Le jeudi 26 novembre 2015 à 00:14 +0100, Salva Peiró a écrit :
> 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
>
Please add some explanation in your commit message.
> 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;
> + }
> +
>
What about
#define call_ok() !access_ok(__builtin_return_address(0), VERIFY_READ)
if (WARN(!call_ok(),
"%s called from user space\n", __function__))
return -1;
If __builtin_return_address() is reliable enough, that trick can be
easily added on many sensitive functions.
If such kind of prologue can be injected by compiler in functions
marked with a dedicated attribute, I think that could be a nice thing
to have before PAX's UDEREF and KERNEXEC are made available, as the
latter should better
Regards.
--
Yann Droneaud
OPTEYA
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.