Docker images can contain SUID binaries #229

Open
timthelion opened this Issue Oct 6, 2015 · 12 comments

Comments

Projects
None yet
4 participants
@timthelion
Contributor

timthelion commented Oct 6, 2015

This means that all subusers can be considered to have root WITHIN THE CONTAINER. This bug will be resolved once usernamespaces are a thing in runc/Docker.

@ruipin

This comment has been minimized.

Show comment
Hide comment
@ruipin

ruipin Oct 9, 2015

Contributor

Can't docker mount its filesystems as nosuid?

Contributor

ruipin commented Oct 9, 2015

Can't docker mount its filesystems as nosuid?

@timthelion

This comment has been minimized.

Show comment
Hide comment
@timthelion

timthelion Oct 9, 2015

Contributor

I searched for this, but couldn't find it. I don't think that it is possible. I also found many claims that it is not desireable, because most distributions rely on nosuid for core functionality. I haven't verified that second part yet.

Contributor

timthelion commented Oct 9, 2015

I searched for this, but couldn't find it. I don't think that it is possible. I also found many claims that it is not desireable, because most distributions rely on nosuid for core functionality. I haven't verified that second part yet.

@ruipin

This comment has been minimized.

Show comment
Hide comment
@ruipin

ruipin Oct 9, 2015

Contributor

I thought they could. For example, this article mentions:

if you’re worried about normal apps escalating from non-root to root, "defang" SUID binaries by removing the SUID bit and/or mount filesystems with nosuid.

Even if that's not the case, this article takes a different approach, by removing suid permissions from files manually, in the dockerfile itself. This could be used as a work-around, I guess.

Contributor

ruipin commented Oct 9, 2015

I thought they could. For example, this article mentions:

if you’re worried about normal apps escalating from non-root to root, "defang" SUID binaries by removing the SUID bit and/or mount filesystems with nosuid.

Even if that's not the case, this article takes a different approach, by removing suid permissions from files manually, in the dockerfile itself. This could be used as a work-around, I guess.

@timthelion

This comment has been minimized.

Show comment
Hide comment
@timthelion

timthelion Oct 9, 2015

Contributor

Yes, I saw that article. Which really seems to give the impression that the only way is to remove suid bits. We even have a good place to put that code: https://github.com/subuser-security/subuser/blob/master/logic/subuserlib/classes/subuserSubmodules/run/runReadyImage.py#L38

However, any time one adds code that gets run within the image, that code has to be extremely portable. Preferably POSIX compliant shell. (Or I guess it might be possible to use a statically linked binary, but that has other complications with compiling/distribution ect.)

Contributor

timthelion commented Oct 9, 2015

Yes, I saw that article. Which really seems to give the impression that the only way is to remove suid bits. We even have a good place to put that code: https://github.com/subuser-security/subuser/blob/master/logic/subuserlib/classes/subuserSubmodules/run/runReadyImage.py#L38

However, any time one adds code that gets run within the image, that code has to be extremely portable. Preferably POSIX compliant shell. (Or I guess it might be possible to use a statically linked binary, but that has other complications with compiling/distribution ect.)

@timthelion

This comment has been minimized.

Show comment
Hide comment
@timthelion

timthelion Oct 9, 2015

Contributor

If you want to play with this, I would suggest, writing some really crapy code quickly, to get rid of the suid bits and see if anything breaks. Don't invest a lot of time in it, untill you know that normal applications have a chance of working without suid bits in the system :)

Contributor

timthelion commented Oct 9, 2015

If you want to play with this, I would suggest, writing some really crapy code quickly, to get rid of the suid bits and see if anything breaks. Don't invest a lot of time in it, untill you know that normal applications have a chance of working without suid bits in the system :)

@timthelion

This comment has been minimized.

Show comment
Hide comment
@timthelion

timthelion Oct 9, 2015

Contributor

Oops, I just realized that modifying the run ready image Dockerfile might not work in this case because it would be possible for a malicious image to interfere with any script that we inserted there. I'm not sure if it would be possible for a malicious image to interfere with a statically linked binary though.

Contributor

timthelion commented Oct 9, 2015

Oops, I just realized that modifying the run ready image Dockerfile might not work in this case because it would be possible for a malicious image to interfere with any script that we inserted there. I'm not sure if it would be possible for a malicious image to interfere with a statically linked binary though.

@timthelion timthelion added this to the 0.6 milestone Oct 9, 2015

@ruipin

This comment has been minimized.

Show comment
Hide comment
@ruipin

ruipin Oct 10, 2015

Contributor

Assuming we trust the docker image not to interfere, for example the only attacks we are worried about would come from outside WHILE using the sandboxed application (for example, browser exploits), removing SUID bits while building the dockerfiles would be enough, right?

Contributor

