Firejail no-exec

This commit is contained in:
Camille Mougey
2024-10-03 10:29:10 +02:00
parent 66c61d0c18
commit ff8a03a326
4 changed files with 79 additions and 0 deletions
+1
View File
@@ -8,3 +8,4 @@ Repository of various experiments / PoC.
* [VDM](windows-defender/VDM): Windows Defender's VDM Format (signatures database)
* [Primary Group ID](windows/random_things/primaryGroupID): Analysis of security checks made on `primaryGroupID` AD attribute changes
* [Unpacking with Windows Defender](windows-defender/unpacking): Re-using the unpackers built into Windows Defender
* [Firejail no-execve](firejail/no-exec): Illustration of an issue when filtering the `execve` syscall for a target binary
+7
View File
@@ -0,0 +1,7 @@
all: link.o hello hello-static exec exec-static
exec: exec.c
gcc exec.c -o exec
exec-static: exec.c
gcc exec.c -o exec-static -static
+59
View File
@@ -0,0 +1,59 @@
# Sec-comping execve
## Context
`firejail`, `systemd-exec`, and similar programs provide the ability to sandbox executables. This sandboxing includes the setup of `seccomp` filters to limit certain syscalls.
To apply these syscall limitations, these programs must call `seccomp` to install the filters before invoking `execve`. If the executable loader (executed after `execve`) requires syscalls that have been previously denied, the programs will be unable to load the executable.
Some strategies have been proposed to bypass this issue. For example, `firejail` [uses](https://github.com/netblue30/firejail/blob/master/src/firejail/fs_trace.c#L105) [a custom *ld preload library*](https://github.com/netblue30/firejail/blob/master/src/libpostexecseccomp/libpostexecseccomp.c) to install some filters at loading time, delaying their application until after the call to `execve`.
## The Problem
An attentive reader might ask: what if the *ld preload library* is not honored, for instance when a static executable is used?
Well, there is no magic. For instance, `firejail` will happily launch the executable without installing the `seccomp`'s `execve` filter.
By compiling [exec.c](./exec.c) (a `ls` wrapper) as both dynamic and static, one can test this behavior:
```bash
# Compile the executables
$ make exec
$ make exec-static
# Launch the dynamic version, seccomping execve
$ firejail --noprofile --shell=none --seccomp=execve ./exec
Seccomp list in: execve, check list: @default-keep, postlist: execve
Parent pid 6606, child pid 6607
Seccomp list in: execve, check list: @default-keep, postlist: execve
Post-exec seccomp protector enabled
Child process initialized in 10.66 ms
execve: Operation not permitted
Parent is shutting down, bye...
# Launch the static version, where even execve is forgiven, `ls` will be launched
$ firejail --noprofile --shell=none --seccomp=execve ./exec-static
Seccomp list in: execve, check list: @default-keep, postlist: execve
Parent pid 6617, child pid 6618
Seccomp list in: execve, check list: @default-keep, postlist: execve
Post-exec seccomp protector enabled
Child process initialized in 10.52 ms
bin boot core dev etc home lib lib32 lib64 lost+found media mnt proc root run sbin sys tmp usr var vmlinuz
Parent is shutting down, bye...
```
For more information, this issue is explained in detail on the official repository [^firejail], including a similar problem related to `prctl` and additional issues concerning the use of a custom *ld preload library* (mainly the need to delay filtering of other syscalls, such as `mmap`, `open`, etc., which could be problematic).
## Discussing a Solution
To the best of my knowledge, there are no easy solutions:
- Removing the ability to seccomp `execve` in sandboxing wrappers like `firejail` in some cases, as this could mislead users into thinking that `execve` will be blocked when it is not. This resembles what `systemd-exec` mention in its documentation[^systemd]:
> Note that strict system call filters may impact execution and error handling code paths of the service invocation. Specifically, access to the execve() system call is required for the execution of the service binary — if it is blocked service invocation will necessarily fail
- Adding a possibility to delay the application of `seccomp` filters in the kernel.
This last possibility has been discussed on the kernel list[^kernel], with answers by people far more knowledgeable than I. Also, some workarounds using `ptrace` or `seccomp-fd` have been proposed.
[^firejail]: https://github.com/netblue30/firejail/issues/3685
[^kernel]: https://lore.kernel.org/all/202010281500.855B950FE@keescook/T/
[^systemd]: https://www.freedesktop.org/software/systemd/man/systemd.exec.html
+12
View File
@@ -0,0 +1,12 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main() {
char *newargv[] = { "/bin/ls", "/", NULL };
char *newenviron[] = { NULL };
execve("/bin/ls", newargv, newenviron);
perror("execve"); /* execve() returns only on error */
exit(EXIT_FAILURE);
}