29

There are two ways I can think of doing this:

  1. On a system with sudo, by modifying /etc/sudoers.

  2. On a system without sudo (such as a Docker environment), by writing a program similar to the below and setting the setuid bit with chmod u+s. apt-get checks real uid, so a setuid call is necessary.

...
int main(int argc, char **argv) {
    char *envp[] = { ... };
    setuid(0);
    execve("/usr/bin/apt-get", argv, envp);
    return 1;
}

I have two questions:

  1. What are the potential vulnerabilities of allowing non-root users to run apt-get?
  2. My goal is to allow people to install/remove/update packages, given that apt-get lives in a custom non-system refroot and installs from a custom curated apt repository. Are there safer ways to allow non-root users to run apt-get on a system without sudo?
kzl
  • 401
  • 4
  • 6
  • 5
    This blog post comes to mind: https://0x90909090.blogspot.com/2015/07/no-one-expect-command-execution.html Apt in particular is not listed there, but I would not be expected at all if it allowed command execution somehow. Perhaps through specifying a repository on the command line (which would be under the attacker's control), perhaps there is a flag for a local deb file... and all of that is ignoring that one could remove system packages or keep packages out of date by maintaining a lock file. – Luc Jun 11 '20 at 23:38
  • 4
    A suggestion for a safer way depends on what you want to do. Do people need to install packages? Only update packages? Or do you merely just want an audit trail? What's the goal here? – Luc Jun 11 '20 at 23:39
  • Thanks for the engagement! The goal is to allow people to install/remove/update packages. – kzl Jun 11 '20 at 23:40
  • https://www.cyberciti.biz/faq/debian-ubuntu-linux-hook-a-script-command-to-apt-get-upgrade-command/ This is a method that allows arbitrary code execution for apt-get, but it requires root privileges to implement in the first place. I haven't been able to find others. – kzl Jun 11 '20 at 23:42
  • 7
    If users need to be able to remove packages, they can always kill the system by removing system packages. A safer way might be to write a script that accepts a package name, filters and escapes it, and calls apt install / upgrade. For removing, perhaps that script could keep track of packages the user installed and allow removing only those? It's is not trivial to make certain something custom like this is secure: if this is important, you might want to get someone to test the solution. Or perhaps there are solutions out there that I haven't heard of (I haven't ducked/googled it). – Luc Jun 11 '20 at 23:59
  • I just clarified in the question that apt-get is installed in a custom refroot! System packages are not at risk. I agree, it's not trivial. At the same time, I haven't found or thought of any vulnerabilities that could result from doing so, so I wanted to ask here in case someone has an answer. – kzl Jun 12 '20 at 00:22
  • 1
    Users should almost certainly be creating containers instead of doing...whatever this is. Look into rootless container solutions such as podman. – Michael Hampton Jun 12 '20 at 19:54
  • 1
    While the negative answers are all good and correct, in principle what OP wants can be done securely, by disallowing anything except request of a new package in the preexisting trusted repo set. That still has threats like causing an insecure daemon to get started with privileges, but it's closer to reasonable than allowing arbitrary `apt-get` commands. – R.. GitHub STOP HELPING ICE Jun 13 '20 at 06:23
  • @MichaelHampton Thanks for your suggestion. To clarify my use-case, I actually was asking about allowing users to use apt-get in a Docker environment. Each user has their own Docker container, and while I want to make sure they cannot run arbitrary commands as root, I also want to allow them to install packages from a custom repository. – kzl Jun 13 '20 at 10:16
  • @R..GitHubSTOPHELPINGICE Thanks for your suggestion! Could you clarify what you mean by "causing an insecure daemon to get started with privileges", please? – kzl Jun 13 '20 at 10:21
  • 1
    [aptdaemon](https://launchpad.net/aptdaemon) in combination with polkit allows one to update package lists and already existing packages on Debian / Ubuntu without being root. – YtvwlD Jun 13 '20 at 12:35
  • 1
    @kzl: Unless anything has changed (admittedly it's been a long time since I touched Debian-based dists except in containers), packages that provide daemons provide init (systemd service, or dbus activation, or whatever) files that cause them to be automatically run. Thus if you can install an obscure junk one, you can use it as attack surface; if it runs as root this can get you root. – R.. GitHub STOP HELPING ICE Jun 13 '20 at 15:45
  • Even if you manage to close all apt related issues you stil have to do the same for dpkg. And for people setting a path that points to a symlink to a shell. – John Keates Jun 13 '20 at 19:49
  • @R..GitHubSTOPHELPINGICE What OP wants can be done both securely and easily be using nix. nix is a package manager that can work beside apt-get. It is interesting how nix is built such that there are no security issues allowing all users unlimited access to run nix. It is easy to install nix on ubuntu https://nixos.org/download.html – emory Jun 14 '20 at 18:35

5 Answers5

67
apt-get update -o APT::Update::Pre-Invoke::=/bin/sh

From GTFOBins

This gives you a root shell on the system. No creating packages and adding fake repos; this will give the user who runs this command easy and simple access to root.

So, in answer to your question, you are effectively giving root to every user who has access to this binary. If you are willing to do this, then you might as well just give them sudo access or the root password.

Cyclic3
  • 845
  • 6
  • 6
  • 2
    This really should be a accepted answer, IMO; it's a much more elegant solution that more clearly answers the question of "what can a user do with `apt`. You don't even need a sources list, a package file, Internet access, or anything else... it just instantly drops you into a shell. – CBHacking Jun 14 '20 at 00:01
  • @CBHacking I changed it to accepted answer per your suggestion - thanks. This is probably the answer that most people would be interested in, though it does not address how to mitigate this risk, as Arminius's answer below does. https://security.stackexchange.com/a/233162/236489 – kzl Jun 14 '20 at 00:49
  • 2
    @CBHacking Thank you very much! Your exploit is more applicable in the real world from my experience: I have seen quite a few management panels that allow users to change repos and install packages, but do not expose the actual `apt-get` command itself. – Cyclic3 Jun 14 '20 at 16:41
  • Providing them with a `root` shell (or `system` access to `apt-get`) is the most stupid thing one could do. When this is some classroom or similar environment, rest assured there is at least one guy able to use it. What exactly is the point of having a security system, only to undermine it's authority? If you go any of these two ways, rest assured that bothered students might understand it as: the challenge is on. Such a configuration should better be kept in an isolated network segment. –  Jun 15 '20 at 15:17
46

You say you're using a "custom curated apt repository" but there's no way to enforce that. Any user that can invoke apt can specify their own source list, for example apt install root-backdoor -o Dir::Etc::Sourcelist=~/apt/my-own-sources.list. This can be done for all the other config settings as well, which means you can also have apt overwrite arbitrary files with content you choose (e.g. by setting the cache directory for retrieved packages).

Packages can (and often do) execute arbitrary commands during installation. Since the attacker can control the sourcelist, they can create malicious packages that either give unprivileged users a privileged backdoor, or simply execute (as root) any command the attacker desires as part of the "install" process.

apt is absolutely not a safe program to let people run (with root privileges) if you want to prevent them from running arbitrary code with root privileges.

EDIT: I want to call attention to this answer as a much cleaner way to get arbitrary execution (as root) out of apt.

CBHacking
  • 40,303
  • 3
  • 74
  • 98
  • 1
    Thanks for the answer! I appreciate your insight. Would preventing users from specifying their own sourcelists (e.g. by making a wrapper that specifically calls `apt-get install -- ` with root privileges) be sufficient to prevent users from installing arbitrary packages (and thus prevent arbitrary code execution as root)? – kzl Jun 12 '20 at 09:16
  • 6
    @kzl: You don't need to "make a wrapper," `sudoers(5)` already supports that sort of thing natively. However, I cannot recommend that because `apt-get` allows the user to specify the version of a package, so an attacker could downgrade a package to enable a security vulnerability. – Kevin Jun 12 '20 at 16:32
  • 5
    Note, that since apt ~1.2 you can install packages directly without referencing a repository, using `./` to point to a deb file. – Braiam Jun 12 '20 at 20:36
  • 1
    @Kevin Thanks for the reply. The constraints I listed above were 1) no sudo 2) custom refroot (non-system apt-get) and 3) custom curated apt repository. Armenius's answer below, suggesting a whitelist, addresses this question. https://security.stackexchange.com/a/233162/236489 – kzl Jun 13 '20 at 10:11
