Skip to main content
SAP Pentest Playbook
Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Back to homepage

Cloud Foundry Container SSH Access

Description

Cloud Foundry exposes application containers through the Diego SSH subsystem. An authenticated user can open an interactive shell or run a single command inside a running app instance via cf ssh, or via a plain ssh client using a one-time authorization code. The session runs with the app’s own privileges - no host or root access - but exposes the app’s full runtime context.

That runtime context is the point. On SAP BTP, every bound service injects its credentials into the container as the VCAP_SERVICES environment variable: XSUAA client id/secret or x509 pair, HANA Cloud connection strings, Destination- and Connectivity-service credentials. VCAP_SERVICES is the single richest credential-harvest target on the platform, and this page covers the two ways to reach it - through the container, and around it.

The “around it” path matters more than the SSH path. The CF feature flag space_developer_env_var_visibility (default: enabled) lets any Space Developer read an app’s full environment over the Cloud Controller API without SSH being enabled at all. Disabling cf ssh does not stop credential harvesting. BTP customers cannot flip that flag themselves - it needs CF platform admin scope, which no customer holds (see Cloud Foundry: SAP BTP-Specific Attack Surface).

On SAP BTP, SSH is enabled by default down to space level, unlike vanilla CF where the operator picks the deployment-wide default. Effective access still requires deployment + space + app level all “on”, but the BTP default means only the app-level toggle typically stands between a Space Developer and a shell.

Risk

Any principal holding the Cloud Foundry Space Developer role - the routine permission for deploying an app, held by developers and CI/CD service users alike - can read every service credential reachable from that space, whether or not SSH is enabled. From inside a container an attacker can additionally:

  • Extract OAuth tokens, client secrets, and certificates from bound services
  • Inspect application source, runtime configuration, and staged build artifacts
  • Execute arbitrary commands as the application runtime user
  • Reach network endpoints the container can reach but the tester cannot, including bound backing services
  • Tunnel to those backing services directly, turning an app foothold into a database session

Because Cloud Foundry treats the space as the primary trust boundary, this is not scoped to the one app compromised - it is every app and every bound service in the space.

Options

VCAP_SERVICES / VCAP_APPLICATION harvest via cf ssh

cf ssh <APP-NAME>
$ env | grep VCAP_SERVICES
$ echo $VCAP_SERVICES | jq .
$ echo $VCAP_APPLICATION | jq .

VCAP_SERVICES.xsuaa[0].credentials contains url, clientid, clientsecret - or, for certificate-based bindings, an x509 cert/key pair instead of a secret. VCAP_APPLICATION leaks org/space GUIDs, app GUID, and route URIs, which feed straight into Cloud Controller API enumeration.

Harvested XSUAA credentials are used outside the container against the tenant’s /oauth/token endpoint - see XSUAA Token Abuse for what a client id/secret is worth once extracted.

cf env - bypassing SSH controls entirely

cf env <APP-NAME>
# or directly against the API:
cf curl /v3/apps/$(cf app <APP-NAME> --guid)/env

Same VCAP_SERVICES content, no SSH involved, governed by space_developer_env_var_visibility rather than any SSH setting. Run this before concluding that a hardened cf disable-ssh posture protects an app’s credentials - it usually does not. The correct compensating control is minimizing what is in VCAP (certificate-based bindings, short-lived credentials), not the SSH flag state.

Verifying and enabling SSH

cf ssh-enabled <APP-NAME>            # app-level state
cf space-ssh-allowed <SPACE>         # space-level state (BTP default: allowed)
cf enable-ssh <APP-NAME> && cf restart <APP-NAME>

Enabling SSH requires a restart to take effect and is an audit-logged, user-visible change - coordinate before flipping it on a production app.

Non-cf-CLI access via one-time code

cf ssh-code                          # one-time authorization code
ssh -p 2222 cf:$(cf app <APP-NAME> --guid)/0@ssh.cf.<region>.hana.ondemand.com

