Evaluate security of browser-based solution
bkeepers opened this issue · 14 comments
I still think there are a lot of open questions about building a web-based solution. I'd like to create a space to discuss them.
- Is JavaScript cryptography secure enough?
- Is localStorage secure enough for storing the encrypted private key?
- Is there a way to securely store the passphrase or decrypted private key?
To clarify, by "secure enough" I mean: without crossing some boundary, could an attacker gain access to the data? If the server or client is compromised, there can be no expectation of security with any architecture.
In #14, @joeyw brought up Javascript Cryptography Considered Harmful
I may just be naive (I am), but I'm not terribly concerned, and here's why…
Most opponents of JavasScript encryption, including this one, assume that you want to share data with the client and server but keep it secure over the wire. I agree with the author that JavaScript cryptography is a cheap replacement for real SSL/TLS. Swordfish's main goal is to share secrets with other clients without revealing them to the server. To me, this seems like a more legitimate use case.
Secure delivery of Javascript to browsers is a chicken-egg problem.
Everything will be served over TLS. The rest of the chicken-egg arguments apply to any other client/server architecture. If the server is compromized then it can't be trusted, and if the client is compromized then it can't be trusted by other clients. To quote the article, "we live and work in an uncertain world in which any piece of software we rely on could be found vulnerable to new flaws at any time".
Browser Javascript is hostile to cryptography.
forge has solved several of the issues he refers to, including JavaScript implementations of the lacking data types and a secure random number generator. Returning to the "secure enough" definition in the original issue above, if your local machine is already compromized, the language that the cryptography is written in seems irrelevant.
What else is JavaScript missing? A secure keystore.
This is one of my bigger areas of concern.
I don't mind storing the encrypted private key in local storage. It is still infinitely more secure than storing everyone's private keys on the server, where an attacker would only need to get a copy of the database (by penetrating the server or obtaining a backup), where they could then do brute force attacks against weak private key passphrases.
What concerns me is that there is not a way to securely store the passphrase or decrypted private key, and requiring users to constantly type in their passphrase will get annoying real fast.
PS We've actually use Matasano (author of this article) for security audits at GitHub, they're not going to be pleased when we ask them to audit swordfish. :)
While I'm especially looking for people to tell me I'm off my rocker, I'd appreciate feedback from all perspectives.
I sent this to two security professionals I know, hopefully they have a moment to look over this.
Safari extensions can store key/value pairs in the user's login
Keychain using the safari.extension.secureSettings
API. I don't know if other browser extensions have access to similar capabilities.
So you could imagine having the user only type their passphrase in some UI provided by the Safari extension itself (which is not exposed to the webpage) and doing all encryption within the extension itself. (Since Safari extensions are signed, this also removes the worry about JavaScript being modified before being received by the browser.)
@aroben That's an awesome point. I'm working on browser extensions now, and was planning on implementing all the encryption logic in the extension, but I didn't think about the idea of using the extension for the heavy lifting if available (or even forcing use of the extension).
I've used Passpack in the past to share important passwords with clients. They do the unpacking/decrypting on the client side with javascript, similar to this. They've open-sourced some of their stuff: http://code.google.com/p/passpack/wiki/LibraryReference
Their site has some good info, but it's a little light on technical details.
This is still very much a relevant issue and the fact the issue was closed without so much as a reason for closing it should be cause for concern
+1 @tarcieri
In the case of website (non-extension) JavaScript used to encrypt data stored on a server:
- The browser user relies a webserver to deliver the JavaScript which, in turn:
- Uses encryption so that data can be stored on a webserver without relying on the webserver to protect the confidentiality of that data.
Scenario 1: There is one webserver serving both JS and providing storage.
If the webserver which serves the JavaScript is the same one where the data is stored, then this boils down to:
- The browser user depends on the webserver to protect the confidentiality of that data.
This simplification is not useful when you want to distinguish something like an SQL injection that exports user data in a limited fashion from the webserver. In that case, since the attack does not affect the JavaScript encryption, the confidentiality would be preserved. But consider that for that specific case, the server could also do encryption / decryption before storing in a database.
If there were a compromise of this single webserver, it could just serve malicious JavaScript which sends the user's cryptographic keys to the attacker.
Scenario 2: Separate App and Storage websites:
The benefit of JS crypto starts to show if the JS is served from one "App Server", which the user relies on to provide backdoor, vulnerability free software, and the storage is on a different "Storage Server". Now, a complete compromise of the storage server cannot reveal cryptographic keys or user data plaintext.
However, I would argue it's difficult to have a "separate server scheme" because of usability issues, and also this mainly moves the attacker target from the Data Server to the App Server. (They still only have to compromise the JS served in order to access user data.)
Scenario 3: Browser Extension + Storage Website:
The next evolution along theses lines are to have browser extension JS and then a Storage Server. This is kind of like making the app store or extension distribution site into "The App Server": Now a compromise of that site is similar to a compromise of the "App Server" above. However, there is one big improvement:
- All users of the extension get the same version, around the same time.
If an attacker compromises the app server in Scenario's 1 or 2, they can selectively serve malicious JS to only some clients.
With an extension, users have a "version" of the extension. It's much harder to distribute a malicious version to only some users.
So, presumably, distributing a malicious extension will be more likely to be noticed.
@nejucomo great thoughts! I have come to mostly same conclusion.
The Web Cryptography API will alleviate most of the concerns with Scenario 1 & 2, but not all of them. You're not relying on JavaScript for the underlying crypto functions, but malicious JavaScript could obviously still be just as damaging.
Scenario 3 is really the only way to do this securely.
Scenario 3 sounds awesome and pretty easy to implement. I'm happy to pitch in and help write a browser extension for Chrome, Safari and Firefox. IE.. uhh.. well..
I agree scenario 3 is really the only way to make this work, but keep in mind this 100% rules out using mobile 📴 since none of the mobile browsers support any form of plugins. I suppose a native app is a possible way around it, but I for one would have hard time using a password manager without some form of mobile use case.
There was some work started on a chrome extension.
I agree scenario 3 is really the only way to make this work, but keep in mind this 100% rules out using mobile
Yep. I think a native app will be the most viable option here. Be server is client-agnostic, so I'm hopeful that we can have a variety of clients someday.