|
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.