Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date: Thu, 21 Feb 2019 01:36:02 +0400
From: Ilya Matveychikov <matvejchikov@...il.com>
To: lkrg-users@...ts.openwall.com
Subject: Re: LKRG 6.0 Exploit Detection bypass



> On Feb 20, 2019, at 3:13 PM, Solar Designer <solar@...nwall.com> wrote:
> 
> Hi Ilya,
> 
> On Wed, Feb 20, 2019 at 09:43:53AM +0400, Ilya Matveychikov wrote:
>> I'd like to show few more exploit detection bypass techniques:
>> https://github.com/milabs/kernel-exploits/commit/6bd99d97c3f99a0a743a012b9cb90fb2fe1c0970
> 
> Thank you!
> 
> Adam is in another timezone, so I expect he will comment later, but
> here's my thinking out loud for now:
> 
>> By this commit we have the list of following:
>> - (1) LKRG ED bypass using UMH and chmod + chwon, the very first bypass
>> - (2) LKRG ED bypass by owerwriting inode->i_{uid,gid,mode} using simple_setattr()
>> - (3) LKRG ED bypass by owerwriting inode->i_{uid,gid,mode} directly
>> - (4) LKRG ED bypass by unlocking "UMH lock down" with LD_PRELOAD
>> - LKRG "poor man's CFI" bypass
>> 
>> (1) and (2) were introduced few months before.
>> 
>> (3) is the improvement of (2) which uses DKOM technique to manipulate inode
>> directly without being detected by simple_setattr() hook.
>> 
>> (4) is the bypass of "UMH locking by using whitelist of programs" which basically
>> allows one to use LD_PRELOAD to inject his payload to /sbin/modprobe or similar.
>> 
>> Since the use of (3) and (4) is locked by pCFI (poor man's Control Flow Integrity)
>> mitigation introduced in LKRG 6.0 I had to add the "rich man's CFI bypass" which
>> wraps calls to all of the listed bypasses with 2 macros which are actually fakes
>> the call stack for the time of exploitation so LKRG could not see this.
> 
> If I understand correctly, all of the new bypasses rely on SMEP having
> been disabled by the ROP chain in the exploit, or on hardware (or VM)
> lacking SMEP support.  Correct?

Correct.

> 
> If so, I guess (4) and your poor man's CFI bypass through having custom
> code prepare pCFI-passing fake stack frames would be defeated on
> SMEP-capable systems if LKRG's SMEP enforcement is made stricter.
> Specifically, right now LKRG's p_pcfi_schedule_entry_smep() merely
> re-enables SMEP if it finds that it's been disabled.  A similar check
> could be performed in a shared function to be called from all other
> places where pCFI is enforced, including on UMH, and the enforcement
> action should be at least killing of the current task (so e.g. UMH
> wouldn't proceed to use the environment you prepare for it).

I think the code from the user-mode could be copied to the kernel and
then executed w/o calling a function(s) which you able to hook to enforce
pCFI... Additional research is required. But also keep in mind that in
theory the call to some function could be made by calling it from the 2nd
instruction (the first one is the __fentry__ call). So, it’s possible to
avoid triggering the ftrace (kprobes).

> As to (3), similar pCFI & SMEP enforcement calls could also be added to
> user_path_at_empty() and (too many?) other kernel functions that provide
> pointers to useful kernel objects.  However, I guess you'd bypass this
> by not disabling SMEP until after having called one of those functions
> from a ROP chain.  You'd need to somehow store/recall this function's
> result across the SMEP-disabling portion of the ROP chain, which might
> take extra gadgets to do.  Then you'd only have the direct writes left
> to do with SMEP disabled, which LKRG would be very unlikely to detect in
> time.  (You also do cleanup like the path_put(), but it's optional, it's
> too late by then anyway, and you could even re-enable SMEP before doing
> it to stay undetected.)

Don’t think that SMEP is the issue as soon as there are ROP-gadgets
in the kernel’s code.

> The more elaborate combination of a SMEP-disabling ROP chain and (3)
> that I described above looks really tough for LKRG to protect against,
> and possibly not worth it.  If so, we could in fact go back and
> reconsider/drop some other (existing and potential) defenses if those
> are relevant in the same scenarios as this.
> 
> On a related note, today on kernel-hardening:
> 
> Subject: [PATCH] x86/asm: Pin sensitive CR4 bits
> https://www.openwall.com/lists/kernel-hardening/2019/02/20/1

Nice for the kernel.

> 
> As I understand, this would break the gadget this exploit uses to
> disable SMEP.  I guess LKRG could at its load time live-patch that
> gadget out of a running kernel as well, perhaps patching
> native_write_cr4()'s MOV instruction to be a CALL into LKRG instead.
> Whether this is worth it or not depends on how likely it is or not that
> another suitable gadget is present in the kernel image anyway (not
> necessarily an intentional MOV to CR4 instruction, but just the
> corresponding byte sequence anywhere).
> 
> Alexander
> 
> P.S. There's no LKRG 6.0 yet.

One day it will be ;-)

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.