Skip to content

Instantly share code, notes, and snippets.

@gquere
Last active October 28, 2022 07:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gquere/17ef5c22cf276bd7d822ee8e09ce58c8 to your computer and use it in GitHub Desktop.
Save gquere/17ef5c22cf276bd7d822ee8e09ce58c8 to your computer and use it in GitHub Desktop.
Recursively dump Hashicorp Vault secrets
#!/usr/bin/env python3
import argparse
import urllib3
import requests
import json
import sys
# SUPPRESS WARNINGS ############################################################
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
# FCTS #########################################################################
def recurse_keys(url, keys):
output = {}
for key in keys:
if key[-1] == '/': # folder
r = s.get(url + key + '?list=true', headers=headers, proxies=proxies, verify=False)
print(r.text)
if r.status_code == 404:
print('404 on {}'.format(url + key + '?list=true'))
return
if r.status_code == 403:
print('403 on {}'.format(url + key + '?list=true'))
continue
keys = json.loads(r.text)
val = recurse_keys(url + key, keys['data']['keys'])
output.update({key: val})
else:
url2 = url.replace('/metadata/', '/data/') # kv v2
r = s.get(url2 + key, headers=headers, proxies=proxies, verify=False)
if r.status_code == 403:
print('403 on {}'.format(url + key + '?list=true'))
continue
secrets = json.loads(r.text)
output.update({key: secrets['data']})
return output
# MAIN #########################################################################
parser = argparse.ArgumentParser()
parser.add_argument('url', type=str)
parser.add_argument('-t', '--token', type=str, required=True)
parser.add_argument('-p', '--proxy', type=str)
parser.add_argument('-m', '--mountpoint', type=str)
args = parser.parse_args()
base_url = args.url
proxies = {}
if args.proxy:
proxies = {'https':args.proxy}
headers = {'X-Vault-Token':args.token}
url = base_url + '/v1/sys/mounts' # list mounted secrets engines
s = requests.Session()
s.verify = False
r = s.get(url, headers=headers, proxies=proxies, verify=False)
print(r.text)
mountpoints = json.loads(r.text)['data']
all_secrets = {}
for mountpoint in mountpoints:
if mountpoint == 'sys/' or mountpoint == 'cubbyhole/':
continue
if args.mountpoint and mountpoint != args.mountpoint:
continue
print('[+] Trying mountpoint {}'.format(mountpoint))
try:
# key-value v2 needs "metadata" in the request path
if mountpoints[mountpoint]['options']['version'] == '2':
mountpoint = mountpoint + 'metadata/'
except KeyError:
pass
try:
all_secrets.update(recurse_keys(base_url + '/v1/', [mountpoint]))
except Exception as e:
print(e)
with open('secrets.json', 'w+') as f:
f.write(json.dumps(all_secrets))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment