8000 Rethinking SUID-root binaries · Issue #866 · secureblue/secureblue · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Rethinking SUID-root binaries #866

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
ok-ryoko opened this issue Feb 21, 2025 · 6 comments
Open

Rethinking SUID-root binaries #866

ok-ryoko opened this issue Feb 21, 2025 · 6 comments
Labels
enhancement New feature or request
Milestone

Comments

@ok-ryoko
Copy link

I recently revisited my research of SUID-root binaries in Fedora Linux and would like to bring several key changes to secureblue’s attention.

To make my work easier to read, navigate, and maintain, I moved away from monolithic and incremental gists to a Git repository at https://git.sr.ht/~megumi/fedora-suid. secureblue is, to my knowledge, the only project using my work at this time. I would find your feedback on the new format and content especially valuable, although there’s no obligation to give any. In any case, the reference in removesuid.sh should be updated accordingly.

I also developed a fork of strace(1) to print capability checks that I then applied to help refine my findings and add new reference use cases. I hope that it can help distro maintainers like yourself reach independent conclusions about capabilities.

Importantly, I revised my position on SUID-root execution. I’d previously operated on the premise that the SUID bit could and should be substituted with file capabilities. However, I now think that file capabilities should be set only to supplement the SUID bit on capabilities-unaware binaries.

SUID-root programs make UID transitions to drop privileges either temporarily or permanently. Unsetting the SUID bit makes certain respective setuid(2), setreuid(2), etc. calls no-ops. The only option that the program has to drop privileges is then to immediately execve(2) an unprivileged program, which isn’t guaranteed.

As well, unsetting the SUID bit imposes a requirement for additional powerful capabilities such as CAP_DAC_OVERRIDE to compensate for the concomitant mismatch in EUIDs when interaction with files and directories owned by root is necessary.

I’d be happy to submit a pull request making the requisite changes. I started by opening an issue because I believe that it’s more important to achieve a consensus on next steps, given how challenging it can be to reason about these topics all at once.

Thank you again for all your work!

@RoyalOughtness RoyalOughtness added the enhancement New feature or request label Feb 21, 2025
@RoyalOughtness
Copy link
Collaborator
RoyalOughtness commented Feb 21, 2025

@ok-ryoko hello and welcome! and than you very much for your work 😄

should be updated accordingly.

Yes certainly

As well, unsetting the SUID bit imposes a requirement for additional powerful capabilities such as CAP_DAC_OVERRIDE

Fortunately, we don't need this currently except for chfn.

secureblue's approach is currently to fully remove suid-root binaries if possible. If that's not possible, then strip suid.

requisite changes

What changes do you have in mind?

Polkit agent helper will no longer require suid once this merges and ships polkit-org/polkit#501

And the only places where we use caps are:

set_caps_if_present "cap_dac_read_search,cap_audit_write=ep" "/usr/bin/chage"
set_caps_if_present "cap_chown,cap_dac_override,cap_fowner,cap_audit_write=ep" "/usr/bin/chfn"
set_caps_if_present "cap_dac_read_search=ep" "/usr/libexec/openssh/ssh-keysign"
set_caps_if_present "cap_sys_admin=ep" "/usr/bin/fusermount3"
set_caps_if_present "cap_dac_read_search,cap_audit_write=ep" "/usr/sbin/unix_chkpwd"

chage and chfn could potentially be removed altogether (or left suidless without caps), like we do for chsh, sudo, su, and pkexec, would need to test that out though.

@ok-ryoko
Copy link
Author
8000 ok-ryoko commented Feb 21, 2025

What changes do you have in mind?

If chfn(1), ssh-keysign(8), and fusermount3(1) were made SUID-root, then the appropriate capability sets would be as follows:

set_caps_if_present "cap_chown,cap_audit_write=ep" "/usr/bin/chfn"
set_caps_if_present "=" "/usr/libexec/openssh/ssh-keysign"
set_caps_if_present "cap_dac_read_search,cap_sys_admin=ep" "/usr/bin/fusermount3"

In this case, it’d also be appropriate to rename setcapsforunsuidbinaries to setcapsforsuidbinaries and propagate that rename. However, if it’s secureblue’s policy to avoid SUID-root execution, then these changes are not viable.

Polkit agent helper will no longer require suid once this merges and ships polkit-org/polkit#501

Good to know!

chage and chfn could potentially be removed altogether (or left suidless without caps)

Out of the five applications listed in setcapsforunsuidbinaries, the only ones I know to be critical to Fedora Linux/GNOME functionality (based on my experience) are unix_chkpwd(8) and fusermount3(1).

I appreciate your quick reply.

@RoyalOughtness
Copy link
Collaborator
RoyalOughtness commented Feb 23, 2025

