Bug#979546: docker.io: version in Bullseye does not support "rootless mode", makes privilege escalation trivial

2021-01-08 Thread El boulangero
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

2021-01-08 Thread Chris Mitchell
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

2021-01-07 Thread El boulangero
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

2021-01-07 Thread Shengjing Zhu
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

2021-01-07 Thread Chris
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