The release notes for 4.6.1 include the statement:
Improves verification and authentication of communication with the 1Password browser extension to address an issue reported by Tavis Ormandy of Google Project Zero. Users should update promptly.
I would like to explain a bit more about what that is. I expect that most people reading this will be unaware that some people have been waiting eagerly since the beginning of August to know what security issue Tavis Ormandy reported to us. But those who have been waiting have been waiting very eagerly for the explanation.
The vulnerability that Tavis Ormandy of Google's Project Zero reported to us at the beginning of August could only be exploited locally on Windows systems by another user of that same machine. A successful exploit of it on those systems would have led to capture of many of a victim's website usernames and passwords. For that portion of 1Password users who this might have affected, this was a serious vulnerability. We have no reason to believe that this vulnerability was ever exploited.
The solution is what everyone is seeing. We now require the user to do a one-time approval of each browser extension and after that is set up the browser extension and 1Password Agent will share a secret that they will use to prove that each message and request between the browser extension and 1P Agent involves a previously approved extension.
We've long had measures in place to prevent some user, Patty let's say, from running a fake browser extension that could talk to Molly's 1Password Agent. Indeed, more than a year ago we wrote about some of the challenges in designing those measures.
One of those measures involves the Agent trying to figure out who the "owner" of the other end of the connection is. When Molly is running 1Password Agent and a browser extension tries to talk to Agent, Agent will ask the operating system (Windows or Mac) about the process at the other end of the connection. If Agent is owned by Molly, it should only talk to extensions that are owned by Agent. It should refuse to talk to an extension that is running in a process owned by Patty.
The details of what the Agent has to ask the operating system and what the operating system can answer depend on – you guessed it – the operating system. On Mac we could get the effective user ID of the other end of the connection, while on Windows we could get something called the SessionID. We compared whether the SessionIDs matched. Unfortunately, as Tavis pointed out to us, this turned out to be a less reliable way to determine the owner of the process than we needed. It turns out that a different user on the same Windows machine can create a process under a SessionID that is the same as Molly's.
One of our design principles is to keep as few secrets in the browser extension as possible. It is 1Password Agent (or "mini" on the Mac, or "Helper" for 1Password 6 for Windows) that actually handles the secrets. This is because web browsers are inherently hostile environments.
So when you, say, use control-\ (or command-\ on Mac), Agent will ask the 1Password browser extension about the site it is on. The extension will tell Agent, and Agent might say, "I know how to fill things on that site, send me details about the page and I will tell you how to fill it". The extension will tell Agent the details about the page, and Agent will respond with filling instructions including the username and password to be filled in. There are also times when the extension can start this conversation (when you click on the 1Password icon within the browser, for example.) So that means that the extension can ask Agent, "Hey, how do I fill this page?" and Agent will respond with the filling instructions, including username and password.
So because Agent is happy to tell the browser extension the username and password for any site the extension knows about, it is important that Agent is only talking to a bona fide 1Password extension. Ensuring this is tricky, and we use a number of mechanisms to deal with this. Tavis showed us that one of the mechanisms that we used wasn't as reliable as we'd previously thought.
The threat that Tavis pointed out is from another unprivileged user on the same system. And so our new defense is against that threat. Our other defenses remain in place. While we could have tried to see if there were ways to tweak the SessionID check (something we still may do), we started working on a defense against this threat that isn't tied to the finer details of a specific exploit. A more general defense is better, as it would not only defend against the very specific attack in question but can defend against a larger class of potential attacks that might be developed in the future.
When you authorize a new browser extension, it and Agent will pick a long term secret that each will store. Every time they connect after that, they will use their copy of that stored secret to prove to each other that they have that secret. They do this in an exchange that is kind of like, "Hey, here is a challenge for you that you should be able to complete only if you know the same secret I use to construct the challenge." That way they can each prove to the other that they know the shared secret without actually revealing the secret to each other. The only time the secret is transmitted (from the extension to the Agent/mini/Helper) is when you first authorize the extension.
It is not just that every connection between the extension and Helper is authenticated this way, but each message they send to each other is encrypted and authenticated using an Encrypt-then-MAC scheme.
It should be made clear that this fix does not defend against an attacker who can read Molly's files. Both Helper and the extension store their shared secret long term and this can be read from the disks. This is fine because this measure is designed to defend against the attacker who is another user on the same system.
We have considered doing something like what we have done now several times over the past few years, but we always felt that it was unnecessary because it would only defend against someone who could not read the target's disk. Indeed, I am very much on record for saying that such a move would be pointless. But now we more clearly realize that it makes sense to address the threat of an unprivileged user distinct from the target as a threat to be addressed in its own right. Of course our SessionID check was an attempt at that, but we now take more robust measures.