Attacks on Browser Password Managers: How Credentials Are Extracted from Chrome, Firefox, and Edge

WILD

Administrator
Staff member
ADMIN
SELLER
SUPREME
MEMBER
Joined
Jan 21, 2025
Messages
219
Reaction score
637
Deposit
0$
1776608171047.png
When I log into a workstation at a Red Team organization, the first thing I do isn't the domain controller or lateral movement via SMB. The first target is the %LOCALAPPDATA%\Google\Chrome\User Data\Default\ directory. The Login Data file is a couple of megabytes, but inside are the keys to everything: corporate portals, VPN accounts, cloud consoles. According to ReliaQuest, browser credential dumping accounted for 21% of all credential theft incidents among their clients in 2023. Attacks on browser password managers are one of the most common and effective credential access techniques in the attackers' arsenal. Low barrier to entry, high payoff.

In MITRE ATT&CK, this technique is documented as Credentials from Password Stores (T1555), Credential Access, with a subtechnique called Credentials from Web Browsers (T1555.003). It is used by dozens of APT groups, from APT33 and APT41 to Kimsuky and LAPSUS$. Next, we'll examine how the password stores of three major browsers are structured, how attackers crack them, and—critically—what artifacts remain for Blue Team.
Password Storage Architecture in Chrome, Firefox, and Edge
Before discussing extracting passwords from Chrome or hacking the Firefox password manager, it's worth understanding what exactly we're attacking. Each browser stores credentials differently, but all three use local files that can be accessed without a single network request. Chrome and Edge: SQLite plus DPAPI
Chrome and Edge (both based on the Chromium engine) use an identical storage scheme. The main file is the Login Data SQLite database, located at the following paths:

Chrome: C:\Users\<Username>\AppData\Local\Google\Chrome\User Data\Default\Login Data
Edge: C:\Users\<Username>\AppData\Local\Microsoft\Edge\User Data\Default\Login Data

Cookies are nearby, in the Network\Cookies subfolder. Both files are regular SQLite3 databases that can be queried directly. According to the MITRE ATT&CK documentation (T1555.003), to retrieve stored credentials, simply use:
SQL:

SELECT action_url, username_value, password_value FROM logins;

The password_value field contains an encrypted blob. Modern versions of Chrome (v80 and later) use a two-layer encryption scheme:

AES-256-GCM - the password is encrypted with a symmetric key
DPAPI (Data Protection API) - the AES key itself is protected via Windows DPAPI

The AES key is located in the Local State (JSON) file at os_crypt.encrypted_key. It is encoded in Base64 and encrypted via DPAPI. To decrypt it, an attacker calls CryptUnprotectData, which only works in the context of the user who created the key. This is key: decrypting Chrome passwords requires code execution in the target user's session. There's no other way.

Older versions (before v80) used direct DPAPI protection without an intermediate AES key – each password_value was decrypted directly via CryptUnprotectData.
Firefox: NSS and Native Cryptography
Firefox takes a different approach. Instead of DPAPI, we use the proprietary NSS (Network Security Services) cryptographic library. Key profile files:

key4.db - master key database (SQLite, replaces the deprecated key3.db)
logins.json - JSON with encrypted logins and passwords
cookies.sqlite - cookie database

Profile path: C:\Users\<Username>\AppData\Roaming\Mozilla\Firefox\Profiles\<random>.default-release\

Passwords in logins.json are encrypted using the NSS PKCS#11 SDR mechanism (3DES-CBC, OID 1.2.840.113549.3.7). Firefox 58 (2018) switched from key3.db (BerkeleyDB) to key4.db (SQLite). Within key4.db, the master key (NSS softtoken) can be protected with AES-256-CBC instead of 3DES, but the passwords themselves in logins.json are still decrypted using PK11SDR_Decrypt. Extraction tools (LaZagne, firepwd) determine the key protection algorithm based on the OIDs in the ASN.1 structure of key4.db. The encryption key is stored in key4.db, protected by an optional master password. If the user hasn't set one (and most don't), decryption is trivial: just initialize the NSS context with the profile path, and that's it.

This is precisely the feature exploited by stealer malware: BeaverTail, according to MITRE ATT&CK, simply collects key3.db, key4.db, and logins.json from /.mozilla/firefox/ for subsequent exfiltration.
Extraction Practice: How Browser Credential Theft Works
Now, on to the specifics. Below is an analysis of the key artifacts and techniques I use during post-exploitation, and then what exactly these actions leave in the logs.
If a master password is set, an attacker can brute-force it—key4.db contains a hash for verification. However, in practice, in red team campaigns, I've seen less than 5% of users set a master password. There's no point in explaining why people don't set one—everyone already knows.
Attacks on Edge Password Storage
Edge uses the same architecture as Chrome (Chromium-based), so the attack is identical. The only difference is the file paths:

Chrome Edge Artifact
Login Data AppData\Local\Google\Chrome\User Data\Default\Login Data AppData\Local\Microsoft\Edge\User Data\Default\Login Data
Local State AppData\Local\Google\Chrome\User Data\Local State AppData\Local\Microsoft\Edge\User Data\Local State
Cookies ...\Default\Network\Cookies ...\Default\Network\Cookies
Attacker's Toolkit: From LaZagne to Mimikatz
The T1555.003 technique is so popular that there's a whole zoo of tools specifically designed for it. Here's what's actually used in attacks (according to MITRE ATT&CK and Unit42):

