blog

git clone https://git.ce9e.org/blog.git

commit
5a95a78a8e733ab76417fbaa0d81de2506236331
parent
a650f40fc10f6b13745c9b61d681a5c97d2d7067
Author
Tobias Bengfort <tobias.bengfort@posteo.de>
Date
2024-06-24 06:15
add post on linux security mechanisms

Diffstat

A _content/posts/2024-06-23-linux-security-mechanisms/index.md 200 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

1 files changed, 200 insertions, 0 deletions


diff --git a/_content/posts/2024-06-23-linux-security-mechanisms/index.md b/_content/posts/2024-06-23-linux-security-mechanisms/index.md

@@ -0,0 +1,200 @@
   -1     1 ---
   -1     2 title: Tier list of Linux security mechanisms
   -1     3 date: 2024-06-23
   -1     4 tags: [code, linux, security]
   -1     5 description: Linux has quite some security mechanisms. So let's look at some of them and rate them by usability and power.
   -1     6 ---
   -1     7 
   -1     8 Linux has quite some security mechanisms. So let's look at some of them and
   -1     9 rate them by usability and power.
   -1    10 
   -1    11 ## File permissions
   -1    12 
   -1    13 Every file has read/write/execute permissions for its owner, group, and others.
   -1    14 This is usually expressed in octal: 755 means everyone can read and execute, but
   -1    15 only the owner can write. 600 means everyone is blocked but the owner can read
   -1    16 and write.
   -1    17 
   -1    18 This system is pretty old and has served us well. For example, home directories
   -1    19 are typically 700 to block access from other users. And system services can run
   -1    20 as separate users so they cannot change the system or access users' home
   -1    21 directories.
   -1    22 
   -1    23 File permissions are simple and powerful. They are a foundational tool for any
   -1    24 Linux user. However, they lack some of the flexibility of other items on the
   -1    25 list.
   -1    26 
   -1    27 A Tier
   -1    28 
   -1    29 ## Capabilities
   -1    30 
   -1    31 The root user has a lot of special permissions. For example, they can access
   -1    32 any file or bind ports below 1024. At some point, the Linux community decided
   -1    33 to divide this role into
   -1    34 [Capabilities](https://www.man7.org/linux/man-pages/man7/capabilities.7.html)
   -1    35 to allow more granular access control.
   -1    36 
   -1    37 However, the list of Capabilities is long and complicated. Regular users will
   -1    38 hardly be able to understand which capabilities a process needs. Some
   -1    39 Capabilities even allow [privilege
   -1    40 escalations](https://book.hacktricks.xyz/linux-hardening/privilege-escalation/linux-capabilities).
   -1    41 
   -1    42 Docker by default runs containers as root, but [drops most
   -1    43 capabilities](https://docs.docker.com/engine/security/#linux-kernel-capabilities).
   -1    44 Running with a limited set of capabilities is better than running as root. But
   -1    45 in practice, you rarely even need any capabilities. Just running as a regular
   -1    46 user will work 99% of the time.
   -1    47 
   -1    48 B Tier
   -1    49 
   -1    50 ## seccomp
   -1    51 
   -1    52 [seccomp](https://www.kernel.org/doc/html/latest/userspace-api/seccomp_filter.html)
   -1    53 allows to filter which syscalls a process has access to. For me, this has much
   -1    54 the same pros and cons as Capabilities: The list of syscalls is just too long
   -1    55 and complicated.
   -1    56 
   -1    57 On top of that, creating a seccomp filter is also complicated. bwrap wants a
   -1    58 [compiled cBPF program](https://www.man7.org/linux/man-pages/man3/seccomp_export_bpf.3.html).
   -1    59 Docker will take a [JSON seccomp profile](https://docs.docker.com/engine/security/seccomp/).
   -1    60 Systemd has probably the most usable interface by providing presets like
   -1    61 `@system-service`.
   -1    62 
   -1    63 B Tier
   -1    64 
   -1    65 ## No new privileges
   -1    66 
   -1    67 [`PR_SET_NO_NEW_PRIVS`](https://docs.kernel.org/userspace-api/no_new_privs.html)
   -1    68 blocks setuid (e.g. sudo) and a bunch of other privilege escalations. Highly
   -1    69 recommended.
   -1    70 
   -1    71 bwrap uses it unconditionally, in systemd it is [implied by a bunch of
   -1    72 settings](https://www.freedesktop.org/software/systemd/man/latest/systemd.exec.html#NoNewPrivileges=),
   -1    73 and Docker has an [option to enable
   -1    74 it](https://docs.docker.com/reference/cli/docker/container/run/#security-opt).
   -1    75 
   -1    76 S Tier
   -1    77 
   -1    78 ## AppArmor / SELinux
   -1    79 
   -1    80 These are effectively file permissions on steroids. Where file permissions only
   -1    81 allow you to assign permissions for owner and group, these allow you to assign
   -1    82 permissions for every binary individually. This means that every application
   -1    83 can come with a specific AppArmor / SELinux profile that exactly lists the
   -1    84 files it needs access to.
   -1    85 
   -1    86 My impression is that very few applications come with AppArmor or SELinux
   -1    87 profiles. Writing them is cumbersome, especially if they are not maintained
   -1    88 along with the application itself.
   -1    89 
   -1    90 I don't think these mechanisms are actively harmful. Maybe I am too harsh, but
   -1    91 given the alternatives we will discuss later, I don't see any reason to use
   -1    92 them.
   -1    93 
   -1    94 C Tier
   -1    95 
   -1    96 ## cgroups
   -1    97 
   -1    98 So far we mainly looked at mechanisms to restrict file access and syscalls.
   -1    99 [Control Groups](https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v2.html)
   -1   100 allow to restrict system resources (mostly CPU and memory). This is what
   -1   101 resource control in systemd and Docker is build upon.
   -1   102 
   -1   103 cgroups are a useful mechanism for servers, especially if you rent out
   -1   104 computing time to others. For single users systems, they are much less
   -1   105 relevant.
   -1   106 
   -1   107 B Tier
   -1   108 
   -1   109 ## Namespaces
   -1   110 
   -1   111 [Namespaces](https://www.man7.org/linux/man-pages/man7/namespaces.7.html) have
   -1   112 fueled the container revolution of the past years, including Docker and
   -1   113 Flatpak. Network and PID namespaces are useful, but the real star is mount
   -1   114 namespaces, which  allows to construct a separate file hierarchy for each
   -1   115 process.
   -1   116 
   -1   117 You can use this mechanism a lot like AppArmor / SELinux, but instead of
   -1   118 blocking access to a file, you just don't include it in the hierarchy. In that
   -1   119 case you still have to maintain the list of files that should be made
   -1   120 available, which is quite complex to get right.
   -1   121 
   -1   122 The other option is to use a completely separate file hierarchy that only
   -1   123 shares some select data folders with the host system. This is easier, but also
   -1   124 results in many redundant and potentially unpatched directory trees.
   -1   125 
   -1   126 Despite the downsides, I really like how powerful this mechanism is while also
   -1   127 being quite intuitive.
   -1   128 
   -1   129 A Tier
   -1   130 
   -1   131 ## Landlock
   -1   132 
   -1   133 Landlock is yet another way to limit access to files, and was only added to the
   -1   134 kernel in 5.13.
   -1   135 
   -1   136 While it could be used to sandbox applications, I think we already have more
   -1   137 than enough mechanisms for that (AppArmor, SELinux, mount namespaces). However,
   -1   138 it could be interesting as a mechanism for processes to restrict themselves.
   -1   139 Landlock was actually modelled after a BSD mechanism called `pledge`, as in "I
   -1   140 pledge to not ever access those files".
   -1   141 
   -1   142 C Tier
   -1   143 
   -1   144 ## polkit
   -1   145 
   -1   146 A trend in recent years is to have services that can perform privileged
   -1   147 actions, so that applications can talk to those services over dbus instead of
   -1   148 having to perform the privileged actions themselves. On its own, this is just a
   -1   149 security bypass. But the services in turn ask polkit whether an action should
   -1   150 be allowed. polkit will then consult its configuration and either allow the
   -1   151 request, deny the request, or ask the user to authorize the request by entering
   -1   152 their password.
   -1   153 
   -1   154 Polkit gives instant privilege escalation while having a voluptuous attack
   -1   155 surface. That doesn't mean that it is insecure. But if I wanted to attack a
   -1   156 Linux desktop system, this is where I would start.
   -1   157 
   -1   158 Proponents of polkit argue that it gives much more flexibility. But polkit
   -1   159 rules decide requests mainly based on group membership. I cannot see how
   -1   160 polkit should make nuanced decisions based on this limited information.
   -1   161 
   -1   162 The main benefit or polkit is that it allows to get the user into the loop.
   -1   163 There is a good idea somewhere in here. But the current implementation is not
   -1   164 that.
   -1   165 
   -1   166 Unfortunately, polkit is a central part of most modern Linux desktops. I wish
   -1   167 we had something else, but for now we are stuck with it.
   -1   168 
   -1   169 D Tier
   -1   170 
   -1   171 ## xdg-dbus-proxy
   -1   172 
   -1   173 The Flatpak project realized that polkit is not sufficient and came up with an
   -1   174 additional mechanism: They build
   -1   175 [xdg-dbus-proxy](https://github.com/flatpak/xdg-dbus-proxy), a dbus proxy that
   -1   176 filters which services are available. They then mount the proxy instead of the
   -1   177 original socket in their mount namespace.
   -1   178 
   -1   179 (Aside: This would not be necessary if dbus would use a separate socket for
   -1   180 each service. Then you could use mount namespaces directly without a need for a
   -1   181 proxy.)
   -1   182 
   -1   183 As far as I understand, they do not do much work on this project because they
   -1   184 want to [move this functionality into dbus
   -1   185 itself](https://gitlab.freedesktop.org/dbus/dbus/-/issues/171). However, the
   -1   186 ticket was created in 2017 and there has not been much progress. So I am not
   -1   187 really sure about the status.
   -1   188 
   -1   189 C Tier
   -1   190 
   -1   191 ## Summary
   -1   192 
   -1   193 There you have it, this is my ranking of linux security mechanisms:
   -1   194 
   -1   195 -	S Tier: No new privileges (great!)
   -1   196 -	A Tier: File permissions, Namespaces (tools for everyday use)
   -1   197 -	B Tier: Capabilities, seccomp, cgroups (only for select occasions)
   -1   198 -	C Tier: AppArmor / SELinux, Landlock, xdg-dbus-proxy (better options are available)
   -1   199 -	D Tier: polkit (I would like to see this one replaced)
   -1   200 -	F Tier: -