Re: [PATCH v2 0/8] Fork brute force attack mitigation

From: John Wood
Date: Fri Nov 06 2020 - 10:55:06 EST


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
>