Bug#979546: docker.io: version in Bullseye does not support "rootless mode", makes privilege escalation trivial
On Sat, Jan 9, 2021 at 2:00 AM Chris Mitchell wrote: > On Fri, 8 Jan 2021 11:38:59 +0700 > El boulangero wrote: > > > Hi Chris, > > > > I believe what you refer to is a well-known issue with docker. I have > > this reference from Apr. 2015: > > https://fosterelli.co/privilege-escalation-via-docker.html > > > > This is how docker works. The most easy mitigation is NOT to add a > > user to the docker group. This way, you will always invoke docker > > with 'sudo docker', and then it's explicit that you're running > > something as root. Explicit better than implicit maybe, at least no > > more "accidental". > > This makes some sense. Given that it's apparently well-known that > allowing a user to run Docker essentially gives them unrestricted root > access, I'm rather surprised that no warning was presented at any point > in this process. > > > Second thing, as you noted, docker can access a directory on the host > > only if you share it with '--volume' or '--mount' or something. So > > it's not really accidental if then the process in the container > > writes to the host directory. It's something that you authorized > > explicitly. And the fact that it's a root access is due to the fact > > that the container is run as root, as you correctly noted. > > Ah, okay. This, I think, is where I fundamentally misunderstood the > situation. I was picturing the "containerized app" as a single entity, > presenting an all-or-nothing choice between "accept that anything you > run in a Docker container has root access to your whole filesystem" or > "don't use Docker". If Docker is providing meaningful enforcement and > limiting the access of the "contained" app to only the directory(ies) > you share with it in the container config (though not subject to the > host system's *permissions*) that's a very different proposition. > > Trusting *myself* not to abuse Docker's privilege-escalation abilities > (on a system where I already have root), checking carefully what paths > are shared via the container configs, and making sure that the path > containing those configs is never shared... That's within the realm of > reasonable expectations. > > > If you download and run a containerized app as root, and share your > > /home with the container, then you'd better trust this app 100%. > > To be clear, I did not knowingly or explicitly do any of these things > except "download and run a containerized app". I downloaded the app as > a regular user, used my sudo powers to add said user to the docker group > (because all the "getting started" instructions just say that you need > to be in the docker group to use Docker) and ran, as a regular user, > "docker-compose -d up". Now that I know to go looking for it, I see > that the "volumes" directive appears in one of the config files. While > I acknowledge that the responsibility for understanding the tools I use > ultimately falls to me, nothing in this sequence jumps out to me as > "you are granting unrestricted root access!" or "you'd better trust > this app 100%". > I never used docker-compose, only the docker command itself, so I've always known more or less what was going on :) docker-compose is a layer on top of docker, so it hides things away from the user (in this case, the arguments for the docker command are in a config file apparently). So things are even less explicit, for the sake of simplicity. I think two important things are 1) *which user* is running in the container (root or non-root), and what volumes are shared. These are the arguments that you would use the most often with 'docker run', and also the king of things you'd want to check in a docker compose file. There are many ways to run container with docker, depending on the use-case. If you want to run a container manually, as your own user, and while sharing only the current directory, you can do this: sudo docker run -it --rm \ -u $(id -u):$(id -g) \ -v /etc/group:/etc/group:ro \ -v /etc/passwd:/etc/passwd:ro \ -v $(pwd):$(pwd) -w $(pwd) \ $YOUR_DOCKER_IMAGE Note that the two first -v arguments are optional, but they allow that you user id is known in the container. Try with and without, both work. This is a command that I use often, but when you get started with docker, it's unlikely you'll find that by yourself at the first try :) > > As a fairly experienced Debian user, I've been accustomed to add myself > to all sorts of groups over the years, and the only one that has ever > been presented as "this grants full root powers" is sudo, which then > pops up a stern warning the first time you use it. Also it's sudo. Its > singular, stated purpose is to grant root powers. The fact that no > warning popped up anywhere along the way to discovering that my > supposedly sandboxed Docker app was creating files as root on the host > strikes me as alarming. > > In my defence, I knew I was playing with things I didn't understand, so > the "regular user" in question
Bug#979546: docker.io: version in Bullseye does not support "rootless mode", makes privilege escalation trivial
On Fri, 8 Jan 2021 11:38:59 +0700 El boulangero wrote: > Hi Chris, > > I believe what you refer to is a well-known issue with docker. I have > this reference from Apr. 2015: > https://fosterelli.co/privilege-escalation-via-docker.html > > This is how docker works. The most easy mitigation is NOT to add a > user to the docker group. This way, you will always invoke docker > with 'sudo docker', and then it's explicit that you're running > something as root. Explicit better than implicit maybe, at least no > more "accidental". This makes some sense. Given that it's apparently well-known that allowing a user to run Docker essentially gives them unrestricted root access, I'm rather surprised that no warning was presented at any point in this process. > Second thing, as you noted, docker can access a directory on the host > only if you share it with '--volume' or '--mount' or something. So > it's not really accidental if then the process in the container > writes to the host directory. It's something that you authorized > explicitly. And the fact that it's a root access is due to the fact > that the container is run as root, as you correctly noted. Ah, okay. This, I think, is where I fundamentally misunderstood the situation. I was picturing the "containerized app" as a single entity, presenting an all-or-nothing choice between "accept that anything you run in a Docker container has root access to your whole filesystem" or "don't use Docker". If Docker is providing meaningful enforcement and limiting the access of the "contained" app to only the directory(ies) you share with it in the container config (though not subject to the host system's *permissions*) that's a very different proposition. Trusting *myself* not to abuse Docker's privilege-escalation abilities (on a system where I already have root), checking carefully what paths are shared via the container configs, and making sure that the path containing those configs is never shared... That's within the realm of reasonable expectations. > If you download and run a containerized app as root, and share your > /home with the container, then you'd better trust this app 100%. To be clear, I did not knowingly or explicitly do any of these things except "download and run a containerized app". I downloaded the app as a regular user, used my sudo powers to add said user to the docker group (because all the "getting started" instructions just say that you need to be in the docker group to use Docker) and ran, as a regular user, "docker-compose -d up". Now that I know to go looking for it, I see that the "volumes" directive appears in one of the config files. While I acknowledge that the responsibility for understanding the tools I use ultimately falls to me, nothing in this sequence jumps out to me as "you are granting unrestricted root access!" or "you'd better trust this app 100%". As a fairly experienced Debian user, I've been accustomed to add myself to all sorts of groups over the years, and the only one that has ever been presented as "this grants full root powers" is sudo, which then pops up a stern warning the first time you use it. Also it's sudo. Its singular, stated purpose is to grant root powers. The fact that no warning popped up anywhere along the way to discovering that my supposedly sandboxed Docker app was creating files as root on the host strikes me as alarming. In my defence, I knew I was playing with things I didn't understand, so the "regular user" in question was a fresh, blank account in a KVM virtual machine that has no shared storage or memory. I'm not *entirely* naive. That said, am I the only one who finds it worrying how easy it would be for a moderately naive desktop user to unwittingly grant a malicious containerized app root access to the entire filesystem of their real system without doing anything obviously reckless or stupid or encountering any warning along the way? Is this a thing that can and should be addressed somehow? > > a search for "docker" on backports.debian.org returned no results > > Indeed, docker sits on top of 100+ dependencies, backporting would > mean backporting all those dependencies. Plus maybe the go compiler > and the go library. It would be such a huge work that it's not > realistic. > > Since Go is a statically compiled language, there's little value in > backporting anyway. You can just try your luck and install the docker > from Debian unstable into your Debian stable. It might work. Maybe > some bugs would be lurking here and there in the dark, maybe not, I > just don't know. > > As for rootless mode, it should be indeed supported in the 20.10 > version. I myself never tested it. If I'm not mistaken, everything is > present in the 20.10 package provided in Debian unstable to run the > rootless mode. You can give it a try :) If being aware of — and careful with — the "volume" directive is the key to running Docker containerized apps in a reasonably safe way, I think I won't mess around
Bug#979546: docker.io: version in Bullseye does not support "rootless mode", makes privilege escalation trivial
Hi Chris, I believe what you refer to is a well-known issue with docker. I have this reference from Apr. 2015: https://fosterelli.co/privilege-escalation-via-docker.html This is how docker works. The most easy mitigation is NOT to add a user to the docker group. This way, you will always invoke docker with 'sudo docker', and then it's explicit that you're running something as root. Explicit better than implicit maybe, at least no more "accidental". Second thing, as you noted, docker can access a directory on the host only if you share it with '--volume' or '--mount' or something. So it's not really accidental if then the process in the container writes to the host directory. It's something that you authorized explicitly. And the fact that it's a root access is due to the fact that the container is run as root, as you correctly noted. If you download and run a containerized app as root, and share your /home with the container, then you'd better trust this app 100%. > a search for "docker" on backports.debian.org returned no results Indeed, docker sits on top of 100+ dependencies, backporting would mean backporting all those dependencies. Plus maybe the go compiler and the go library. It would be such a huge work that it's not realistic. Since Go is a statically compiled language, there's little value in backporting anyway. You can just try your luck and install the docker from Debian unstable into your Debian stable. It might work. Maybe some bugs would be lurking here and there in the dark, maybe not, I just don't know. As for rootless mode, it should be indeed supported in the 20.10 version. I myself never tested it. If I'm not mistaken, everything is present in the 20.10 package provided in Debian unstable to run the rootless mode. You can give it a try :) All the best, Arnaud On Fri, Jan 8, 2021 at 10:48 AM Chris wrote: > Package: docker.io > Version: 18.09.1+dfsg1-7.1+deb10u2 > Severity: critical > Tags: security > Justification: root security hole > > Dear Maintainer, > > Unless I'm missing something, any program running in a Docker container > using the Docker version currently available in Debian stable has a > trivial-to-exploit path to full, persistent, root privilege escalation. > > Docker v18 only works when it's SUID root. Processes running as root > *inside* the container accessing the *host* filesystem do so as root *on > the host system* unless they are internally configured to map to a > regular user on the host system. (According to my rough and inexpert > understanding of the situation.) > > I installed docker.io from the official Debian stable repos, added a > user to group "docker" in order to be able to use it, downloaded and > ran a containerized program, and noticed that the program in the > container was creating files and directories with root ownership in my > home directory on the host system. > > A quick search of the web turned up a tutorial showing how easy it is > to exploit this situation: > https://medium.com/@Affix/privilege-escallation-with-docker-56dc682a6e17 > ...as well as tutorials on how not to *accidentally* create root-owned > files on the host system when setting up Docker containers, eg: > https://vsupalov.com/docker-shared-permissions/ > > I discovered that newer versions of Docker have a "rootless mode" that > doesn't require the main Docker executable to run SUID root (though it > does rely on a couple of narrow-scope SUID helper utilities), which > should hopefully mitigate this situation to a considerable extent: > https://docs.docker.com/engine/security/rootless > This capability was introduced as experimental in v19.03 and "graduated > from experimental" in v20.10. Unsurprisingly, it requires that > unprivileged_userns_clone be enabled. > > The version of docker.io in the Buster repos is 18.09 at the time of > this writing, and a search for "docker" on backports.debian.org returned > no results. While I am aware of the controversy around > unprivileged_userns_clone, I gather that it will be enabled by default > in Bullseye (starting with kernel 5.10, I believe) because at this point > it presents the lesser evil. > > Unless I'm gravely mistaken about the situation, I'd much rather enable > that potentially-exploitable kernel feature and run Docker in "rootless > mode" than continue running Docker in a configuration that's so easily > exploitable there are tutorials on how to prevent accidentally creating > files as root when using Docker containers as a regular user. > > Accidental. Root. Filesystem access. As a regular user. > > I propose that — as a minimum — backporting the version of Docker in > Bullseye (currently v20.10) to Buster be treated as an urgent security > priority, so that users at least have the option to install Docker from > an official Debian source and use it in the less-dangerous "rootless > mode". > > Further, Docker is widespread and gaining popularity fast, it's already > in the Debian stable repositories, and
Bug#979546: docker.io: version in Bullseye does not support "rootless mode", makes privilege escalation trivial
Control: retitle -1 docker.io: version in Buster does not support "rootless mode" Control: fixed -1 20.10.0~rc1+dfsg2-1 Control: severity -1 wishlist On Fri, Jan 8, 2021 at 11:55 AM Chris wrote: > > Package: docker.io > Version: 18.09.1+dfsg1-7.1+deb10u2 > Severity: critical > Tags: security > Justification: root security hole > > Dear Maintainer, > > Unless I'm missing something, any program running in a Docker container > using the Docker version currently available in Debian stable has a > trivial-to-exploit path to full, persistent, root privilege escalation. > > Docker v18 only works when it's SUID root. Processes running as root > *inside* the container accessing the *host* filesystem do so as root *on > the host system* unless they are internally configured to map to a > regular user on the host system. (According to my rough and inexpert > understanding of the situation.) > > I installed docker.io from the official Debian stable repos, added a > user to group "docker" in order to be able to use it, downloaded and > ran a containerized program, and noticed that the program in the > container was creating files and directories with root ownership in my > home directory on the host system. > > A quick search of the web turned up a tutorial showing how easy it is > to exploit this situation: > https://medium.com/@Affix/privilege-escallation-with-docker-56dc682a6e17 > ...as well as tutorials on how not to *accidentally* create root-owned > files on the host system when setting up Docker containers, eg: > https://vsupalov.com/docker-shared-permissions/ > > I discovered that newer versions of Docker have a "rootless mode" that > doesn't require the main Docker executable to run SUID root (though it > does rely on a couple of narrow-scope SUID helper utilities), which > should hopefully mitigate this situation to a considerable extent: > https://docs.docker.com/engine/security/rootless > This capability was introduced as experimental in v19.03 and "graduated > from experimental" in v20.10. Unsurprisingly, it requires that > unprivileged_userns_clone be enabled. > > The version of docker.io in the Buster repos is 18.09 at the time of > this writing, and a search for "docker" on backports.debian.org returned > no results. While I am aware of the controversy around > unprivileged_userns_clone, I gather that it will be enabled by default > in Bullseye (starting with kernel 5.10, I believe) because at this point > it presents the lesser evil. > > Unless I'm gravely mistaken about the situation, I'd much rather enable > that potentially-exploitable kernel feature and run Docker in "rootless > mode" than continue running Docker in a configuration that's so easily > exploitable there are tutorials on how to prevent accidentally creating > files as root when using Docker containers as a regular user. > > Accidental. Root. Filesystem access. As a regular user. > > I propose that — as a minimum — backporting the version of Docker in > Bullseye (currently v20.10) to Buster be treated as an urgent security > priority, so that users at least have the option to install Docker from > an official Debian source and use it in the less-dangerous "rootless > mode". > > Further, Docker is widespread and gaining popularity fast, it's already > in the Debian stable repositories, and the only way the version > currently in stable can be used is *shockingly* dangerous. Given all > that, I'm inclined to suggest that pushing Docker v20.10 to > buster-security along with configuration that enables > unpriv_userns_clone and sets Docker up to run in "rootless mode" should > be seriously considered. > > Or my understanding of the situation could be profoundly wrong. I'm > pushing the edge of my technical understanding here, and I would be > thoroughly pleased to be wrong about this whole thing. > This is how docker designed. If you give someone the permission to use docker daemon, then it means you give out the root permission. Rootless is a new feature, so this bug is a feature request, not a security bug. docker is written in Go, you can install the 20.10 version from unstable even if you are on buster. But it's not recommended anyway. -- Shengjing Zhu
Bug#979546: docker.io: version in Bullseye does not support "rootless mode", makes privilege escalation trivial
Package: docker.io Version: 18.09.1+dfsg1-7.1+deb10u2 Severity: critical Tags: security Justification: root security hole Dear Maintainer, Unless I'm missing something, any program running in a Docker container using the Docker version currently available in Debian stable has a trivial-to-exploit path to full, persistent, root privilege escalation. Docker v18 only works when it's SUID root. Processes running as root *inside* the container accessing the *host* filesystem do so as root *on the host system* unless they are internally configured to map to a regular user on the host system. (According to my rough and inexpert understanding of the situation.) I installed docker.io from the official Debian stable repos, added a user to group "docker" in order to be able to use it, downloaded and ran a containerized program, and noticed that the program in the container was creating files and directories with root ownership in my home directory on the host system. A quick search of the web turned up a tutorial showing how easy it is to exploit this situation: https://medium.com/@Affix/privilege-escallation-with-docker-56dc682a6e17 ...as well as tutorials on how not to *accidentally* create root-owned files on the host system when setting up Docker containers, eg: https://vsupalov.com/docker-shared-permissions/ I discovered that newer versions of Docker have a "rootless mode" that doesn't require the main Docker executable to run SUID root (though it does rely on a couple of narrow-scope SUID helper utilities), which should hopefully mitigate this situation to a considerable extent: https://docs.docker.com/engine/security/rootless This capability was introduced as experimental in v19.03 and "graduated from experimental" in v20.10. Unsurprisingly, it requires that unprivileged_userns_clone be enabled. The version of docker.io in the Buster repos is 18.09 at the time of this writing, and a search for "docker" on backports.debian.org returned no results. While I am aware of the controversy around unprivileged_userns_clone, I gather that it will be enabled by default in Bullseye (starting with kernel 5.10, I believe) because at this point it presents the lesser evil. Unless I'm gravely mistaken about the situation, I'd much rather enable that potentially-exploitable kernel feature and run Docker in "rootless mode" than continue running Docker in a configuration that's so easily exploitable there are tutorials on how to prevent accidentally creating files as root when using Docker containers as a regular user. Accidental. Root. Filesystem access. As a regular user. I propose that — as a minimum — backporting the version of Docker in Bullseye (currently v20.10) to Buster be treated as an urgent security priority, so that users at least have the option to install Docker from an official Debian source and use it in the less-dangerous "rootless mode". Further, Docker is widespread and gaining popularity fast, it's already in the Debian stable repositories, and the only way the version currently in stable can be used is *shockingly* dangerous. Given all that, I'm inclined to suggest that pushing Docker v20.10 to buster-security along with configuration that enables unpriv_userns_clone and sets Docker up to run in "rootless mode" should be seriously considered. Or my understanding of the situation could be profoundly wrong. I'm pushing the edge of my technical understanding here, and I would be thoroughly pleased to be wrong about this whole thing. Cheers! -Chris -- System Information: Debian Release: 10.7 APT prefers stable-updates APT policy: (500, 'stable-updates'), (500, 'stable') Architecture: amd64 (x86_64) Kernel: Linux 4.19.0-13-amd64 (SMP w/2 CPU cores) Kernel taint flags: TAINT_UNSIGNED_MODULE Locale: LANG=en_CA.UTF-8, LC_CTYPE=en_CA.UTF-8 (charmap=UTF-8), LANGUAGE=en_CA:en (charmap=UTF-8) Shell: /bin/sh linked to /usr/bin/dash Init: systemd (via /run/systemd/system) LSM: AppArmor: enabled Versions of packages docker.io depends on: ii adduser 3.118 ii iptables1.8.2-4 ii libc6 2.28-10 ii libdevmapper1.02.1 2:1.02.155-3 ii libltdl72.4.6-9 ii libnspr42:4.20-1 ii libnss3 2:3.42.1-1+deb10u3 ii libseccomp2 2.3.3-4 ii libsystemd0 241-7~deb10u5 ii lsb-base10.2019051400 ii runc1.0.0~rc6+dfsg1-3 ii tini0.18.0-1 Versions of packages docker.io recommends: ii ca-certificates 20200601~deb10u1 ii cgroupfs-mount 1.4 ii git 1:2.20.1-2+deb10u3 ii needrestart 3.4-5 ii xz-utils 5.2.4-1 Versions of packages docker.io suggests: pn aufs-tools pn btrfs-progs pn debootstrap pn docker-doc ii e2fsprogs1.44.5-1+deb10u3 pn rinse pn xfsprogs pn zfs-fuse | zfsutils -- no debconf information