Pass-ta-key: When "Passwordless" Doesn't Mean "Accessless"
I spent most of Tuesday chasing a ghost in our dev environment. A developer in our Bengaluru office reported some weirdness with their GCP console—specifically, an SSH key they didn't recognize appearing in their metadata. I initially figured it was a botched automation script or a misconfigured terraform run. Then I saw the logs. The access didn't come from a leaked service account key or a phished password. It came from a session that looked perfectly legitimate, authenticated via a passkey that was supposed to be hardware-backed and un-phishable.
We’re seeing a shift in how infostealers like Lumma and Meduza operate. They aren't just looking for Login Data anymore. They've moved on to the Web Data file. This is where the New Pass-ta-key attacks let malware hijack Google-synced passkeys, effectively turning a security feature into a persistence mechanism for attackers. If you're relying on the browser to keep your passkeys safe and synced, you're essentially betting your entire infrastructure on the browser's local encryption, which—as it turns out—malware running in the user's context can bypass quite easily.
The Failed Approach: Why You Can't Just Rsync a Vault
When I first started digging into how these passkeys were stored, I thought I could just pull a copy of the SQLite database and analyze it on my own machine. I ran a quick rsync to grab the profile directory from a test VM I'd infected with a neutralized sample.
# Attempting to copy the Chrome profile to a lab machine for analysis
scp -r user@compromised-host:~/.config/google-chrome/Default/Web\ Data ./lab_analysis/ sqlite3 ./lab_analysis/Web\ Data "SELECT name, credential_id FROM passkeys;"
I could see the metadata. I saw the names of the services—GCP, AWS, GitHub. But the actual secret material? Total garbage. Chrome uses OS-level APIs to encrypt the sensitive fields. On Windows, it’s DPAPI; on macOS, it’s the Keychain. If you move the file to another machine, the master key is gone. The data remains ciphertext. I hit exit code 255 on my custom extraction script because the decryption hook failed to find the local system's secret.
This is the "security" we've been relying on. It stops a casual thief who steals a laptop, but it does absolutely nothing against malware already running as the user. The New Pass-ta-key attacks let malware hijack Google-synced passkeys by simply asking the OS to decrypt the data while the session is active, or by hijacking the synchronization token itself to re-sync the vault to an attacker-controlled browser instance.
How Malware Hijacks Google-Synced Passkeys
The "Pass-ta-key" technique is basically "Pass-the-Hash" but for the modern passwordless era. The infostealers we’re seeing in the wild, particularly those targeting Indian IT-ES employees through "cracked" software ads, are getting very good at this. They exploit the fact that Google Chrome's synchronization mechanism is designed for convenience, not high-assurance isolation.
The malware typically enters via a standard vector—lately, it's been CVE-2023-4863 (the libwebp heap buffer overflow) or just straight-up social engineering. Once it's in the user context, it doesn't need root or admin privileges to talk to the browser's data files. It just needs to be the same user.
$ sqlite3 ~/Library/Application\ Support/Google/Chrome/Default/Web\ Data "SELECT name, credential_id FROM passkeys;"
The malware runs this, identifies the credential_id, and then uses the browser's own internal functions—or the Google Sync API—to export the data. Because the browser is already authenticated to the user's Google account, the "Sync" feature happily replicates the hijacked passkeys to the attacker's "new device." Once the attacker has the passkey in their own browser, they can authenticate as the victim to any service that doesn't enforce hardware-bound attestation.
The Mechanics of the Sync Vulnerability
The core problem is the Chromium-based synchronization mechanism. When you enable "Sync," Chrome creates a vault that is protected by a key derived from your Google credentials. While Google has implemented "Application Bound Encryption" to prevent other apps from reading Chrome's secrets, this defense is brittle. If malware can inject code into the Chrome process or simply simulate user input to trigger a sync/export, the encryption is moot.
We tracked a specific instance where a dev’s GCP console was accessed. The attacker didn't have the dev's physical YubiKey. They didn't need it. The passkey was a "synced passkey" stored in the Google Password Manager. By hijacking the Google account session, the attacker synced the passkeys to their own machine, which then allowed them to log in to GCP as the dev. Once inside, they did this:
gcloud compute instances add-metadata [INSTANCE_NAME] --metadata ssh-keys="user:$(cat ~/.ssh/id_rsa.pub)"
Now they have persistent SSH access that doesn't even rely on the passkey anymore. It’s a classic pivot. The New Pass-ta-key attacks let malware hijack Google-synced passkeys, and from there, the cloud environment is wide open.
Why Traditional MFA is Failing Here
We’ve been telling everyone that MFA is the cure-all. But passkeys are MFA. They combine something you have (the device/key) with something you are (biometrics) or know (PIN). The issue is the "something you have" has become a software file that moves between devices via the cloud.
When a passkey is synced, the "hardware-bound" property is lost. The biometric protection (TouchID, Windows Hello) only protects the local access to the vault. It doesn't protect the data while it's being synced to Google's servers or when it's being downloaded to a new, potentially malicious device. If an attacker gets your Google session, they get your passkeys. And since passkeys are designed to be persistent, you can't just "change your password" to fix it. You have to revoke every single individual passkey in every single service you use.
Detection and Mitigation in the Real World
Detecting this is a nightmare. To the server, the login looks like a legitimate FIDO2 authentication. The only way to catch it is on the endpoint or by monitoring for weird sync behavior. I’ve started rolling out auditd rules to monitor access to the Chrome profile files, though it's noisy as hell, highlighting the managed access/audit tradeoffs inherent in endpoint-heavy security models.
# Auditd rule to monitor Chrome profile access
-w /home/admin/.config/google-chrome/ -p wa -k chrome_profile_change
You can also try to catch the theft in progress by watching for unauthorized read attempts on the SQLite files by processes that aren't Chrome, but modern infostealers are stealthy—they often wait for Chrome to be open and then use debugging ports or process injection.
For our high-value targets (sysadmins, devops), I've started forcing a move back to hardware-only keys that are not syncable, often following this guide on SSH CAs to maintain control. In sshd_config, we're getting stricter to mitigate what happens after a passkey is hijacked.
# /etc/ssh/sshd_config
Mitigate hijacked passkey/key access by forcing hardware MFA
AuthenticationMethods publickey,keyboard-interactive PubkeyAuthentication yes PasswordAuthentication no
By forcing keyboard-interactive alongside the publickey, we can at least demand a secondary TOTP or a physical tap on a YubiKey that isn't stored in the browser vault. It’s a friction-heavy compromise, but after seeing a "secure" passkey get walked out the front door by a libwebp exploit, I'm not taking chances.
The Long-term Risk of Stolen Digital Identities
The scariest part of this is the revocation problem. If a password is stolen, I reset it. If a session cookie is stolen, I clear sessions. But if a passkey is hijacked via Pass-ta-key, that credential is valid until I manually go into GitHub, AWS, GCP, and my bank to delete that specific credential_id. Most users have no idea how to do this. Most admins don't even have a list of which passkeys their users have registered.
We tried to audit our SSH keys using the ssh-keygen tool to see if we could find the hijacked keys on our servers.
ssh-keygen -l -E sha256 -f ~/.ssh/authorized_keys
But here’s the gotcha: if you’re using GCP OS Login or AWS Instance Connect, the keys added via the console won't show up in the local ~/.ssh/authorized_keys file. They are injected at runtime. You have to audit the cloud provider's metadata logs, which is why we are moving away from static keys in favor of ephemeral cloud identities.
journalctl -u ssh --since "1 hour ago" | grep "Accepted publickey"
Checking the logs showed a login from an IP in a completely different region using a key that was added just minutes prior via the web console. The chain of events was clear: Malware -> Google Account Sync -> GCP Console -> SSH Key Injection.
Where Do We Go From Here?
The industry is pushing hard for passkeys, and they are better than passwords for 99% of people. But for those of us managing infrastructure, the "synced" part of the equation is a massive liability. The New Pass-ta-key attacks let malware hijack Google-synced passkeys because we've prioritized convenience over the "something you have" requirement of MFA.
Google has been pushing updates to Chrome to harden the Web Data encryption, but as long as the browser has to be able to decrypt it for the user, malware sitting in that same user context will eventually find a way. The only real fix is hardware-bound keys that cannot be exported, but good luck telling a fleet of 500 developers they have to carry a physical token and can't use their phone's biometrics anymore.
I'm currently looking into whether we can use Enterprise Policies to disable Passkey syncing entirely while still allowing local Passkey usage. It’s an undocumented mess right now. I'm also wondering if we can trigger a re-authentication challenge whenever a new device attempts to sync the passkey vault—something more robust than just a "new login" email that everyone ignores.
The next experiment is to see if we can detect the specific SQLite read patterns of Lumma versus a standard Chrome sync operation. If we can pattern-match that, maybe we can kill the process before the vault is exfiltrated. But that’s a project for next week. For now, I’m just revoking keys and wondering why we keep building these "secure" systems with such obvious backdoors for the sake of "seamless" experiences.
