Skip to content
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

Draft: Add 'nosetuid' treefile boolean to strip SetUID & SetGID bits #3433

Closed
wants to merge 6 commits into from

Conversation

travier
Copy link
Member

@travier travier commented Feb 14, 2022

Add 'nosetuid' treefile boolean to strip SetUIG & SetGID bits

This implements a post_process step similar to cliwrap that will strip
the SetUID and SetGID bits from all executable files found in the
compose.

@cgwalters
Copy link
Member

SetUIG

Did you mean SetUID?

This feels like it'd be more flexible as an allowlist, like:

setuid:
  - /usr/bin/sudo
  - /usr/bin/su

I also think we should debate stripping them out versus erroring. We could instead have e.g.:

suid-remove:
  - /usr/bin/somethingelse
  - /usr/bin/another-thing

?

Copy link
Member

@cgwalters cgwalters left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you give a specific example of where you want to use this?


/// Remove SetUID and SetGID bits from all executables.
#[context("Removing SetUID & SetGID bits from all executables")]
fn remove_setuid(_rootfs_dfd: &openat::Dir) -> Result<()> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, we're ignoring the passed dfd...

/// Remove SetUID and SetGID bits from all executables.
#[context("Removing SetUID & SetGID bits from all executables")]
fn remove_setuid(_rootfs_dfd: &openat::Dir) -> Result<()> {
for e in WalkDir::new("usr") {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So doesn't this actually operate on the process cwd? Which...I don't think we necessarily make be the rootfs.

I think while this walkdir crate is obviously nice code, today it isn't integrating with cap-std, and I've been trying to push things towards that. I am not sure that walkdir is buying us much over a simple recursive traversal function which we have in a few other places.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@travier travier changed the title Draft: Add 'nosetuid' treefile boolean to strip SetUIG & SetGID bits Draft: Add 'nosetuid' treefile boolean to strip SetUID & SetGID bits Feb 14, 2022
This implements a post_process step similar to cliwrap that will strip
the SetUID and SetGID bits from all executable files found in the
compose.
@travier
Copy link
Member Author

travier commented Feb 14, 2022

This feels like it'd be more flexible as an allowlist, like:

setuid:
  - /usr/bin/sudo
  - /usr/bin/su

Indeed, this would definitely make this even more useful. I would prefer we do an allow list (that could be empty) and that would keep the bits only from the selected binaries. That might allow user to select which one they want via CoreOS layering maybe?

I'll do that + the change to use something cap-std based.

@travier
Copy link
Member Author

travier commented Feb 14, 2022

So a more concrete example / use case for this feature: Creating a SetUID/SetGID less setup for rpm-ostree based systems.

Instead of using sudo, the user could setup its sshd server config to allow localhost only root login and optionally setup a strong 2 factor authentication for example (via a U2F key, etc.).

This would enable us to easily setup rpm-ostree based systems that remove the entire class of vulnerability from SetUID/SetGID apps.

@cgwalters
Copy link
Member

Instead of using sudo, the user could setup its sshd server config to allow localhost only root login and optionally setup a strong 2 factor authentication for example (via a U2F key, etc.).

OK. Hmm, one thing I tried here is:

$ cat /etc/systemd/system/user@.service.d/override.conf 
[Service]
NoNewPrivileges=true
$

But sadly it doesn't work, because at least sshd directly forks the child process. It's probably doable with a PAM module.

The advantage of NO_NEW_PRIVILEGES is that it applies to all setuid binaries, including e.g. any that are outside the OS root, including e.g. /var and mounted USB drives/network shares (which generally do use nosuid of course).

NNP can also be done in a more fine grained fashion - there may be a convenient non-PAM-module way to force it on.

But there may also be a "big hammer" way to do this globally today as an effective drop-in to all systemd units.

@travier
Copy link
Member Author

travier commented Feb 14, 2022

Those are indeed also good ideas. I vaguely remember trying to do things like that a while ago but never really found a nice setup. One would also have to go over each service to make sure that they still work.

PAM is also very complex and hard to work with thus I don't think I would be able to write such a module in a secure way (and it's also C).

There is also the option of using confined SELinux users, but that's another beast too. I'll have to try it again to make sure it works with rootless podman.

The idea behind this PR is that directly removing the SetUID bits avoids all of that complexity and makes it easy to try it out and revert right away if it fails.

@openshift-ci
Copy link

openshift-ci bot commented Mar 13, 2022

@travier: PR needs rebase.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository.

@openshift-ci
Copy link

openshift-ci bot commented Jun 6, 2023

@travier: The following tests failed, say /retest to rerun all failed tests or /retest-required to rerun all mandatory failed tests:

Test name Commit Details Required Rerun command
ci/prow/build-clang 50b543d link true /test build-clang
ci/prow/images 50b543d link true /test images
ci/prow/clang-analyzer 50b543d link true /test clang-analyzer
ci/prow/fcos-e2e 50b543d link true /test fcos-e2e
ci/prow/kola-upgrade 50b543d link true /test kola-upgrade

Full PR test history. Your PR dashboard.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. I understand the commands that are listed here.

@travier
Copy link
Member Author

travier commented May 13, 2024

I'm going to close this as this will be more easily done in a container layer and won't need any code changes in rpm-ostree at all.

@travier travier closed this May 13, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants