Challenge 6 ☆☆

Welcome to challenge Challenge 6. You need to guess the secret that is hidden in Java, Docker, Kubernetes, Vault, AWS or GCP.

K8s Secrets

So a ConfigMap did not do the job. But what about a K8s secret in the default namespace without RBAC?

If this challenge is enabled, you are running this from a K8s cluster. Can you use kubectl to find the secret? Or what about looking at the repository where the cluster is configured by? You might have spotted it as well if the configmap was committed to Git maybe.

Answer to solution :

You can solve this challenge by the following alternative solutions:

  1. Check the status of the secret in Git:

    • Can you see where in git we stored the secrets-secret.yml? If not, just do a search.

    • Take a look at the Data field: what can you find there? Please bare in mind that secrets are base64 encoded. Once mounted into the workloads, they are decoded.

  2. Ask nicely using Kubectl:

    • Make sure you have Kubectl installed as defined in the README.MD & make sure kubectl is configured to send commands to the right cluster.

    • Now do kubectl get secrets . Here you see all the configmaps active in the namespace you are in, which is for this app normally default (unless otherwise specified by your administrator/trainer).

    • Now do kubectl get secret funnystuff -o Yaml . Can you see the secret? What is the value of it once you base64 decocde it?

  3. Exec into the pod and get the data:

    • Make sure you have Kubectl installed as defined in the README.MD & make sure kubectl is configured to send commands to the right cluster.

    • Now do kubectl get pods. Here you see all the Pods active in the namespace you are in, which is for this app normally default (unless otherwise specified by your administrator/trainer).

    • Now for your instance of the WrongSecrets pod, do kubectl exec -it secret-challenge-<rest of the name of the pod from the prev.step> — sh.

    • Now do env | grep SPECIAL_SPECIAL_K8S_SECRET and there is your secret. Note that there is no decoding required as the secret is mounted now.

BTW: with kubectl get <resourcetype> -A gives you an overview of all the instances of such a resourcetype over all the namespaces you have access to. This shows how important it is not to give people access to every namespace in your cluster, as this might mean leaking important config/items to them.

Why secrets need RBAC so badly

K8s Secrets are designed to host secrets. As you can tell by solving the challenge and careful reconnaissance secrets are already base64 encoded so that they can contain encrypted binary data.

Secrets should, unless encrypted (and better yet, even not then), obviously not be committed to git, which is one of the first mistakes made here as we then end up with the same problems as described in the previous challenges.

Most importantly: RBAC should be really tight around secrets: only the processes which requires the actual secret should be able to read it and a very limited of other roles to maintain the secret.

And then there is the storage of the K8s cluster where the secrets are now hosted by. This is not encrypted at the moment and could be misused as well.

So: K8S secrets are not a bad idea. They do, however, require a proper configuration of the K8s cluster hosting them in order to be more effectively secured.

Last but not least: we could easily exec into the container, to grep the ENV vars with the secret. This has to do with 3 things:

  • we are allowed to do so by means of RBAC, which should not be your normal case in PRD: otherwise everybody of your organization can poke around in the container.

  • we are having executables within the container (sh/openssl/etc) which we can execute to setup a shell. Stripping your container from any non-necessary binary can help to reduce attack-surface and make it harder for any attacker that did an RCE at your container to jump to other places within the container to further gain execution.

  • we have exposed the configmap as an ENV. This means that anybody who got to the container runtime within the pod can now dump the secret. We brought the secret close to the consumer, but maybe not close enough yet (e.g. the app only).


0