Useful where the cf CLI is unavailable or where a raw SSH client is needed for tunneling/ProxyCommand chaining.

cf ssh -L tunnel into bound HANA Cloud / PostgreSQL

SAP publishes this itself as a legitimate developer workflow - cf ssh -L forwards a local port through the app container to a bound backing-service instance for direct DB tooling. The identical mechanism is available to anyone holding Space Developer plus SSH.

cf enable-ssh <APP-NAME> && cf restart <APP-NAME>
cf ssh -L 63306:<postgres-host-from-VCAP>:<postgres-port> <APP-NAME>
# separate terminal:
psql -h localhost -p 63306 -U <user-from-VCAP> -d <db-from-VCAP>

For HANA Cloud the tunnel is often unnecessary: HANA Cloud exposes one direct DB connection over port 443 on the public internet by default, so a harvested credential gives a working SQL session with no tunnel, VPN, or Cloud Connector involved.

hdbsql -n <host>:<port> -u <user> -p <password> -e    # -e: TLS-only, required for HANA Cloud

Where the app’s own binding is read-scoped, minting a fresh, more privileged key against the same instance is a separate move - see Service Key & Credential Store Abuse.

In-container reconnaissance

Beyond env, the container holds the staged application as it actually runs:

$ cat /home/vcap/app/package.json                    # or pom.xml, mta.yaml remnants
$ ls -la /home/vcap/app/.profile.d/                  # startup scripts, often hold exports
$ grep -rlE "(secret|password|clientsecret|api_key)" /home/vcap/app 2>/dev/null
$ cat /etc/cf-instance-credentials/* 2>/dev/null     # instance identity cert/key, if present

Container-to-container networking is not available on SAP BTP CF, so do not spend session time scanning for sibling app containers - see the C2C dead end documented in Cloud Foundry: SAP BTP-Specific Attack Surface.

For the equivalent offline technique - pulling the staged filesystem without a live session at all - see cf download-droplet on the same page.

Mitigation

  • cf disallow-space-ssh <SPACE> on production spaces and cf disable-ssh <APP> per app - but do not treat this as sufficient: space_developer_env_var_visibility independently exposes the same VCAP_SERVICES via cf env, and BTP customers cannot disable that flag.
  • Minimize what is in VCAP_SERVICES: prefer certificate-based (x509) service bindings over clientsecret bindings, and short-lived credentials over standing ones. This is the control that actually holds when SSH controls do not.
  • Restrict Space Developer role assignment; separate development, test, and production into distinct spaces and subaccounts so a foothold in one does not reach another’s bound services.
  • Segregate sensitive backing services (HANA Cloud, Credential Store) into dedicated, narrow-membership spaces.
  • Scope bound DB users to least-privilege schemas; enforce TLS-only (-e) HANA Cloud connections.
  • Never bake secrets into the build artifact - they survive into the container and the droplet regardless of SSH state.
  • Rotate every credential reachable from a space where unauthorized SSH or API access is suspected; assume full VCAP_SERVICES disclosure.

Detection and Monitoring

  • BTP Audit Log SSH session events, plus cf enable-ssh / cf allow-space-ssh configuration changes - treat enablement as an out-of-band monitored event.
  • In-container activity after cf ssh is not logged by the BTP Audit Log at all. The session’s start is visible; what happened inside it is not.
  • Direct SQL to HANA Cloud / PostgreSQL over a harvested credential or cf ssh -L tunnel is captured only by the database’s own audit mechanism (e.g. HANA’s SQL audit policies), never by the BTP platform log. Enable and centrally aggregate those separately.
  • GET /v3/apps/:guid/env calls across many apps from a single principal - the cf env harvesting signature, and the one that leaves a platform-side trace where SSH does not.
  • Monitor XSUAA token-issuance volume and source IPs for anomalies following any suspected VCAP leak.
  • See BTP Audit Log Blind Spots for the full coverage and retention caveats governing all of the above.

References