Differences

This shows you the differences between two versions of the page.

Link to this comparison view

p_lkrg:Main [2019/11/22 16:32]
solar drop the Patreon link
p_lkrg:Main [2020/12/17 12:59] (current)
solar replaced much of the content of the page with a note on why it was dropped, added links to currently updated resources
Line 1: Line 1:
 {{ :​p_lkrg:​p_lkrg.png?​500 |}} {{ :​p_lkrg:​p_lkrg.png?​500 |}}
  
-\\ +====== ​Historical ​Linux Kernel Runtime Guard (LKRG) ​wiki ======
-\\ +
-\\ +
- +
-====== ​LKRG ====== +
- +
-[[http://​www.openwall.com/​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 "​[[p_lkrg:​Protected_Features|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: +
- +
-\\ +
- +
-[[p_lkrg:​Threat_model|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: +For up to date information on LKRG, please visit its [[https://​www.openwall.com/​lkrg/​|homepage]]. We do not currently actively update this section ​of the wiki. Instead, we recommend the documentation files included in LKRG releases, with their latest revisions found in the [[https://​github.com/​openwall/​lkrg|GitHub repository]],​ and [[https://​www.openwall.com/​presentations/​OSTconf2020-LKRG-In-A-Nutshell/​|Adam'​s presentation describing LKRG as of version 0.8]].
-  * 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 +This wiki page contained detailed information on early development versions of LKRG roughly up through its 0.0 release made in January 2018. LKRG has since changed, and most of this page's content was finally dropped in 2020 as it became more confusing than useful. However, we preserved ​the exploit detection examples. Some LKRG messages ​are now differentbut overall LKRG should still catch the same attacks on a vulnerable system in a similar way.
-  * 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 systemnot just for the one which executed syscall. +
-This list is not closed and will be evolving.+
  
-===== Examples ​=====+===== Exploit detection examples ​=====
  
 ==== Detecting CVE-2014-9322 (BadIRET) - Fedora 20 ==== ==== Detecting CVE-2014-9322 (BadIRET) - Fedora 20 ====
Line 724: Line 534:
   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.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]!   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 ===== 
-  - 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. 
-  - 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 [[p_lkrg:​Examples|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 [[p_lkrg:​Main#​Modules|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 ===== 
- 
-We used to accept donations for LKRG via Patreon, but we currently don't. Some of our former supporters are listed in the PATREON file in LKRG distribution tarballs. 
- 
-===== 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: 2020/12/17 12:59 by solar
 
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