0

I've been finding a lot of blog posts claiming JS encryption is unsafe, here's a couple of detailed ones:

http://www.matasano.com/articles/javascript-cryptography/

http://rdist.root.org/2010/11/29/final-post-on-javascript-crypto/

My question is, if browsers truly are inherently unsafe then, by extension, entering any PCI-related info in the browser is unsafe - regardless of JS encryption, HTTPS, or any other security measures? Which would imply that malicious parties should be taking major advantage of this fact, right? Could someone provide specific examples where browser vulnerabilities were leveraged to steal massive amounts of PCI-info/PII (by "massive" I mean comparable to the amount that could be obtained by hacking into the hosting servers/DB)?

Also, despite all those posts describing security flaws there's a proliferation of payment services and JS crypto libraries - does that indicate that most companies/communities:

  1. are unaware of browser vulnerabilities?
  2. are simply disregarding the underlying issues and jumping on the bandwagon to make some dough?
  3. have weighted the (possibly low) likelihood of someone going through the trouble of exploiting browsers and decided it's still worth to capture payments through browsers?

EDIT

Using SSL/TLS addresses some of the issues, but definitely not all. Here are a few notable issues that fall outside of the area that SSL/TLS can solve (quoted directly from the Matasano blog post):

The prevalence of content-controlled code.

  • We mean that pages are built from multiple requests, some of them conveying Javascript directly, and some of them influencing Javascript using DOM tag attributes (such as "onmouseover").

The malleability of the Javascript runtime.

  • There is no reliable way for any piece of Javascript code to verify its execution environment. Javascript crypto code can't ask, "am I really dealing with a random number generator, or with some facsimile of one provided by an attacker?" And it certainly can't assert "nobody is allowed to do anything with this crypto secret except in ways that I, the author, approve of". These are two properties that often are provided in other environments that use crypto, and they're impossible in Javascript.

