how to allow running a suid exe only with restricted params/env/context?
0
votes
1
answer
153
views
I have a suid-to-root executable that users should run only with certain parameters, env var settings and context setup. I can't modify that exe.
I will wrap the exe in arg-less scripts, one for each allowed parameterization, env and context setup. The problem is how to allow the user to run these scripts but not run the exe other ways.
Are there any security issues with my proposed solutions below or better alternatives?
I don't know if polkit or sudo can accomplish this, but would be interested in how if anyone knows.
I have 3 solutions:
1. use a mount namespace. Globally, mount the exe nosuid (it exits immediately if not run euid=0). Create a private mount namespace and remount the exe suid. Write a small suid exe with only arg = name of wrapper script, which enters the private namespace, drops privileges and runs the script. The wrapper scripts are all kept in a dedicated dir (/usr/local/bin/safescripts), hardcoded into the new small suid exe. The new exe always calls scripts only in that dir, which contains nothing else.
2. use a directory "vault". Create parent-child directory pair /usr/local/lock and /usr/local/lock/vault. Both are root:root owned, /usr/local/lock is 750, /usr/local/lock/vault is 755. Users cannot get to vault unaided. But once in vault, users can get at what's there. Move the original suid exe into /usr/local/lock/vault. Write a small suid exe that takes a basename of one of the scripts, chdirs into /usr/local/lock/vault, drops privileges and runs the script. Same setup for the wrapper scripts as in 1, but they must call the original exe using "./" prefixed pathname while staying in the cwd (vault).
3. handoff with elevated privileges (euid=0). Remove the suid bit on the original exe. Write a small suid exe that takes a basename of one of the scripts (as 1 and 2 above), and without dropping privileges, call the script (which must have #!/bin/bash -p) and allow the original exe to drop privileges itself.
I consider 3 to be too risky because so much is run with euid=0, including scripts.
Comparing the small exes of 1 and 2: 2 only does chdir (how bad can that be?) with euid=0, while 1 does an open of the bind-mounted suid namespace and setns to that fd - still small, but with more complex consequences. Also the setup of 1 requires a service to create the suid mount namespace and bind-mount it somewhere. Not much, but something. Alternatively, the new exe could create the mount namespace itself, but that makes it even more complex: it would have to call unshare and mount with elevated privs, both of which have many more options than open and setns.
I am leaning towards 2, which seems to be safest/easiest, although the vault setup seems kludgy. Unless someone can offer a better way or sees issues with 2.
Asked by schmeg
(31 rep)
May 21, 2023, 05:41 PM
Last activity: Jun 19, 2023, 07:31 PM
Last activity: Jun 19, 2023, 07:31 PM