New issue
Advanced search Search tips
Starred by 26 users

Issue metadata

Status: Started
EstimatedDays: ----
NextAction: ----
OS: Linux , Android , Windows , iOS , Chrome , Mac , Fuchsia
Pri: 2
Type: Bug

Blocked on:
issue 875901

Show other hotlists

Hotlists containing this issue:

Sign in to add a comment

Security: Chrome Sync passphrase is far too easy to bruteforce

Reported by, Mar 12

Issue description

Documentation states the following:

> With a passphrase, you can use Google's cloud to store and sync your Chrome data without letting Google read it.

That's not currently true. The encryption key for the data is derived from the passphrase using PBKDF2-HMAC-SHA1 using a fixed salt and merely 1003 iterations. This doesn't provide significant protection against bruteforcing the passphrase. Worse yet, if somebody manages to access encrypted data from multiple user accounts, the fixed salt allows bruteforcing all of them at the same time.

The sequence in code is the following:

* SyncEncryptionHandlerImpl::SetCustomPassphrase(passphrase),
* Cryptographer::AddKey({"localhost", "dummy", passphrase}),
* Nigori::InitByDerivation("localhost", "dummy", passphrase),

InitByDerivation() will derive a salt first. Given that the input is fixed however, that salt is a constant: Suser = PBKDF2("localhostdummy", "saltsalt", 1001, 8). It will then derive the encryption key as Kenc = PBKDF2(passphrase, Suser, 1003, 16). So in order to find any Google Sync accounts using "password1" as passphrase, an attacker would only need to derive an encryption key from that passphrase once and try to decrypt the data for any accounts it can access.

Even with a salt that isn't fixed but rather based on account ID for example, 1003 iterations are a way too low hurdle today. Judging by the numbers provided in, a single Nvidia GTX 1080 GPU would be able to calculate 3.2 million PBKDF2-HMAC-SHA1 hashes with 1003 iterations per second. That's enough to go through the enormous list of passwords under in less than 8 minutes. Even the passphrase of users who didn't reuse passwords and chose a passphrase with 40 bits of entropy (that's already stronger than most of them) would be guessed within two days.

I'd consider 256,000 PBKDF2-HMAC-SHA1 iterations or 100,000 PBKDF2-HMAC-SHA256 iterations the bare minimum that is still acceptable today. And each user should have their individual salt of course.
Components: Security Services>Sync Privacy
Labels: -Type-Bug-Security -Restrict-View-SecurityTeam Type-Bug
On an external post is also this note that probably bears fixing at the same time, but isn't a security issue:

"The function in question manages to run PBKDF2 four times where one run would have been sufficient. First run derives the salt from host name and username (both happen to be constants in case of Chrome Sync). This is pretty pointless: a salt doesn’t have to be a secret, it merely needs to be unique. So concatenating the values or running SHA-256 on them would do just as well. The next three runs derive three different keys from identical input, using different iteration counts. A single PBKDF2 call producing the data for all three keys clearly would have been a better idea."
tschumann@: Mind triaging this from the sync perspective?

battre@, FYI.
Status: Assigned (was: Unconfirmed)
Labels: M-69 OS-Android OS-Chrome OS-Fuchsia OS-iOS OS-Linux OS-Mac OS-Windows Pri-1
Status: Started (was: Assigned)
Just to kickstart the process, I put up a CL here: It probably won't work as-is, but hopefully we can do a sort of stone soup thing ( :)
Could you please use Argon2 or scrypt instead of PBKDF2?
Thank you for your suggestion! We are already looking at using something else than PBKDF2, however, the outcome is not clear yet, because there are multiple factors at play.
Ping: Any updates on this?
There seem to be a consensus to use scrypt instead.
The parameter selection happened to be harder than I thought (mainly because of memory). I need to do some benchmarking and check with people knowing more about memory on Android. 
Labels: -Pri-1 Pri-2
Triage ping. Does this target M69? It seems too optimistic.
It does target M69, the BP is on 19th of July.
I am meeting with Android Chrome folks tomorrow.
Issue 686929 has been merged into this issue.
sync-triage ping: any updates?
Labels: -M-69 M-70
I've reached an agreement with the security team, I need to polish the design doc, get more approvals and start implementing.

I hope that the first implementation will be in M70.
However, we won't enable it in M70 due to backward incompatibility and will wait for at list 2 milestones.
Blockedon: 875901
The optimistic plan for the implementation is still M70.
The launch itself can be done in M71 or M72 (depending on how much backward incompatibility can we allow).

davidovic@ is starting the implementation.
Issue 875901 is a tracking bug (sorry, Google-internal only).

Sign in to add a comment