ruipin commented Oct 10, 2015

Assuming we trust the docker image not to interfere, for example the only attacks we are worried about would come from outside WHILE using the sandboxed application (for example, browser exploits), removing SUID bits while building the dockerfiles would be enough, right?

@ruipin

This comment has been minimized.

Show comment
Hide comment
@ruipin

ruipin Oct 10, 2015

Contributor

I added this to my dockerfile, right at the end:

# Remove SUID bits
RUN for i in `find / -not \( -path /proc -prune \) -perm +6000 -type f`; do echo -n "Removing SUID bit from $i... " && chmod a-s $i && echo "Done."; done

I know this isn't POSIX compliant and all, but I wanted something quick. It seems to work perfectly fine. I can then run bash under the subuser, and am not able to find a single SUID binary. Meanwhile, Firefox (+ fresh-player/pepper-flash Flash; and audio through Pulseaudio), Thunderbird and qBittorrent still seem to work perfectly fine.

The SUID binaries of course stop working without "sudo" (for example, 'ping www.google.com' gives an error), but that doesn't matter much.

Contributor

ruipin commented Oct 10, 2015

I added this to my dockerfile, right at the end:

# Remove SUID bits
RUN for i in `find / -not \( -path /proc -prune \) -perm +6000 -type f`; do echo -n "Removing SUID bit from $i... " && chmod a-s $i && echo "Done."; done

I know this isn't POSIX compliant and all, but I wanted something quick. It seems to work perfectly fine. I can then run bash under the subuser, and am not able to find a single SUID binary. Meanwhile, Firefox (+ fresh-player/pepper-flash Flash; and audio through Pulseaudio), Thunderbird and qBittorrent still seem to work perfectly fine.

The SUID binaries of course stop working without "sudo" (for example, 'ping www.google.com' gives an error), but that doesn't matter much.

@timthelion

This comment has been minimized.

Show comment
Hide comment
@timthelion

timthelion Oct 10, 2015

Contributor

Thank you for testing this out. I will resolve this once a good, elegant, solution appears. Which might not be untill subuser moves from working through Docker to calling runc directly.

Contributor

timthelion commented Oct 10, 2015

Thank you for testing this out. I will resolve this once a good, elegant, solution appears. Which might not be untill subuser moves from working through Docker to calling runc directly.

@SuicSoft

This comment has been minimized.

Show comment
Hide comment
@SuicSoft

SuicSoft Apr 8, 2016

@timthelion I think that subuser should not run as root (like xdg-app) because if a application escapes the sandbox then they have root (I think it is better to run my web browser outside subuser)

Also take a look at how rm -rf / could permanently brick your UEFI (2012 and newer) motherboard (I am typing this using a UEFI laptop running elementary OS freya). This needs root access to be done and makes me not run my web browser in subuser (Chrome already has a sandbox)

SuicSoft commented Apr 8, 2016

@timthelion I think that subuser should not run as root (like xdg-app) because if a application escapes the sandbox then they have root (I think it is better to run my web browser outside subuser)

Also take a look at how rm -rf / could permanently brick your UEFI (2012 and newer) motherboard (I am typing this using a UEFI laptop running elementary OS freya). This needs root access to be done and makes me not run my web browser in subuser (Chrome already has a sandbox)

@timthelion

This comment has been minimized.

Show comment
Hide comment
@timthelion

timthelion Apr 8, 2016

Contributor

First off, subuser itself does not ever run as root, Docker does. But
that is irrelivant. Docker and xdg-app both use the same sandboxing
mechanism, only xdg-app uses user-namespaces. Whether using user
namespaces or not is more secure or less secure has been debated. What
docker does as root in order to create a sandbox is:

  1. Creates a new filesystem namespace. That means that "rm -rf /" no
    longer can damage your system, becuase the files simply aren't in the
    namespace.
  2. Uses cgroups to prevent access to devices, the network, and other
    things that the container doesn't need
  3. Creates a special network "bridge" which allows the container to
    talk to the network (if need be, if a subuser isn't given network access
    permission, this bridge will be dissabled).
  4. Drops administrator capabilities and many other capabilities, thus
    restricting which actions the processes in the sandbox can perform
  5. Uses seccomp to dissable 44 infrequently used system
    calls
    ,
    to reduce the risk that the program can trick the kernel into letting it
    out of the sandbox

This makes Docker quite secure. It is not perfect, but in no way is it
significantly less secure than xdg-app's own sandbox.

Subuser further provides several security advantages:

  1. It discards all changes to the containers root filesystem each time
    the container is run
  2. It dissables access to the network unless you specifically give the
    subuser permission to access it
  3. It runs all aplications as the normal user within the sandbox
  4. It uses the xpra x11 bridge to provide secure access to x11. Unless
    you use wayland, xdg-app is %100 insecure becuause it gives full access
    to X11!

The bug report that you are commenting on, about SUID binaries, only
applies to UNTRUSTED images. But the iceweasel or chromium images that
you would run in subuser would be trusted, as they are installed
directly from debian:
https://github.com/subuser-security/subuser-default-repository/blob/latest/iceweasel/image/SubuserImagefile

The fact is, that iceweasel or chromium or whichever web browser you
choose would never be run as root in subuser! Nor would they have any
access to root, within the sandbox or outside of it.

The most likely vectors of attack against subuser and xdg-app are via
the kernel, which both have direct access too. If there is a serious
kernel bug which allows container sandboxes to be escaped, than it is
probable that both subuser and xdg-app will be effected.

On 04/08/16 16:40, Suici Doga wrote:

@timthelion https://github.com/timthelion I think that subuser
should not run as root (like xdg-app) because if a application escapes
the sandbox then they have root (I think it is better to run my web
browser outside subuser)

Also take a look at how |rm -rf /| could permanently brick your UEFI
(2012 and newer) motherboard (I am typing this using a UEFI laptop
running elementary OS freya). This needs root access to be done and
makes me not run my web browser in subuser (Chrome already has a sandbox)


You are receiving this because you were mentioned.
Reply to this email directly or view it on GitHub
#229 (comment)

Contributor

timthelion commented Apr 8, 2016

First off, subuser itself does not ever run as root, Docker does. But
that is irrelivant. Docker and xdg-app both use the same sandboxing
mechanism, only xdg-app uses user-namespaces. Whether using user
namespaces or not is more secure or less secure has been debated. What
docker does as root in order to create a sandbox is:

  1. Creates a new filesystem namespace. That means that "rm -rf /" no
    longer can damage your system, becuase the files simply aren't in the
    namespace.
  2. Uses cgroups to prevent access to devices, the network, and other
    things that the container doesn't need
  3. Creates a special network "bridge" which allows the container to
    talk to the network (if need be, if a subuser isn't given network access
    permission, this bridge will be dissabled).
  4. Drops administrator capabilities and many other capabilities, thus
    restricting which actions the processes in the sandbox can perform
  5. Uses seccomp to dissable 44 infrequently used system
    calls
    ,
    to reduce the risk that the program can trick the kernel into letting it
    out of the sandbox

This makes Docker quite secure. It is not perfect, but in no way is it
significantly less secure than xdg-app's own sandbox.

Subuser further provides several security advantages:

  1. It discards all changes to the containers root filesystem each time
    the container is run
  2. It dissables access to the network unless you specifically give the
    subuser permission to access it
  3. It runs all aplications as the normal user within the sandbox
  4. It uses the xpra x11 bridge to provide secure access to x11. Unless
    you use wayland, xdg-app is %100 insecure becuause it gives full access
    to X11!

The bug report that you are commenting on, about SUID binaries, only
applies to UNTRUSTED images. But the iceweasel or chromium images that
you would run in subuser would be trusted, as they are installed
directly from debian:
https://github.com/subuser-security/subuser-default-repository/blob/latest/iceweasel/image/SubuserImagefile

The fact is, that iceweasel or chromium or whichever web browser you
choose would never be run as root in subuser! Nor would they have any
access to root, within the sandbox or outside of it.

The most likely vectors of attack against subuser and xdg-app are via
the kernel, which both have direct access too. If there is a serious
kernel bug which allows container sandboxes to be escaped, than it is
probable that both subuser and xdg-app will be effected.

On 04/08/16 16:40, Suici Doga wrote:

@timthelion https://github.com/timthelion I think that subuser
should not run as root (like xdg-app) because if a application escapes
the sandbox then they have root (I think it is better to run my web
browser outside subuser)

Also take a look at how |rm -rf /| could permanently brick your UEFI
(2012 and newer) motherboard (I am typing this using a UEFI laptop
running elementary OS freya). This needs root access to be done and
makes me not run my web browser in subuser (Chrome already has a sandbox)


You are receiving this because you were mentioned.
Reply to this email directly or view it on GitHub
#229 (comment)

@timthelion timthelion added the Future label Apr 9, 2016

@timthelion timthelion modified the milestones: 0.6, 0.7 Jan 23, 2017

@mviereck

This comment has been minimized.

Show comment
Hide comment
@mviereck

mviereck Nov 24, 2017

You can forbid suid in container with --cap-drop=SETUID --cap-drop=SETGID. Indeed, I regulary drop all capabilities with --cap-drop=ALL and most apps still work fine.

You can forbid suid in container with --cap-drop=SETUID --cap-drop=SETGID. Indeed, I regulary drop all capabilities with --cap-drop=ALL and most apps still work fine.

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