🧠 Ansible Vault Cracking
What is it?
- Concept: Ansible Vault encrypts sensitive strings inside playbooks/roles (
!vault |YAML blocks, or entire vault files) with AES256 under a key derived from a single passphrase via PBKDF2. If a vault-protected file or string ends up somewhere readable (a misconfigured file share, a backup archive, a git repo that shouldn’t have been public), the passphrase itself is just another crackable hash — and unlike a per-account password, cracking it once decrypts every secret protected under that same passphrase. - Impact: Full recovery of every credential an Ansible playbook was configured to manage — service account passwords, application admin credentials, API keys — directly from automation files that were never meant to be readable outside the deployment pipeline.
How it works
- The Ansible Vault format self-identifies with a
$ANSIBLE_VAULT;1.1;AES256header followed by hex-encoded salt, HMAC, and ciphertext. ansible2john.py(bundled with John the Ripper) parses that into a crackable hash format understood by both John and Hashcat.- Crack it offline like any other hash — a wordlist attack is usually enough, since these passphrases are chosen by a human for convenience during automation setup, not generated.
- Once cracked, the same passphrase decrypts every vault-protected string found anywhere in that playbook/role tree — feed it back through
ansible-vault decrypt/viewto recover the actual plaintext secrets.
Exploitation
Prerequisites
- Read access to one or more Ansible Vault-encrypted files or
!vault |strings (commonly found on file shares, in backup archives, or in exposed git history)
Attack Vectors
# Strip leading YAML indentation from an inline !vault | block before treating
# it as a standalone vault file
sed -i 's/^[ \t]*//' vault1
python3 /usr/share/john/ansible2john.py vault1 > vault1.hashhashcat -m 16900 vault1.hash /usr/share/wordlists/rockyou.txt# Once cracked, decrypt every vault-protected value with the recovered passphrase
ansible-vault decrypt vault1
# non-interactively, with the passphrase piped in instead of typed:
ansible-vault view vault1 --vault-password-file <(echo '<cracked_password>')Notes
- Every vault block encrypted under the same passphrase cracks together in a single Hashcat run (one hash per line, same mode) — batch every vault string found in a playbook tree instead of cracking them one at a time.
- Ansible directories are a goldmine beyond the vault blocks themselves — inventory files,
ansible.cfg, and task/template files routinely contain plaintext credentials the author never got around to vaulting at all, sitting right next to the ones that were.
Mitigation
- Fix: Never store Ansible Vault files or strings somewhere a lower-privileged principal can read them — vault encryption protects against casual disclosure, not against an attacker who already has file access. Rotate any credential that was ever protected by a vault passphrase of uncertain strength, since offline cracking of a weak passphrase is undetectable until it’s too late.
Related Usage
| File | Created |
|---|---|
| HTB - Authority | July 23, 2026 |
References: