Any code execution inside of a SUID binary basically becomes root access. That means that SUID binaries need a lot of security measures for everything they do. The more complex you make your SUID capable binary, the more work this adds, and the higher the probability that you’re introducing some kind of bypass vulnerability.
With sudo and to some extent doas, the process that should be in charge of vetting whether or not a user can become root/another user (and probably should only be doing that) is also parsing files, interacting with the network, possibly doing I/O on the filesystem. The binary is started as a user with limited permissions, but that user has full control of the binary’s environment.
With a root daemon (the one your system already needs if you’re running systemd in the first place), the binary that submits the elevation request can be as small as possible, and have no additional permissions. You can trick run0 into doing something, but that won’t give you root access, as polkit and other mechanisms actually decide if you’re root or not. If you’re not root, you’re not going to be able to seriously influence those daemons, even if you debug and monitor the memory of the application that’s communicating with them, or somehow manage to LD_PRELOAD some malware into it.
Take, for instance, CVE-2023–22809. This vulnerability allowed some users to write files with root permissions (think /etc/sudoers) when the low privilege user was permitted to only edit files on a whitelist, because rather than taking the root user environment variables, various sudo tools accepted the user’s environment variables (the ones you provide on the command line) to decide what editor to launch. This editor could (basically) be ‘nano /etc/passwd’ and when you sudoedit /etc/user/tool/file/here.conf (as specified in sido’s config), sudoedit would spawn an editor opening /etc/passwd instead.
In the daemon model of run0, the daemon would be the one evaluating its (root) environment variables and picking the editor. However, in sudo, the binary that allowed itself to become root, could also be directly influenced by the low privilege user, and its protections against tampering proved insufficient.
This entire class of attacks just isn’t viable when the binary the end user runs doesn’t have the ability to exert any control. All the important bits are on the “other side”, running as a different user, isolated from the low privilege side.
Thanks for taking the time to explain. I was trying to get my head around on how this works but could not understand much of it. A lot of people here are very much against systemd in all senses, but this sounds like a better approach. Even if it not done as systemd, makes more sense than checking files and getting elevated privileges for a scope and use guardrails everywhere
Any code execution inside of a SUID binary basically becomes root access. That means that SUID binaries need a lot of security measures for everything they do. The more complex you make your SUID capable binary, the more work this adds, and the higher the probability that you’re introducing some kind of bypass vulnerability.
With sudo and to some extent doas, the process that should be in charge of vetting whether or not a user can become root/another user (and probably should only be doing that) is also parsing files, interacting with the network, possibly doing I/O on the filesystem. The binary is started as a user with limited permissions, but that user has full control of the binary’s environment.
With a root daemon (the one your system already needs if you’re running systemd in the first place), the binary that submits the elevation request can be as small as possible, and have no additional permissions. You can trick run0 into doing something, but that won’t give you root access, as polkit and other mechanisms actually decide if you’re root or not. If you’re not root, you’re not going to be able to seriously influence those daemons, even if you debug and monitor the memory of the application that’s communicating with them, or somehow manage to LD_PRELOAD some malware into it.
Take, for instance, CVE-2023–22809. This vulnerability allowed some users to write files with root permissions (think /etc/sudoers) when the low privilege user was permitted to only edit files on a whitelist, because rather than taking the root user environment variables, various sudo tools accepted the user’s environment variables (the ones you provide on the command line) to decide what editor to launch. This editor could (basically) be ‘nano /etc/passwd’ and when you sudoedit /etc/user/tool/file/here.conf (as specified in sido’s config), sudoedit would spawn an editor opening /etc/passwd instead.
In the daemon model of run0, the daemon would be the one evaluating its (root) environment variables and picking the editor. However, in sudo, the binary that allowed itself to become root, could also be directly influenced by the low privilege user, and its protections against tampering proved insufficient.
This entire class of attacks just isn’t viable when the binary the end user runs doesn’t have the ability to exert any control. All the important bits are on the “other side”, running as a different user, isolated from the low privilege side.
Thanks for taking the time to explain. I was trying to get my head around on how this works but could not understand much of it. A lot of people here are very much against systemd in all senses, but this sounds like a better approach. Even if it not done as systemd, makes more sense than checking files and getting elevated privileges for a scope and use guardrails everywhere