Following a Config Pointer to an Environment File to Leak an Admin Token

Web & API Security Level 3/5 ~5 min 2026-07-04

The challenge

You have a shell on app01 as the nginx user. The app config does not store the admin token directly - it reads it from an environment file somewhere on disk. Follow the trail from the config to that file and submit the admin token.

What you'll learn

  • Recognise when a config file references a secret instead of holding it
  • Locate a systemd EnvironmentFile and the env file it loads
  • Read an env file to extract a credential like ADMIN_TOKEN
  • Use grep across /etc to find a secret when the path is not obvious
  • Apply the fix: load secrets from a vault or scoped secret store at runtime

Skills tested

Shell recon and file enumerationConfiguration and service-unit reviewCredential discoveryLinux post-exploitation

Prerequisites

  • Comfortable with basic shell commands (ls, cat, grep)
  • Can read a Python config file and a systemd service unit

How it works

Mature apps try not to hardcode secrets directly in source. Instead the code reads a secret from the process environment, and something else - a systemd unit, a Docker env_file, or a shell wrapper - is responsible for putting that value into the environment at start-up. In this challenge config.py calls os.environ.get('ADMIN_TOKEN') and even leaves a breadcrumb: SECRET_ENV_PATH = '/etc/acme/secret.env'. The secret is real, it is just one file away.

That indirection improves hygiene in version control - the repository never contains the token - but it does nothing once an attacker has read access to the host. The env file still sits on disk in plain text, and the service unit declares exactly where: EnvironmentFile=/etc/acme/secret.env. Anyone who can read that path reads the token. A foothold as the service user is usually enough, because the file has to be readable by that very user for the service to start.

The skill being exercised is chaining one artifact to the next: a config that names a path, a service unit that confirms the path, and finally the env file that holds the value. When the path is not spelled out, a recursive grep such as grep -r ADMIN_TOKEN /etc jumps straight to the line. The token is stored in clear text because the app must send it verbatim, so reading the file is all it takes.

Common mistakes

  • Stopping at the config file. config.py does not contain the token - it only names the path. Solvers who grep just the app directory miss the secret entirely.
  • Ignoring the service unit. The systemd unit's EnvironmentFile= line is the strongest pointer to where the secret is loaded from; skipping /etc/systemd means guessing.
  • Assuming /etc is off-limits. The env file must be readable by the service user, so a low-privilege shell as that user can usually read it.
  • Grepping for the wrong keyword. Searching for password finds the DB password, not the admin token - grep for ADMIN_TOKEN specifically.

How to defend against it

Moving a secret from source into an on-disk env file is a half-measure; the durable fix keeps the value off the host filesystem entirely:

  • Fetch the token at start-up from a secret manager - a vault service or your cloud provider's secrets store - and hold it only in process memory.
  • If an env file is unavoidable, lock it down with chmod 600 and a dedicated owner so a compromised service user cannot read it.
  • Scope and rotate the token so a single leak is short-lived and limited in blast radius.
  • Audit reads of secret paths and alert on access from unexpected users or processes.

Treat any token that has touched a readable file on a shared host as already burned: rotate it and reissue, since deleting the file does not undo a read that already happened.

Full solution

Pro and Max members unlock the complete step-by-step walkthrough.

Go Pro

Community stats

59 completions
79% success rate
Malekith First blood

Related Daily Hacks

15,000+ Hackers 100+ Labs & Courses Free
Start Hacking Free