Recently, I've stumbled across an example of a chrome password extractor on reddit (1). Since the original one was written in Python I thought it will be fun to implement similar thing in Rust.

Usually, if we want to show a saved password in Chrome we have to insert windows user password. Passwords are stored in the SQLite database usually located in:

%LOCALAPPDATA%\Google\Chrome\User Data\Default\Login Data

Interestingly, since passwords are encrypted using Crypt­Protect­Data Windows function, logged in user can just directly decrypt them using CryptUnprotectData function without providing further credentials. Of course, this means that we assume that we have access to PC and there is an argument to be made if this is a realistic attack scenario since we have access anyway (but it is interesting to know).

After we connect to the database we can simply execute:

SELECT action_url, username_value, password_value FROM logins

take the extracted passwords and decrypt them.

Many browsers are based on Chrome and use a slightly modified path and name of the database file. A good list of these browsers and names of DB files they use can be found here.

The most interesting part of the whole program was how to handle SQLite connection. The original program assumes that Chrome is closed which doesn't make much sense (but does make our program simpler). Problem is that Chrome, when running, acquires lock on the database and running any query will result in an error.

One simple, but crude, solution is to simply copy database file and try to access copied version. This will work but it does require writing to disk, which is not ideal.

Browsing to SQLite docs, for the simpler way I've found:

immutable=1

The immutable query parameter is a boolean that signals to SQLite that the underlying database file is held on read-only media and cannot be modified, even by another process with elevated privileges. SQLite always opens immutable database files read-only and it skips all file locking and change detection on immutable database files. If these query parameter (or the SQLITE_IOCAP_IMMUTABLE bit in xDeviceCharacteristics) asserts that a database file is immutable and that file changes anyhow, then SQLite might return incorrect query results and/or SQLITE_CORRUPT errors.

this means that if we are using URI to access DB, we can just specify immutable=1 and all checks about DB being locked are skipped.

Full source code can be found here.

Rust ecosystem has matured quite a bit, tools like cargo, rustfmt and clippy provide really great way to improve your code and manage your project. With clippy we can simply run:

cargo clippy --all -- -W clippy::all -W clippy::pedantic -W clippy::restriction -W clippy::nursery -D warnings

to find and fix many common mistakes.

- F3real