Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
security/brute: Detect a brute force attack
For a correct management of a fork brute force attack it is necessary to
track all the information related to the application crashes. To do so,
use the extended attributes (xattr) of the executable files and define a
statistical data structure to hold all the necessary information shared
by all the fork hierarchy processes. This info is the number of crashes,
the last crash timestamp and the crash period's moving average.
The same can be achieved using a pointer to the fork hierarchy
statistical data held by the task_struct structure. But this has an
important drawback: a brute force attack that happens through the execve
system call losts the faults info since these statistics are freed when
the fork hierarchy disappears. Using this method makes not possible to
manage this attack type that can be successfully treated using extended
attributes.
Also, to avoid false positives during the attack detection it is
necessary to narrow the possible cases. So, only the following scenarios
are taken into account:
1.- Launching (fork()/exec()) a setuid/setgid process repeatedly until a
desirable memory layout is got (e.g. Stack Clash).
2.- Connecting to an exec()ing network daemon (e.g. xinetd) repeatedly
until a desirable memory layout is got (e.g. what CTFs do for simple
network service).
3.- Launching processes without exec() (e.g. Android Zygote) and
exposing state to attack a sibling.
4.- Connecting to a fork()ing network daemon (e.g. apache) repeatedly
until the previously shared memory layout of all the other children
is exposed (e.g. kind of related to HeartBleed).
In each case, a privilege boundary has been crossed:
Case 1: setuid/setgid process
Case 2: network to local
Case 3: privilege changes
Case 4: network to local
To mark that a privilege boundary has been crossed it is only necessary
to create a new stats for the executable file via the extended attribute
and only if it has no previous statistical data. This is done using four
different LSM hooks, one per privilege boundary:
setuid/setgid process --> bprm_creds_from_file hook (based on secureexec
flag).
network to local -------> socket_accept hook (taking into account only
external connections).
privilege changes ------> task_fix_setuid and task_fix_setgid hooks.
To detect a brute force attack it is necessary that the executable file
statistics be updated in every fatal crash and the most important data
to update is the application crash period. To do so, use the new
"task_fatal_signal" LSM hook added in a previous step.
The application crash period must be a value that is not prone to change
due to spurious data and follows the real crash period. So, to compute
it, the exponential moving average (EMA) is used.
Based on the updated statistics two different attacks can be handled. A
slow brute force attack that is detected if the maximum number of faults
per fork hierarchy is reached and a fast brute force attack that is
detected if the application crash period falls below a certain
threshold.
Moreover, only the signals delivered by the kernel are taken into
account with the exception of the SIGABRT signal since the latter is
used by glibc for stack canary, malloc, etc failures, which may indicate
that a mitigation has been triggered.
Signed-off-by: John Wood <john.wood@gmx.com>- Loading branch information