What else is the Javascript runtime lacking for crypto implementors?

  • Two big ones are secure erase (Javascript is usually garbage collected, so secrets are lurking in memory potentially long after they're needed) and functions with known timing characteristics. Real crypto libraries are carefully studied and vetted to eliminate data-dependant code paths --- ensuring that one similarly-sized bucket of bits takes as long to process as any other --- because without that vetting, attackers can extract crypto keys from timing.

Again, my main point is that, technically, once a credit card number (or some other important piece of info) is entered into a text field of a page there's a chance that it's been compromised - and at that, compromised more easily then if it were entered in the native application.

  • 2
    The point of these posts is that javascript cryto doesn't add any security over https -- not that https is insecure. In particular javascript crypto without https is not secure, and javascript crypto over https doesn't protect you from a malicious server. There are people who claim they don't need https or that they're safe from malicious server, which is not true. – CodesInChaos Apr 20 '14 at 16:29
  • @CodesInChaos please see my edited answer - SSL/TLS doesn't solve all the problems (only most of the transport related ones) – Andrey Apr 20 '14 at 17:28
  • First one is about code style, second is just as bad for native code. Only the lack of secure erase is a real issue, and one with little relevance to credit cards since it this only matters when the client gets compromised later on. The biggest issue IMO is how common it is to embed external javascript instead of serving it from your own. SSL is good enough for low value targets like CC numbers, but might not be good enough for liberationtech. – CodesInChaos Apr 20 '14 at 17:44
  • so, in your opinion, all the major security issues associated with Javascript that are listed in the matasano article can be solved by using SSL/TLS? – Andrey Apr 20 '14 at 19:46
  • Even with TLS you need to trust the server which delivers the javascript. This problem can only be solved by improving browsers and even then only in part. For example if a shop website embeds javascript from an ad server it trusts, but the ad server is actually malicious (perhaps it was hacked) that server can send a copy of the CC data to the hacker. – CodesInChaos Apr 20 '14 at 19:52
2

EDIT: I felt compelled to address the transport side of the question understanding that the OP was not advocating using JavaScript encryption in lieu of SSL/TLS. But I've certainly seen that and a number of other unsafe variations done multiple times. However; with respect directly to the issue of how safe it is to input data into a text field in a web browser--that does not require JavaScript. If you post a form to a server then JavaScript isn't part of the equation at all. Yet there is a lot of JavaScript browser-based validation code floating around out there, and that sort of thing certainly could leave sensitive data in memory on the client, depending on the implementation. Still, doesn't the end user bear at least some responsibility for trying to ensure that their computer is free of malware? Because the only way that sort of thing really causes a problem is if the client's machine has been hijacked by some rogue code that can read its memory.

ORIGINAL: Show me the standard reference implementation of JavaScript-based cryptography in a browser.

There isn't one. As far as I know, the only cryptographically relevant primitive in JavaScript is a pseudo-random number generator. The rest has to be implemented in JavaScript itself.

Cryptography is not trivial to get right. Taking shortcuts is extremely ill-advised. Even taking the shortcut of doing user authentication over HTTPS then switching to HTTP is extremely ill-advised, because it opens a system wide to man-in-the-middle attacks.

Using half-baked roll-your-own cryptography is a really good way to compromise the security of your users.

To do even a barely adequate job of encrypting a password sent over HTTP (rather than HTTPS) from a client to a server, to protect it from prying eyes would require Asymmetric encryption keys (RSA style), with the private key kept aggressively safe on the server, and the public key disseminated to users.

But there are some serious problems with a solution that simple, including:

  1. The encryption could only go one way, from client to server. ANYTHING the server encrypted with the private key could be decrypted by anybody with access to the public key.

    • By definition, that's everybody.
  2. Asymmetric encryption is really expensive compared to symmetric encryption, so even without the one-way-encryption problem, asymmetric encryption is a terrible way to carry on a long conversation. That's one of the chief reasons why SSL/TLS uses asymmetric encryption to exchange a shared secret key for symmetric encryption, so that server and client can use an order-of-magnitude faster symmetric algorithm for ongoing secure communication.

  3. There is no provision for forward secrecy. A third party could intercept a communication session, later obtain the private key and have all they need to decrypt both sides of the communication (we've already established that they have all they need to decrypt anything sent from the server, by design).

So, let's be honest, to actually do an adequate job of even exchanging a password would require:

  • Asymmetric encryption keys (RSA style)
  • A session-initiation handshake algorithm for securely transmitting an ephemeral shared secret symmetric encryption key.
  • To be actually secure rather than just fooling yourself into thinking you're secure, a forward secrecy or perfect forward secrecy mechanism, so that the asymmetric keys used to exchange the ephemeral symmetric key are themselves ephemeral and discarded sometime soon after use, so that the session cannot be recorded then broken later merely by obtaining the private key from the server.

If you add all of that up, you more or less have SSL/TSL.

So why even consider re-inventing the wheel with a custom solution that will take a lot of time, be very difficult to get right, take even more time and energy to keep up-to-date, with full-on security bugs that you really just don't have the time, resources or know-how to detect and fix?

Even if you come up with a reason to have the JavaScript client encrypt data for some kind of local persistence, you have a key-management issue. The very strongest encryption is only as strong as your key management. You could manage that key on the server, but then you still need a secure mechanism for transmitting it to the client.

Again, it looks like SSL/TLS is the go-to solution.

The current state of cryptography basically boils down to two types: Asymmetric and Symmetric.

  • Asymmetric is the RSA-style public/private key cryptography. Anything signed or encrypted with the private key can be validated or decrypted with the public key, and vice-versa.

  • Symmetric is the standard "shared secret" pattern, used by AES and other symmetric algorithms.

  • Stir the various message digest or "hash" algorithms into the mix, and you're able to generate smallish fixed-length "thumbprints" of large data sets for integrity checks (digital signatures), password hashes, and more.

To securely transmit anything between two endpoints using symmetric encryption, you have to figure out how to get a shared secret to both ends without anybody in the middle intercepting the secret and using it to masquerade their way into your system or covertly tapping communications.

To securely transmit anything between two endpoints using asymmetric encryption requires a multiple-round-trip handshake, for each transfer, with challenges and responses and hashing and signature verification and so on.

On top of all the rest, having SSL/TLS certificates signed by a trusted Certificate Authority provides a measure of security via the ability for the client to confirm that the certificate being presented does indeed come from a valid source, hasn't been tampered with, is not expired, and has not been revoked for any reason.

  • just to be clear, i was not advocating avoiding SSL/TLS in preference to "your own cryptographic solution". SSL/TLS does a great job of protecting data while it's being transferred over the wire (let's just ignore the heartbleed bug for the purposes of this discussion). my main question is: is a browser truly an insecure environment for entering sensitive data? the main focus is on the browser itself rather than the transmission of data through the Internet (since, as I already pointed out, SSL/TLS solves most of those problems). – Andrey Apr 20 '14 at 23:43
  • @Andrey: I did note your comments about SSL/TLS security, but I felt compelled to elaborate for folks who are thinking about encrypting data for transport. I think it may be a bit of conflation to ask about browser data-entry security and JavaScript encryption in the same context. A text field in a browser does not require any JavaScript interaction. However, there is a lot of JavaScript input validation code around, and that could leave sensitive data in memory on the client. But if you post the data straight to a server for validation, JavaScript isn't part of the equation. – Craig Apr 20 '14 at 23:53
  • that's not necessarily true - malicious JS could very easily register event listeners with arbitrary DOM elements. hence the importance of serving all website content/pages over SSL/TLS not just parts of it. still, there's a potential of XSS attacks. – Andrey Apr 21 '14 at 0:31
  • If you serve your site using HTTPS you substantially mitigate the chances of that kind of attack. You're absolutely correct that it's important to serve all of the content using HTTPS. In fact, if you're going to serve any of it using HTTPS, you should completely disable HTTP on the site to defeat attacks like SSLSTRIP. – Craig Apr 21 '14 at 0:54
  • If you really do have a problem with JavaScript injection on your site, then all bets are off. That same JavaScript could just as easily screen-scrape the entire page and send it off who-knows-where, as the user types, regardless of whether a form is ever posted back to a server. The only way to defeat that behavior if the site is compromised would be to disable JavaScript in the browser. – Craig Apr 21 '14 at 0:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.