10

Would preventing users from specifying their own sourcelists (e.g. by making a wrapper that specifically calls apt-get install -- <packages> with root privileges) be sufficient to prevent users from installing arbitrary packages (and thus prevent arbitrary code execution as root)?

Nope, apt-get can also pick up packages from paths. An attacker could create a malicious .deb package that patches /etc/<something> for root access upon installation via e.g. apt-get install -- /path/to/foo.deb.

You might be able to make it work securely if your custom wrapper script only accepts what's on a whitelist of package names, and if you can guarantee the packages are only picked up from your sources list - and can never be supplied via custom configs, environment variables, etc.

Arminius
  • 43,922
  • 13
  • 140
  • 136
  • Thanks, this is also very helpful to me. I wish I could accept multiple answers. – kzl Jun 12 '20 at 17:10
7
  1. What are the potential vulnerabilities of allowing non-root users to run apt-get?

Full system compromise; Persistent privilege escalation from the user allowed to run apt-get to root.

  1. My goal is to allow people to install/remove/update packages, given that apt-get lives in a custom non-system refroot and installs from a custom curated apt repository. Are there safer ways to allow non-root users to run apt-get on a system without sudo?

As explained here, you cannot guarantee this.

Pedro
  • 3,911
  • 11
  • 25
  • Of course one can guarantee this, while not undermining the security system. –  Jun 15 '20 at 15:46
0

I actually strongly disagree with the answers so far, that's why I've added another perspective. My solution approach is roughly based upon one of @ Cyclic3's comments, but amended as required.


The actual attack vector:

When there already is a root shell, why deliver the payload by package manager? apt-get is not the main problem (as it is not essential to install software), but inappropriate software provisioning by unauthorized users is, which should better request the packages to be installed for them. Letting them surf the internet with a root account would be about the same idiocy, when looking at it from a security perspective.

On a side note, independent from apt-get, they always could wget some 0-day exploit, which performs privilege escalation. This would require white-listing destinations on the firewall to prevent, which does not amuse users in general, because this shuts down all of their random internet usage (which may also include job-related web research). This aspect is often being completely ignored.


One simple self-service solution:

Since nobody wants to play the server serf ...why not write a simple web UI, which let's them select the packages and then provision them to the machine they've requested from? Then just ssh into and run apt-get. This is a method of white-listing (I only know yum in detail, which does support black-listing but not white-listing). In general, this is a very simple way to almost guarantee zero risk, as the root shell & apt-get install are being kept outside of their reach. When triggering this as a batch job from the root crontab (assuming the root SSH keys match on all machines), one does not even have to switch the user account to do so. Just push a notify when done and they'll be amazed.

As I used to say, when working in user support: What they cannot click, they cannot mess up.