Skip to content

Instantly share code, notes, and snippets.

@wisq
Created April 11, 2012 01:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wisq/2356189 to your computer and use it in GitHub Desktop.
Save wisq/2356189 to your computer and use it in GitHub Desktop.
Why chowning /usr/local is bad

So let's say you're trying to write an app that will get root privs on someone's Macbook. Okay, there's a few different ways to go about this.

One, you could just run an application that asks for their login password and hope they're stupid enough to supply it. You'll catch some newbies but a lot of people will notice something's wrong, and if you're trying to spread before anyone notices, it's game over.

Two, you could create your own "sudo" and put it somewhere in their $PATH, including altering their login to point their $PATH to a new directory somewhere. But firstly, you're relying on someone running sudo eventually (many people never touch the command line), and secondly, some people are still going to notice.

So here's your third option. You only infect people who are running Homebrew, who have their /usr/local chowned to them. Why is this handy? Because /usr/local is in the default system-wide path. You can bet there's some script that runs with root privileges, that has /usr/local/bin or /usr/local/sbin in the path, and that doesn't use absolute paths for everything it runs.

So you find some exploit along these lines. I don't know any offhand, because most of the obvious ones (like "ls") already exist in /bin or /usr/bin and they're going to use those instead. But let's say you've got something. Call it /usr/local/bin/exploitable. So you create this file, and it gains root privs, installs itself system-wide (the whole computer is yours now), and deletes the old /usr/local/bin/exploitable to remove any trace.

Congrats. Privilege escalation for cheap.

This is why we have these rules. This is why users shouldn't install anything outside their home directory unless they switch to root (sudo or password dialog) and it installs as the root user so they can no longer touch it (without sudo'ing again, which requires their password).

There is a reason we do things the way we do. Homebrew ignores this in the name of a) not being bothered to choose a more sensible place, and b) not wanting the user to have to sudo. I don't mind (b); sudoing is something that ought to be done as little as is reasonably possible. But for god's sake, put it in their home directory and leave /usr/local alone.

Addendum: Unless you're installing something that is meant to be run by root, as a daemon or similar. Then, require sudo, install it somewhere system-wide (/opt/brew or /usr/local/brew or /usr/local/programname is a good choice), and don't let the user touch it again without sudo'ing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment