How Chrome stores your passwords (Windows & macOS), and why you (still) shouldn’t let it

As part of some degree research I recently read an article called “How Browsers Store Your Passwords (and Why You Shouldn’t Let Them)” which runs through how the major web browsers store your passwords. I won’t go over the details here so just go and read that article if you’re interested. However as that was written in 2013 I figured that things must have changed and was interested to see if it was still possible to easily extract the passwords from the SQLite database, which Google Chrome uses to store its passwords. Once I completed this I was interested in finding out about how macOS handles this and to see if this was also possible using Chrome on a Mac.

I set up a quick test environment using a Windows 10 VM and installed the latest version of Google Chrome (76 at this time).

About Chrome

I then created a test_user account on a site that I own and closed Chrome to release the database (Chrome locks its database whilst it’s running and this causes issues with the Python script). The database (%APPDATA%\Local\Google\Chrome\User Data\Default\Login Data) was checked using a SQLite DB Browser app to ensure that it contained the test_user account details.

Windows 10 database contents

As noted in the original article, Chrome encrypts this password using the Windows API function CryptProtectData. This function gets called in the user context of the machine and only a user with the same credentials as the user who encrypted the data can decrypt it. This encryption / decryption also must be carried out on the same machine (Microsoft, 2018).

With this in mind I then installed Python (2.7 in this case) along with pywin32 which is used by the POC to make Windows API calls. I then ran the POC and received errors about the database being locked, closing Chrome cleared these and the script return the results below.

Windows 10 results

Google Chrome on macOS

Chrome running on macOS saves its passwords in the “~/Library/Application Support/Google/Chrome/(Default|{PROFILE})/Login Data” SQLite database. Examining this file in DB SQLite Browser shows the same database structure as the Windows version.

macOS database contents

The password is encrypted with AES-128-CBC, where a PBKDF2 hash value is used to create the key. The PBKDF2 hash is created with a 128-bit IV, a salt of “saltysalt”, 1003 iterations, and a defined password (Chromium Source Code). This password is stored in the user’s keychain as Chrome Safe Storage (bufferovernoah, 2016).

macOS database contents

The bufferovernoah article states that at the time of writing (2016) OSX didn’t prompt for a password when running security find-generic-password -ga Chrome on the command line to access the Chrome Safe Storage data from the keychain, so it would be fairly trivial to have a Python script brute-force the prompt and eventually have the user click “allow” to retrieve this information. However at this time macOS does prompt for a password, which is good news.

So at this point we have a SQLite database of credentials with encrypted passwords. We know the encryption method, the key derivation function, we have the salt constant, the key length, number of iterations and we can get the password from Chrome Safe Storage which is used in the PBKDF2 key derivation function. Using this Python script (thanatoskira), with that information, it’s possible to decrypt the stored passwords in macOS Google Chrome.

macOS results

Whilst this isn’t a vulnerability, it is concerning especially in Windows. Let’s say a user gets phished and accidently installs malware on their machine. This malware would easily run in the user context and could therefore extract all of Chrome’s saved passwords and send them off to a C&C.

Chrome on macOS is a little more secure because the user would need to enter the keychain password to allow any scripts access to Chrome Safe Storage. Without the password stored in there it would be computationally very difficult to break the AES encryption.

There’s nothing new here and I’m simply just re-trying what was originally researched in the above articles but I was interested to see if the Windows POC still works 6-years later, and it does.

RaiderSec, 2013: How Browsers Store Your Passwords (and Why You Shouldn’t Let Them)
Microsoft, 2018: CryptProtectData function
Chromium, accessed 2019: Chromium Source Code
bufferovernoah, 2016: Decrypting Google Chrome Passwords on macOS / OS X
thanatoskira, accessed 2019: OSXChromeDecrypt