LaZagne is an open-source Python utility that extracts credentials from Chrome, Firefox, Edge, Opera, and dozens of other applications. Used by APT33, OilRig, and Leafminer. The lazagne.exe browsers command will give you all your saved browser passwords in seconds.

Mimikatz (dpapi module) - In addition to Kerberos attacks, Mimikatz can work with DPAPI: extract master keys and decrypt blobs. It's especially dangerous when combined with access to the domain controller where the DPAPI backup key is stored – with it, you can decrypt the data of any user in the domain.

HackerBrowserData - A Go utility from GitHub that exports credentials, cookies, history, and bookmarks from all major browsers. It's convenient for the red team because it compiles into a single binary with no dependencies. Just grab it, run it, and you're done.

Empire / Cobalt Strike - Post-exploitation frameworks with modules for browser credential dumping. Empire extracts passwords from Firefox and Chrome using built-in PowerShell modules. Cobalt Strike - via BOF (Beacon Object Files).

Metasploit - the post/windows/gather/enum_chrome module collects history, cookies, and autofill data from Chrome, but its support for decrypting passwords from modern versions (v80+, AES-256-GCM) can be limited depending on the framework version. For full password extraction, it's often easier to run SharpChrome or LaZagne through execute. For Firefox, there's post/multi/gather/firefox_creds, although compatibility with modern key4.db (AES-256-CBC) should also be checked for the specific Metasploit version.

Stealer malware is a separate category. Emotet, TrickBot (pwgrab32 module), Lumma Stealer, RedLine, and Azorult all include modules for stealing browser passwords. According to MITRE ATT&CK, Lumma Stealer extracts credentials from multiple browsers simultaneously, and Emotet distributes specialized grabber modules.
What's left in the logs: detecting browser password theft
Switching to Blue Team. Every attacker's action leaves a trace—if you know where to look.
File access to credentials databases
The most obvious indicator is a process other than the browser accessing the Login Data, logins.json, or key4.db files. Enable file access auditing (Windows Event ID 4663) for the following paths:
%LOCALAPPDATA%\Google\Chrome\User Data\Default\Login Data
%LOCALAPPDATA%\Microsoft\Edge\User Data\Default\Login Data
%APPDATA%\Mozilla\Firefox\Profiles\*\logins.json
%APPDATA%\Mozilla\Firefox\Profiles\*\key4.db
%LOCALAPPDATA%\Google\Chrome\User Data\Local State

Sigma-правило для детектирования аномального доступа:


YAML:

# Пример для демонстрации концепции
title: Suspicious Access to Browser Credential Files
id: d7c9b22a-4f3e-4a1b-8c55-credential-access
status: experimental
description: Detects non-browser process accessing browser credential stores
logsource:
category: file_access
product: windows
detection:
selection:
TargetFilename|contains:
- '\Login Data'
- '\logins.json'
- '\key4.db'
- '\cookies.sqlite'
- '\Local State'
filter_browsers:
Image|endswith:
- '\chrome.exe'
- '\msedge.exe'
- '\firefox.exe'
- '\brave.exe'
- '\opera.exe'
filter_system:
Image|startswith:
- 'C:\Windows\System32\'
condition: selection and not filter_browsers and not filter_system
falsepositives:
- Browser update processes
- Legitimate backup software
level: high
tags:
- attack.credential_access
- attack.t1555.003

CryptUnprotectData Calls
The CryptUnprotectData call is the heart of DPAPI decryption. Monitoring via ETW (Event Tracing for Windows) or endpoint solutions allows you to catch decryption attempts. What to look for:

The process calling CryptUnprotectData is not chrome.exe, msedge.exe, or firefox.exe
Bulk calls (a legitimate browser decrypts one password at a time during autofill, while an attacker decrypts hundreds in a row)
powershell.exe or python.exe calling crypt32.dll via P/Invoke or ctypes

PowerShell Logging
As recommended by Exabeam experts, enable PowerShell Script Block Logging (Event ID 4104) and Module Logging (Event ID 4103). This allows you to catch scripts like Get-ChromePassword.ps1 accessing Login Data files.

KQL query for Microsoft Sentinel - detecting suspicious access to credential files:

Код:

// Пример для демонстрации концепции
DeviceFileEvents
| where Timestamp > ago(24h)
| where FileName in~ ("Login Data", "logins.json", "key4.db", "Local State")
| where InitiatingProcessFileName !in~ ("chrome.exe", "msedge.exe", "firefox.exe", "brave.exe")
| where InitiatingProcessFileName !in~ ("svchost.exe", "SearchProtocolHost.exe")
| project Timestamp, DeviceName, InitiatingProcessFileName,
InitiatingProcessCommandLine, FileName, FolderPath
| sort by Timestamp desc

Процессные аномалии​

Отслеживайте запуск известных инструментов:


Код:

// Пример для демонстрации концепции
DeviceProcessEvents
| where Timestamp > ago(7d)
| where ProcessCommandLine has_any ("lazagne", "hackbrowserdata", "browserpassview",
"sharpchrome", "enum_chrome", "dpapi::chrome")
| project Timestamp, DeviceName, AccountName, ProcessCommandLine, InitiatingProcessFileName
 
Top Bottom