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

Run brew commands as regular user #1564

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from
Draft

Run brew commands as regular user #1564

wants to merge 3 commits into from

Conversation

Neved4
Copy link

@Neved4 Neved4 commented Oct 21, 2024

Fixes #382, related #1273.

Instead of running Homebrew as the root user, this change runs it as a normal user, which is the intended use case for Homebrew. After the change, the command is run a non-root user context, which seems a way to effectively drop privileges.

This prevents raising the error:

Error: Running Homebrew as root is extremely dangerous and no longer supported.
As Homebrew does not drop privileges on installation you would be giving all
build scripts full access to your system.

Note: the function could have a different descriptive name, refactored to be more compact, etc. See:

RunBrewAsUser() {
    { [ "$(id -u)" -eq 0 ] && sudo -u "$SUDO_USER" brew "$@"; } || brew "$@"
}

Security

Thanks to brew's safeguards this might not be exploitable, but including the following for reference.

MITRE's CWE-250 is related to this change:

CWE ID CWE Title Description
CWE-250 Execution with Unnecessary Privileges The software runs with more privileges than necessary, which can lead to security vulnerabilities.

This change follows REF-76 by dropping the privileges as soon as possible, as in:

Run your code using the lowest privileges that are required to accomplish the necessary tasks.
Wrap and centralize this functionality if possible, and isolate the privileged code as much as possible from other code.
Raise privileges as late as possible, and drop them as soon as possible to avoid CWE-271.

Source: CWE-250: Execution with Unnecessary Privileges.

@Neved4 Neved4 changed the title Run brew commands as regular user when Lynis is invoked as root Run brew commands as regular user when lynis is invoked as root Oct 21, 2024
@wileyhy
Copy link

wileyhy commented Oct 22, 2024 via email

@wileyhy
Copy link

wileyhy commented Oct 22, 2024

Have I gotten anything wrong in this reply? It's been kind of a weird day.

@Neved4
Copy link
Author

Neved4 commented Oct 22, 2024

Hey @wileyhy thx for looking into this! You're 100% right for noting it.

Additionally:

  1. The function above is not the one that is in the commit.
  2. You're right $(id -u) evaluates as-is instead of being compared to anything there.
  3. This is a typo. It should have had the [ "$(id -u)" -eq 0 ] comparison.

We could edit my post to update this suggestion, or remove it since it doesn't reflect the current change.

Cheers!

@wileyhy
Copy link

wileyhy commented Oct 25, 2024 via email

@Neved4
Copy link
Author

Neved4 commented Oct 25, 2024

Hi @wileyhy,

You're right to raise those points. My initial PR only adressed cases where lynis runs with sudo. We could consider POSIX more broadly.

In Homebrew, some packages like util-linux vary between macOS and Linux. You can find disabled binaries (util-linux.rb#L104-L132) in the util-linux Homebrew version, which also disables commands such as su and runuser on both systems (util-linux.rb#L88-L89). Interestingly, setpriv is not installed on macOS, and for Linux, it seems it doesn't override existing system commands.

In systems with only su available, we could do:

su "$(id -un)" -c 'id -u'

These are the shells it seems to be working in:

Shell Version Supported
bash 5.2.37 Yes
dash 0.5.12 Yes
etsh 5.4.0 No
ksh93 1.0.10 Yes
mksh 59c Yes
oksh 7.5 Yes
osh 0.23.0 Yes
posh 0.14.1 Yes
yash 2.57 Yes
zsh 5.9 Yes

Both this one and sudo -u "$(whoami)" <cmd> seem to be effective ways to drop privileges temporarily for a specific command. On the flip side, neither sudo nor su are specified by POSIX.

C17 is specified by POSIX, but how else could it be done?

That's a great question. In C, I believe one can drop privileges by doing:

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[], char *environ[]) {
    uid_t prev_uid = getuid();
    uid_t prev_gid = getgid();

    if (setgid(prev_gid) != 0 || setuid(prev_uid) != 0) {
        perror("error: failed to drop privileges");
        return 1;
    }

    char *args[] = { "id", "-u", NULL };

    if (execve("/usr/bin/id", args, environ) == -1) {
        perror("error: failed to run execve");
        return 1;
    }

    return 0;
}
*This is test code and should not be used in production

Which seems to return the user id, even when calling it with sudo ./main. It also doesn't throw an error when running brew list.

Probably C folks would know what the right way to go about this is.

Currently, Homebrew only runs on both Linux and macOS. It's fair to assume brew is not running in a system without sudo, or that lynis would not call brew in a system that is not macOS nor Linux.

Using which isn’t POSIX-compliant, maybe we should use command -v instead. Besides that, the brew query in lynis only checks if the command itself is available, as in test_ports_packages#L1119:

FIND=$(which brew 2> /dev/null | grep -v "no [^ ]* in ")

It doesn’t check to skip the step for non-Linux or non-macOS systems.

Would be more than happy to add platform checks, use su instead of sudo or take any other approach. Feel free to make any adjustments necessary, or let me know what direction you’d prefer.

I’m here if you need anything.

Kind regards,
Neved4

@Neved4 Neved4 changed the title Run brew commands as regular user when lynis is invoked as root Run brew commands as regular user Oct 25, 2024
@Neved4 Neved4 marked this pull request as draft October 26, 2024 17:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Lynis needs to drop privilleges to support homebrew on MacOSX
2 participants