However, if it’s secureblue’s policy to avoid SUID-root execution, then these changes are not viable.

Well, it depends. If I understand your concern correctly, it's that although using caps instead of suid reduces the maximum privileges a binary can have, it might also increase the minimum privileges of that binary, by making it incapable of dropping privileges (as it does when suid-root).

If this is correct, I think it would be best to approach it on a case by case basis, asking the following questions:

  • Does the binary work without any caps or suid? If so, we can leave the binary and strip it of suid, without replacing with caps.
  • Does the binary only require relatively innocuous (like cap_dac_read_search) caps if suid is removed? If so, replacing suid with caps seems preferred, even if those relatively innocuous caps aren't dropped, due to how significant of a risk is posed by suid.
  • Does the binary only work without suid if it's replaced with powerful caps? In this case, I'd be inclined to either remove the binary altogether if possible, or leave it suid and investigate upstream solutions like making the binary cap-aware.

Let me know your thoughts

@ok-ryoko
Copy link
Author
ok-ryoko commented Feb 24, 2025

I think it would be best to approach it on a case by case basis

Certainly. I’ve sketched some analyses below based on the sources for and traces of the Fedora Linux 41 1.4 versions of the binaries.

/usr/bin/chage: For chage -l LOGIN, requires CAP_DAC_READ_SEARCH and CAP_AUDIT_WRITE irrespective of EUID. Drops privileges via setregid(2) and setreuid(2) after opening /etc/passwd and /etc/shadow. Doesn’t openat(2) any user-supplied path after dropping privileges. Non-SUID-root setup may incur less risk.

/usr/bin/chfn: For updating finger information, requires CAP_CHOWN and CAP_AUDIT_WRITE when running SUID-root, otherwise also requires CAP_DAC_OVERRIDE and CAP_FOWNER. Doesn’t drop privileges.

/usr/libexec/openssh/ssh-keysign: To support host-based authentication via ssh(1), requires no capabilities when running SUID-root, otherwise requires CAP_DAC_READ_SEARCH. Drops privileges via setresgid(2) and setresuid(2) after opening private SSH host keys, the NSS configuration file, and /etc/passwd. Doesn’t openat(2) any user-supplied path after dropping privileges. If not running SUID-root, then the process can hypothetically extract sensitive information such as encrypted passwords from /etc/shadow.

/usr/bin/fusermount3: For mounting and unmounting FUSE filesystems, requires CAP_DAC_READ_SEARCH and CAP_SYS_ADMIN when running SUID-root, but not CAP_DAC_READ_SEARCH when running as an unprivileged user. In either case, drops only filesystem privileges via setfsgid(2) and setfsuid(2) before opening /dev/fuse, reading /etc/fuse.conf, and resolving the path to the mountpoint, restoring filesystem privileges immediately afterwards. Non-SUID-root setup may incur less risk. In addition, running fusermount3(1) non-SUID-root doesn’t interfere with its ability to drop privileges because FSUID transitions have no effect on process capability sets.

/usr/sbin/unix_chkpwd: To support the pam_unix.so auth and password modules, requires CAP_DAC_READ_SEARCH and CAP_AUDIT_WRITE irrespective of EUID. Doesn’t drop privileges on the happy path. Non-SUID-root setup may incur less risk.

On the basis of just these observations, and without reference to any particular threat model, it does seem less risky to run some of these binaries non-SUID-root when aiming to minimize attack surface.

I’d prioritize removing privileges from chfn(1) as secureblue already does for chsh(1). If you wanted to remove the binary altogether, usermod(8) could help fill the gap:

$ run0 usermod -c COMMENT LOGIN

… although this would require users to remember the structure of the GECOS field.

@bluca
Copy link
bluca commented Feb 26, 2025

On modern Linux dropping privileges doesn't just mean changing uid/gid, it can also be done via LSMs such as Landlock. This would work great for cases like unix_chkpwd that only need access to one or two fixed files that are privileged, and nothing else. So a file-based capability for reading/writing plus Landlock to restrict access to only those two files should be feasible and remove the need for suid.

@RoyalOughtness RoyalOughtness modified the milestones: 4.5, 5.0 Mar 3, 2025
@RoyalOughtness
Copy link
Collaborator

@ok-ryoko

If not running SUID-root, then the process can hypothetically extract sensitive information such as encrypted passwords from /etc/shadow.

This seems like the most critical of the issues you listed. Is the best option available to add back suid? Seems like a lose-lose.

I’d prioritize removing privileges from chfn(1) as secureblue already does for chsh(1). If you wanted to remove the binary altogether, usermod(8) could help fill the gap:

I'm inclined to do so but it would require documenting how to use usermod in its place, in an FAQ item.

@RoyalOughtness RoyalOughtness marked this as a duplicate of #296 May 4, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants
0