Hi, Has anyone had time to review this patch serie? Any comments on this? Regards. On Sun, Oct 25, 2020 at 02:45:32PM +0100, John Wood wrote: > Attacks against vulnerable userspace applications with the purpose to break > ASLR or bypass canaries traditionaly use some level of brute force with the > help of the fork system call. This is possible since when creating a new > process using fork its memory contents are the same as those of the parent > process (the process that called the fork system call). So, the attacker > can test the memory infinite times to find the correct memory values or the > correct memory addresses without worrying about crashing the application. > > Based on the above scenario it would be nice to have this detected and > mitigated, and this is the goal of this patch serie. > > Other implementations > --------------------- > > The public version of grsecurity, as a summary, is based on the idea of > delay the fork system call if a child died due to a fatal error. This has > some issues: > > 1.- Bad practices: Add delays to the kernel is, in general, a bad idea. > > 2.- Weak points: This protection can be bypassed using two different > methods since it acts only when the fork is called after a child has > crashed. > > 2.1.- Bypass 1: So, it would still be possible for an attacker to fork > a big amount of children (in the order of thousands), then probe > all of them, and finally wait the protection time before repeat > the steps. > > 2.2.- Bypass 2: This method is based on the idea that the protection > doesn't act if the parent crashes. So, it would still be possible > for an attacker to fork a process and probe itself. Then, fork > the child process and probe itself again. This way, these steps > can be repeated infinite times without any mitigation. > > This implementation > ------------------- > > The main idea behind this implementation is to improve the existing ones > focusing on the weak points annotated before. The solution for the first > bypass method is to detect a fast crash rate instead of only one simple > crash. For the second bypass method the solution is to detect both the > crash of parent and child processes. Moreover, as a mitigation method it is > better to kill all the offending tasks involve in the attack instead of use > delays. > > So, the solution to the two bypass methods previously commented is to use > some statistical data shared across all the processes that can have the > same memory contents. Or in other words, a statistical data shared between > all the fork hierarchy processes after an execve system call. > > The purpose of these statistics is to compute the application crash period > in order to detect an attack. This crash period is the time between the > execve system call and the first fault or the time between two consecutives > faults, but this has a drawback. If an application crashes once quickly > from the execve system call or crashes twice in a short period of time for > some reason, a false positive attack will be triggered. To avoid this > scenario the shared statistical data holds a list of the i last crashes > timestamps and the application crash period is computed as follows: > > crash_period = (n_last_timestamp - n_minus_i_timestamp) / i; > > This ways, the size of the last crashes timestamps list allows to fine > tuning the detection sensibility. > > When this crash period falls under a certain threshold there is a clear > signal that something malicious is happening. Once detected, the mitigation > only kills the processes that share the same statistical data and so, all > the tasks that can have the same memory contents. This way, an attack is > rejected. > > 1.- Per system enabling: This feature can be enabled at build time using > the CONFIG_SECURITY_FORK_BRUTE option or using the visual config > application under the following menu: > > Security options ---> Fork brute force attack detection and mitigation > > 2.- Per process enabling/disabling: To allow that specific applications can > turn off or turn on the detection and mitigation of a fork brute force > attack when required, there are two new prctls. > > prctl(PR_SECURITY_FORK_BRUTE_ENABLE, 0, 0, 0, 0) > prctl(PR_SECURITY_FORK_BRUTE_DISABLE, 0, 0, 0, 0) > > 3.- Fine tuning: To customize the detection's sensibility there are two new > sysctl attributes that allow to set the last crashes timestamps list > size and the application crash period threshold (in milliseconds). Both > are accessible through the following files respectively. > > /proc/sys/kernel/brute/timestamps_list_size > /proc/sys/kernel/brute/crash_period_threshold > > The list size allows to avoid false positives due to crashes unrelated > with a real attack. The period threshold sets the time limit to detect > an attack. And, since a fork brute force attack will be detected if the > application crash period falls under this threshold, the higher this > value, the more sensitive the detection will be. > > So, knowing all this information I will explain now the different patches: > > The 1/8 patch defines a new LSM hook to get the fatal signal of a task. > This will be useful during the attack detection phase. > > The 2/8 patch defines a new LSM and manages the statistical data shared by > all the fork hierarchy processes. > > The 3/8 patch adds the sysctl attributes to fine tuning the detection. > > Patchs 4/8 and 5/8 detect and mitigate a fork brute force attack. > > Patch 6/8 adds the prctls to allow per process enabling/disabling. > > Patch 7/8 adds the documentation to explain this implementation. > > Patch 8/8 updates the maintainers file. > > This patch series is a task of the KSPP [1] and can also be accessed from > my github tree [2] in the "brute_v2" branch. > > [1] https://github.com/KSPP/linux/issues/39 > [2] https://github.com/johwood/linux/ > > The first version can be found in: > > https://lore.kernel.org/kernel-hardening/20200910202107.3799376-1-keescook@xxxxxxxxxxxx/ > > Changelog RFC -> v2 > ------------------- > - Rename this feature with a more appropiate name (Jann Horn, Kees Cook). > - Convert the code to an LSM (Kees Cook). > - Add locking to avoid data races (Jann Horn). > - Add a new LSM hook to get the fatal signal of a task (Jann Horn, Kees > Cook). > - Add the last crashes timestamps list to avoid false positives in the > attack detection (Jann Horn). > - Use "period" instead of "rate" (Jann Horn). > - Other minor changes suggested (Jann Horn, Kees Cook). > > John Wood (8): > security: Add LSM hook at the point where a task gets a fatal signal > security/brute: Define a LSM and manage statistical data > security/brute: Add sysctl attributes to allow detection fine tuning > security/brute: Detect a fork brute force attack > security/brute: Mitigate a fork brute force attack > security/brute: Add prctls to enable/disable the fork attack detection > Documentation: Add documentation for the Brute LSM > MAINTAINERS: Add a new entry for the Brute LSM > > Documentation/admin-guide/LSM/Brute.rst | 118 ++++ > Documentation/admin-guide/LSM/index.rst | 1 + > MAINTAINERS | 7 + > include/brute/brute.h | 16 + > include/linux/lsm_hook_defs.h | 1 + > include/linux/lsm_hooks.h | 4 + > include/linux/security.h | 4 + > include/uapi/linux/prctl.h | 4 + > kernel/signal.c | 1 + > kernel/sys.c | 8 + > security/Kconfig | 11 +- > security/Makefile | 4 + > security/brute/Kconfig | 13 + > security/brute/Makefile | 2 + > security/brute/brute.c | 749 ++++++++++++++++++++++++ > security/security.c | 5 + > 16 files changed, 943 insertions(+), 5 deletions(-) > create mode 100644 Documentation/admin-guide/LSM/Brute.rst > create mode 100644 include/brute/brute.h > create mode 100644 security/brute/Kconfig > create mode 100644 security/brute/Makefile > create mode 100644 security/brute/brute.c > > -- > 2.25.1 >