Bruteforcing my own Bitwarden vault

📆
🏷
security, bitwarden

But, as the title suggests, there is an other option: bruteforcing. My masterkey actually is a passphrase comprised of a number of words. I was pretty sure about which words most likely have been lost. I also had a list of candidates. Basically I assumed that I have no more than to two words which could have been wrong. So I searched my system for the wordlist used by bitwarden to generate passphrases and started to assemble a wordlist with likely candidates for bruteforcing. My final wordlist has 187735 candidates. I was also able to extract my keyHash from data.json and with a little help of a friend I also found how Bitwarden was generating the keyHash saved on disk which basically is

pepper  = pbkdf2(sha256, pass = masterkey, salt = email,     rounds = 100000)
keyHash = pbkdf2(sha256, pass = pepper,    salt = masterkey, rounds = 1)

googling for a bitwarden specific bruteforcer was unsuccessful so the plan grew on me to write my own. As I still had access to the vault I was under no pressure at least not on the time front. Some hours later bw_brute.py has been conjured and tests with a list of one thousand entries finished in 9s on my 8 core, 16 threads Ryzen CPU which left me with some hope.

In the meantime remembrance kicked in and I was able to successfully remember my masterkey. This greatly helped in finalising the tool, eliminating some stupid bugs and working on the multiprocess part of the script (the above benchmark was done with the final version). So I ran the tool and lo and behold, nothing was found! After giving it some thought I found one fatal assumption in my approach: the words used for constructing my own wordlist. The vault itself is older than bitwarden itself and I migrated from another password manager to Bitwarden. I also – bad I know – recycled my old passphrase and obviously the wordlist used by the old password manager was different than what Bitwarden was using. As I was still curious about the performance of bw_brute.py I put the correct masterkey at roughly the position it would have been. 7 minutes and 16 seconds or 51789 attempts later I was able to “recover” my lost passphrase :-)

Having my data back I can now safely say that this was a frightening but also a funny experience and I am happy that I both remembered the correct masterkey and to successfully bruteforce myself!

--EOF