Add Portainer authenticated Docker API root RCE - #21745
Open
Gill-Singh-A wants to merge 10 commits into
Open
Conversation
Authenticated Portainer users can drive the Docker Engine API to create a privileged host-mounted container and chroot to root on the Docker host. Adds the exploit module and documentation.
Contributor
There was a problem hiding this comment.
Pull request overview
Adds a new Metasploit exploit module and accompanying documentation to gain host root RCE by abusing Portainer’s authenticated proxy access to the Docker Engine API (creating a privileged, host-mounted container and executing a payload via chroot /host).
Changes:
- Introduces
exploit/linux/http/portainer_authenticated_docker_rce, including Portainer auth (JWT), endpoint selection, optional image pull, privileged container creation, host payload drop/launch, and container/image cleanup. - Adds full module documentation with setup, options, verification steps, scenarios, and limitations.
Impact Analysis: isolated change; no meaningful downstream impact identified from diff.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| modules/exploits/linux/http/portainer_authenticated_docker_rce.rb | New exploit module implementing authenticated Portainer→Docker API host-root payload deployment and cleanup. |
| documentation/modules/exploit/linux/http/portainer_authenticated_docker_rce.md | New documentation describing prerequisites, usage, options, and example runs. |
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
CmdStager API unused, only generate_payload_exe needed
msutovsky-r7
reviewed
Aug 7, 2026
Co-authored-by: msutovsky-r7 <martin_sutovsky@rapid7.com>
Co-authored-by: msutovsky-r7 <martin_sutovsky@rapid7.com>
Co-authored-by: msutovsky-r7 <martin_sutovsky@rapid7.com>
Co-authored-by: msutovsky-r7 <martin_sutovsky@rapid7.com>
Co-authored-by: msutovsky-r7 <martin_sutovsky@rapid7.com>
Co-authored-by: msutovsky-r7 <martin_sutovsky@rapid7.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
New module:
exploits/linux/http/portainer_authenticated_docker_rce.Portainer proxies the full Docker Engine API to authenticated users who have access to a
managed Docker environment. Because the Docker daemon runs as root, an authenticated user can
create a privileged container that bind-mounts the host root filesystem (
/:/host) andchroots into it, gaining code execution as root on the Docker host — not merely inside acontainer.
The module authenticates to Portainer (
POST /api/auth), selects a Docker environment, ensuresa payload image is present (pulling
alpine:latestonly if missing), creates a privilegedhost-mounted container that drops and runs a native Metasploit payload under
chroot /host, andopens a session as host root. The payload is launched via the host's init (systemd) so it
survives removal of the throwaway container, which is stopped and force-removed during cleanup.
The default target is native Linux Meterpreter (x64/x86); a secondary
cmd/unixcommand targetis included.
This is an abuse of intended functionality combined with a common misconfiguration (a
network-reachable Portainer instance protected only by weak or shared credentials), so it
references the original research rather than a CVE. Original research and proof of concept by
Aman Singh Gill (Gill-Singh-A):
Related Issue: N/A
Breaking Changes
None
Reviewer Notes
Post-authentication only — no brute forcing is bundled. The host-side launcher is deliberately
defensive so it works across old and new hosts/Portainer versions: it decodes the payload with
the container image's own busybox
base64, feeds a POSIX launcher to the host/bin/shoverstdin via
chroot(no quoting pitfalls across dash/bash/busybox), probes for an exec-capabledirectory (handles a
noexec/tmp), relabels for SELinux enforcing hosts (chcon -t bin_t,best-effort), and launches via
systemd-run(falling back to plainsystemd-runon old systemdwithout
--collect, then tosetsid). Container create accepts both HTTP 200 (older Portainer)and 201.
Verification Steps
docker run -d -p 9443:9443 -p 9000:9000 -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer-ce:lts,then create the initial admin account in the web UI.
msfconsoleand do:use exploit/linux/http/portainer_authenticated_docker_rceset RHOSTS <target>;set USERNAME <user>;set PASSWORD <pass>;set LHOST <you>(for a plain-HTTP instance:
set RPORT 9000andset SSL false)check→ it reports the Portainer version and that the credentials are valid.run→ a Meterpreter session opens as root on the Docker host.getuidreturnsroot,sysinfoshows the host, and in a shellcat /proc/1/commreturnssystemd(host PID 1, not a container).[+] Removed container ...).Test Evidence
Verified as host root against multiple Portainer versions and Linux distributions
(IPs/credentials sanitized).
Portainer 2.39.5 on Fedora 44 (native Meterpreter):
Portainer 2.16.2 on CentOS 7.9 (auto image pull +
CLEANUP_IMAGE):Also verified: Portainer 2.0.1 on Ubuntu 18.04.4 (
cmd/unixtarget, host root), thecmd/unixtarget on Fedora,
RHOSTSlist/file iteration, andcheckfailure paths (rejected credentials,non-Portainer service).
msftidy,rubocop, andmsftidy_docsare all clean.Environment
portainer/portainer-ce:ltsbound to/var/run/docker.sockAI Usage Disclosure
AI-assisted (Claude Code) for code generation, documentation drafting, and test orchestration.
All behavior was verified by hand against live Portainer instances on three Linux distributions
before submission.
Pre-Submission Checklist
documentation/modules(new modules only)lib/changes)