Files
TripleCross/docs/chapters/chapter6.tex
2022-06-23 14:20:32 -04:00

372 lines
25 KiB
TeX

\chapter{Related work} \label{chapter:related_work}
% Comparison of the rootkit with other eBPF and non eBPF rootkits.
In this work, we have developed a rootkit that loads itself in the kernel
and incorporates network-level capabilities and other functionalities both
at user and kernel space. Although eBPF, the technology used for this
rootkit, has been rarely explored before, some of the techniques presented
here are equivalent (or mimic) those historically incorporated in classic
rootkits, while others are also inspired by malicious uses of eBPF explored
in recent research.
In this chapter, we provide a comprehensive review of previous
work on UNIX/Linux rootkits, their main types and most relevant examples.
We also offer a comparison in terms of techniques and functionality with
previous families. In particular, we highlight the differences of our
eBPF rootkit with respect to others that rely on traditional methods,
and also to those already built using eBPF.
\section{User-mode rootkits}
As discussed in Section \ref{section:motivation}, user-mode rootkits
are those that are run at the same level as common user applications. They
do not require to be loaded in the kernel to tamper with the execution of
programs. Instead, they usually redirect or substitute common system
programs to achieve their malicious purposes.
The most popular and commonly found technique in user-mode rootkits is the
LD\_PRELOAD technique, which enables to redefine function calls at shared
libraries. LD\_PRELOAD is an environment variable interpreted by the
dynamic linker at runtime that indicates to preload a shared library
before those already indicated at the ELF file \cite{ldpreload_pros}. If
this preloaded library implements the same function as some other library,
then the preloaded function overrides the original. This means that a
rootkit may define functions with malicious functionality that will run in
any program that loads the library instead of that from the original
function, without the need of modifying any of these programs.
This type of rootkits are considered trivial to detect by an investigator,
however they are easy to write and their capabilities can be quickly
extended, which has motivated the creation of many LD\_PRELOAD rootkits.
\subsection{Jynx/Jynx2} Jynx \cite{jynx_github} is one of the most
well-known rootkits using the LD\_PRELOAD technique. It injects the name of
its malicious library into the file \textit{/etc/ld.so.preload}, which acts
similarly to defining the LD\_PRELOAD environment variable for each
executable, but instead applying this setting to any program (since every
program checks this file to know the libraries to preload)
\cite{ldpreload_so_jynx}.
Its first version, Jynx, was best known for implementing a backdoor by
hooking the socket function accept() \cite{ldpreload_pros_2327}. This
function, responsible of accepting a connection, was defined in a preloaded
malicious library so that any connection (specifically encrypted ones)
could be checked to come from a remote attacker. If that is the case, the
rootkit would accept and establish a connection, and then execute a remote
root shell which provided the attacker with remote access.
In its later version, Jynx2 \cite{jynx2_github}, the rootkit incorporated
other mechanisms focused on hiding the rootkit activity
\cite{jynx2_infosecinstitute}. This included hiding Jynx's connections by
hooking read calls at the \textit{/proc} filesystem (which we covered in
Section \ref{section:proc_filesystem} so that processes related with the
rootkit activity remain undisclosed. Other functionalities include file
hiding, privilege escalation, or multi-factor authentication in the rootkit
backdoor.
\subsection{Azazel}
Azazel is another LD\_PRELOAD rootkit originally based on Jynx and that
extends its functionalities in multiple areas, including additional
anti-debugging and anti-detection techniques. This rootkit incorporates
more hooked functions into its preloaded library to achieve capabilities
such as:
\begin{itemize}
\item Avoid detection by programs such as \textit{ldd} (which lists
libraries to be loaded in an executable), \textit{ps} (which lists
processes) or \textit{lsof} (that displays opened files by processes).
\item Hide rootkit files and processes.
\item Hide rootkit-related network connections.
\item Incorporate backdoors (one launching an encrypted connection, another in plaintext).
\item Clean logs and allow for local privilege escalation.
\item Anti-debugging, by means of hooking ptrace() calls.
\end{itemize}
\subsection{TripleCross comparison}
Jynx---and, especially, Azazel---are advanced rootkits with many
functionalities, but they are restricted both because of the LD\_PRELOAD
technique and because of working from the user space.
%
In particular, the use of LD\_PRELOAD in a program can be detected by the
\textit{export} command and removed via \textit{unset}
\cite{ld_preload_detect}. In addition, this technique does not work on
statically-linked programs, that is, those where the calls to libraries
and exported functions are resolved at compile time \cite{ldpreload_pros}.
On the other hand, because they only have access to user-space programs and
components, their activities can be more easily detected than a rootkit
working from inside the kernel.
Since TripleCross is composed of both a kernel-side component (the eBPF
programs at the kernel) and a user-side component (the rootkit user program
that communicates with eBPF), the capabilities of user-mode rootkits are
more limited than those that could be eventually implemented in
TripleCross, yet they are easier and faster to implement, and do not
require loading an eBPF program in the kernel, an event which is likely to
be logged by EDRs and IDSs.
With respect to the capabilities offered, the ability to hook function
calls by preloading libraries so that malicious code is run can be
considered analogous to eBPF tracepoint, kprobe, and uprobes programs. On
the one hand, eBPF can modify parameters and execute kernel code
transparently from user programs. On the other hand, user-mode
rootkits may execute any instruction on the preloaded libraries, but eBPF
is restricted to a certain range of operations and those offered by eBPF
helpers. Nevertheless, both types of rootkits are able to implement the key
features needed for a usual rootkit, including a backdoor and a C2 system,
in addition to the basic stealth mechanisms.
\section{Kernel-mode rootkits}
As described in Section \ref{section:motivation}, kernel-mode
rootkits are run at the same level of privilege as the operating system,
thus enjoying unrestricted access in both the kernel- and user-space. These
are the hardest and riskiest to develop (since they need to work with
kernel structures and any error could cause a kernel panic), yet the offer
the richest and most powerful variety of functionalities. Also, they mostly
remain hidden from the user space, thus boosting their stealth, while at
the same time they are capable of further hiding their activities thanks
to their capabilities at both the user- and kernel-space.
Historically, kernel-mode rootkits in UNIX systems have been built as
Loadable Kernel Modules (LKM), whose original purpose is to expand the
capabilities of the kernel by adding new modules for specific tasks without
the need of recompiling or even reloading the kernel.
\subsection{SucKIT rootkit}
Although the great majority of kernel-mode rootkits are loaded as LKMs,
SucKIT \cite{suckit_rootkit} remains one of the exceptions to this rule.
This old rootkit uses the \textit{/dev/kmem} special file \cite{dev_kmem}
for directly accessing kernel memory, including both reading and writing.
This means that the rootkit could potentially find and overwrite key data
at the kernel \cite{suckit_lasamhna}.
Nowadays, this type of rootkit is not relevant except for historical
reasons, since distributions such as Debian have limited access to this file to
kernels compiled with the CONFIG\_DEVKMEM parameter \cite{dev_kmem_debian}
which is disabled by default \cite{dev_kmem_off_default}.
\subsection{Diamorphine}
Diamorphine \cite{diamorphine_github} is one of the best known kernel-mode
rootkits, and it is implemented as a LKM. This type of rootkits commonly
intercept and hook system calls from the kernel, executing malicious code
(together with the original function) with the aim of achieving different
malicious purposes.
When a system call takes place in the user space, an interrupt is issued to
the kernel, which checks the type of syscall that has been issued. This is
done using a syscall table, which relates each system call to the function
at the kernel where its implementation is stored. A common technique by
LKMs is to modify the syscall table, so that it points to the functions
implemented by the LKM, where the malicious code will be executed
\cite{incibe_rootkit_lkm}. This code may be a modified version of the
original (e.g.: a sys\_getdents64 call that lists files but hides those
belonging to the rootkit) or modify kernel and user data received at the
hooked function.
Because LKMs are run directly inside the kernel, they are not limitied and thus
they can read, write and allocate kernel and user memory freely. It is also
possible to hook and modify data at internal kernel functions by means of,
for instance, kprobe programs.
In the case of Diamorphine, it uses the aforementioned capabilities to hide
processes, provide local privilege escalation, hide files and directories
and implement a messaging protocol using system calls (it enables a
malicious user to locally communicate actions to the rootkit with
\textit{kill} signals). Most importantly, it hides itself from commands
such as \textit{lsmod}, which list the LKMs loaded into the kernel, thus
turning invisible.
\subsection{Reptile}
Reptile \cite{reptile_github} is another LKM rootkit which incorporates
advanced stealth and network functionalities. Some of its most relevant
capabilities include:
\begin{itemize}
\item Hiding files, directories, processes and network connections related to the rootkit activity.
\item A backdoor that is operated via port-knocking triggers (which we explained in Section \ref{subsection:triggers}).
\item C2 capabilities via a custom shell (similar to the pseudo-shells of our rootkit).
\end{itemize}
\subsection{TripleCross comparison}
Although TripleCross incorporates many of the techniques mentioned in
Reptile and Diamorphine (backdooring, modification of files and directories
or local privilege escalation) these capabilities are achieved using
workarounds for the limitations of eBPF programs, namely not having write
access in kernel memory. For instance, Reptile can grant root privileges to
any program by overwriting the kernel data structure storing the user
privileges, whilst this is not achievable for TripleCross, which has to
take advantage of user buffers when reading the \textit{/etc/sudoers}
file.
Therefore, LKMs are more powerful since they enjoy almost no restrictions
in the kernel, while TripleCross' modules will always be limited to those
capabilities achievable without kernel memory modifications. In terms of
developing complexity, LKMs are more difficult to develop, since eBPF
programs will never crash the kernel (because of the eBPF verifier), whilst
developing kernel modules may incur in causing kernel panics, often because
of tiny kernel differences between kernel versions, which leads to having
to adjust the LKM for multiple kernels. On the other hand, although an eBPF
program is guaranteed to work once in the kernel, it requires deep
knowledge of which actions are accepted by the verifier, and about which
are the limitations of these programs.
With respect to the techniques used we can also find similarities, since
both LKMs and eBPF rootkits make heavy use of hooking syscalls and kernel
functions, with the only difference that the instructions that can be
executed at the eBPF probe function are restricted to those allowed by
the eBPF helpers, whilst LKMs may read or write any memory section. In
terms of network-related functions, both eBPF and LKMs enjoy similar
capabilities, with the exception that LKMs may create their own packets,
whilst eBPF may only modify or drop existing ones. Finally, both LKMs and
eBPF rootkits may execute user space programs (in eBPF, by hijacking calls
or triggering actions via a messaging system such as a ring buffer, and in
LKMs using, for instance, the function call\_usermodehelper
\cite{usermode_helper_lkm}).
\section{eBPF rootkits}
Although eBPF is loaded at the kernel like kernel-mode rootkits, we will
analyze this type of rootkits separately given their novelty and the
difference of their capabilities with classic LKMs.
Most research work on the offensive capabilities of eBPF has been conducted
in recent years, while the first publicly-released eBPF-only rootkit dates
from 2021. The work on this matter by Jeff Dileo and Andy Olsen from NCC
Group appeared first in 2018 at the 35th Chaos Communication Congress
(35C3) \cite{god_ebpf}, and later by Jeff Dileo at DEFCON 27 (2019)
\cite{evil_ebpf}. These works remain one of the first efforts to explore
the capabilities of eBPF applied to computer security. Between others
advancements, the capabilities of eBPF helpers, such as
bpf\_probe\_write\_user() or the possibility of hooking and modifying
syscalls, were first discussed in the CCC presentation. On the other
hand, the work presented at DEFCON 27 introduces the ROP technique for
achieving library injection, which we have discussed in Section
\ref{subsection:rop_ebpf}. NCC Group has made publicly available a set of
programs developed in BCC showing a proof of concept for this technique
\cite{evil_ebpf_github}.
In 2021, the work of Pat Hogan presented at DEFCON 29 \cite{bad_ebpf}
further elaborates on the offensive capabilities of eBPF both in the
network and at the user space. Specifically, the possibilities of eBPF
network programs as backdoors with C2 functionality are discussed, together
with the capabilities of eBPF to modify data read from critical files, such
as \textit{/etc/sudoers}. Although not a rootkit by itself, Hogan released
a set of tools that demonstrate some of these capabilities
\cite{bad_ebpf_github}, including local privilege escalation, hiding
processes, or replacing the content of files.
\subsection{Ebpfkit}
Ebpfkit is the first publicly released rootkit fully developed using eBPF.
It was presented in 2021at DEFCON 29 by Guillaume Fournier and Sylvain Afchain from
Datadog \cite{ebpf_friends}, and it is also available at
GitHub \cite{ebpf_friends_github}. The same rootkit was also presented at
BlackHat 2021 with some additional functionalities
\cite{ebpf_friends_blackhat}. This rootkit uses the Go version of the
libbpf library.
The work of Fournier and Afchainte is developed around the three
fundamental pillars on which eBPF programs operate: the network, the user
space and the kernel space.
\begin{itemize}
\item In the network, ebpfkit incorporates the first eBPF backdoor with C2 capabilities powered by an XDP and TC program. It presents for the first time the TCP retransmissions technique we explained in Section \ref{subsection:tcp} for sending new packets from the backdoor. It also incorporates a network scanning functionality based on this technique.
\item In the kernel space, ebpfkit incorporates hooks at open and read syscalls, with the purpose of hiding the rootkit (such as hiding the PID at the proc filesystem) or adding custom ssh keys when the keys file is read by the sshd process. Most importantly, it incorporates the first technique to hide the warning log messages shown in the kernel log buffer, which we mentioned in Section \ref{subsection:bpf_probe_write_apps}. This technique works by hooking sys\_read calls during the attachment process, during which the eBPF program will indicate the kernel that nothing is available to be read from the buffer by means of bpf\_override\_return(), followed by overwritting the warning messages using bpf\_probe\_write\_user().
\item At user space, ebpfkit incorporates multiple techniques to target specific versions of common software by hooking their function calls using uprobes and modifying its arguments. An example of this is bypassing the protection of Runtime Application Self Protection (RASP) software \cite{rasps}, which are programs oriented towards monitoring the data in a program to prevent malicious data input by an attacker, so that a SQL injection attack \cite{sql_injection} could take place.
\end{itemize}
\subsection{Boopkit}
After the creation of ebpfkit and during 2022, the computer security
community has contributed to the creation of more eBPF rootkits, being
Boopkit one of the best known, created by Kris Nóva and available publicly
on GitHub \cite{boopkit}.
Boopkit incorporates a network backdoor which can be operated via a remote
boopkit-boop remote client. This backdoor incorporates C2 capabilities that
enable to spawn a reverse shell and execute commands remotely. Also, the
backdoor listens for 'Boop-Vectors', backdoor triggers consisting of either
TCP packets with bad calculated checksums or TCP packets with the RST and
ACK flags activated.
Note that Boopkit is younger than TripleCross and thus it takes no
inspiration on this project.
\subsection{Rootkits in the wild}
Most rootkits found to be actively being used to infect machines are not
completely eBPF-based, but rather incorporate eBPF programs for particular
modules of the rootkit, usually the network. This the case of rootkits
Bvp47 (on which as we mentioned we based our design of one backdoor
trigger) \cite{bvp47_report_p49} and BPFDoor, a rootkit that was discovered
by PwC to be targeting telecommunication companies at Asia and Middle East
\cite{bpfdoor_pwc}. Both rootkits were found to incorporate eBPF for
implementing a network backdoor and supporing C2 operations.
Because eBPF XDP programs allow for hiding network communications and
hooking packets before they are even received at the kernel (and LKMs
cannot access XDP), this type of rootkits with eBPF backdoors are a growing
tendency. For instance, in June 2022, a new Linux rootkit named Symbiote
discovered by Blackberry was found to combine the LD\_PRELOAD technique
with a eBPF backdoor \cite{symbiote}.
\subsection{TripleCross comparison}
Although ebpfkit and boopkit are the only major eBPF rootkits publicly
available, the capabilities incorporated into them, together with those
described by Jeff Dileo and Pat Hogan compound a great range of possible
functionalities for eBPF rootkits, and TripleCross development has been
greatly inspired by this past work. In particular, there exist the
following similarities:
\begin{itemize}
\item The backdoor module and C2 capabilities are based on those presented by ebpfkit, since both rootkits use a combination of XDP and TC programs (for managing incoming and outgoing traffic respectively). The phantom shell of TripleCross is also based on the TCP retransmissions technique of ebpfkit. With respect to backdoor triggers, these were based on the Bvp47 and Hive rootkits, as we mentioned in Section \ref{subsection:triggers}.
\item The privilege escalation module is based on the file sys\_read syscalls modification presented by Pat Hogan, which describes its possibilities for obtaining sudo privileges by modifying data read from the \textit{/etc/sudoers} file. Also, the execution hijacking process is based on the capability of modifying sys\_execve described by Hogan.
\item The stack scanning technique used by the library injection module is based on that presented for the ROP attack by Jeff Dileo.
\item The files and directories hiding technique is a common functionality incorporated at rootkits, although it was first discussed by Johann Rehberger \cite{embracethered_getdents}.
\end{itemize}
On the other hand, TripleCross incorporates new features, and builds new capabilities on top of those techniques in which as we mentioned it is inspired:
\begin{itemize}
\item The backdoor in TripleCross is the first incorporating the possibility of managing multi-packet triggers, apart from featuring a novel C2 system with stealth in mind and on which actions are not hardcoded values nor they need to be inserted in the TCP payload field (they can be hidden at the headers). Also, it features encrypted shell connections for the first time, disguising the malicious traffic with from common applications, together with the other three types of shells implemented. Finally, the new RawTCP\_Lib library allows the C2 system to incorporate its own protocol without the need of supplementary network traffic (like 3-way TCP handshakes) between other purposes, thus reducing the network noise.
It must also be noted that, although the ability to modify outgoing traffic and to duplicate packets using retransmissions is incorporated in ebpfkit, TripleCross remains as the only other rootkit to implement this functionality.
\item The library injection module not only presents an alternative technique to scan scanning presented by Jeff Dileo but also incorporates the possibility of performing GOT hijacking for the first time with the support of an eBPF program. Overwriting GOT is a well-known technique (and frequently used before the incorporation of RELRO), but TripleCross revives it to demonstrate the capabilities of eBPF at the user space.
\item The privilege escalation module mostly uses the same technique as Hogan, but it incorporates some improvements so that it also enables to work with \textit{/etc/sudoers} files which already have a sudo entry at that file.
\item The execution hijacking module just takes as a basis that the sys\_execve call could be hijacked, proceeding to build the module on top of that idea. Specifically, new research into the cases on which this substitution fails has been made (e.g.: page faults), together with the argument hiding and malicious program in charge of manipulating the hijacked calls so that it executes both the original program and malicious code.
\item The rootkit persistence module uses cron, which is widely known for rootkit development, however it is the first eBPF rootkit to incorporate it. On the other hand, hiding files and directories is one of the best known techniques in rootkits so it was the only module leaving little possibilities for innovation.
\item TripleCross in general has been designed and implemented to be as modular as possible, therefore its eBPF program configurator and multi-purpose events sent via the ring buffer compound another relevant feature.
\end{itemize}
In summary, TripleCross offers new techniques and modifies others presented in previous research work, while at the same time takes as a basis both well-known techniques in rootkit development and also those already presented in previous eBPF rootkits which are key for certain functionalities, such as ebpfkit's TCP retransmissions for duplicating packets.
\section{Rootkit features comparison}
This chapter compares the overall features and capabilities of the rootkits described in this chapter. Table \ref{table:rootkit_comparison} shows this comparison.
\newgeometry{hmargin=3cm,vmargin=2cm}
\thispagestyle{lscape}
\begin{landscape}
\begin{table}[htbp]
\begin{tabular}{|>{\centering\arraybackslash}p{3cm}|>{\centering\arraybackslash}p{3cm}|>{\centering\arraybackslash}p{3cm}|>{\centering\arraybackslash}p{3cm}|>{\centering\arraybackslash}p{3cm}|>{\centering\arraybackslash}p{3cm}|>{\centering\arraybackslash}p{3cm}|>{\centering\arraybackslash}p{3cm}|}
\hline
\textbf{ROOTKIT AND TYPE} & \textbf{BACKDOOR \& C2} & \textbf{CODE EXECUTION} & \textbf{DATA MANIPULATION} & \textbf{STEALTH} & \textbf{PRIVILEGE ESCALATION} & \textbf{PERSISTENCE}\\
\hline
\hline
Jynx2 (LD\_PRELOAD) & accept() hijacking & LD\_PRELOAD & User space & Files hiding. Process hiding. & Yes & No\\
\hline
Azazel (LD\_PRELOAD) & accept() hijacking & LD\_PRELOAD & User space & Files hiding. Process hiding. & Yes & No\\
\hline
SucKIT (/dev/kmem) & Magic packet trigger & Syscall table hijack with /dev/kmem & User and kernel space & No & No & /sbin/init hijack\\
\hline
Diamorphine (LKM) & Local, via kill signals & At kernel Kprobes & Kernel space (kprobes) & Files hiding. LKM hiding. & Yes & No\\
\hline
Reptile (LKM) & Port-knocking & At kernel Kprobes & User space (files) and kernel space (kprobes) & Files hiding. LKM hiding. Process hiding. & Yes & Yes\\
\hline
Ebpfkit (eBPF) & Port filtering. Data exfiltration. Network scans. & At eBPF programs only & User space (files, uprobes) Kernel space (kprobes) & BPF hiding. Files hiding. & No & Init system\\
\hline
boopkit (eBPF) & Command execution. Boop vectors. Remote shell. & User program and eBPF programs. & No & BPF process hiding. & No & No\\
\hline
TripleCross (eBPF) & Command execution. Pattern \& Multi packet trigger. Remote shells. & User and eBPF programs. Library injection and execution hijacking. & User space (files, uprobes) Kernel space (tracepoints). & Files hiding. Packet payload hiding. & Yes & Cron and sudo\\
\hline
\end{tabular}
\caption{Overall rootkit features comparison.}
\label{table:rootkit_comparison}
\end{table}
\end{landscape}
\restoregeometry