comments (not for humans)

This post describes how OWASP Top 10 - A7: Insecure Cryptographic Storage affects javascript applications. This is a wide category which covers a lot more than this blog post. I'll try to focus on the aspects that often occur in applications that rely heavily on JavaScript.

This is the risk rating from OWASP:

Threat Agents Attack Vectors Security Weakness Technical Impacts Business Impacts
______ Exploitability
Consider the users of your system. Would they like to gain access to protected data they aren't authorized for? What about internal administrators? Attackers typically don't break the crypto. They break something else, such as find keys, get cleartext copies of data, or access data via channels that automatically decrypt. The most common flaw in this area is simply not encrypting data that deserves encryption. When encryption is employed, unsafe key generation and storage, not rotating keys, and weak algorithm usage is common. Use of weak or unsalted hashes to protect passwords is also common. External attackers have difficulty detecting such flaws due to limited access. They usually must exploit something else first to gain the needed access. Failure frequently compromises all data that should have been encrypted. Typically this information includes sensitive data such as health records, credentials, personal data, credit cards, etc. Consider the business value of the lost data and impact to your reputation. What is your legal liability if this data is exposed? Also consider the damage to your reputation.

What is insecure cryptographic storage?

Private data needs to be protected, be it private messages, documents or passwords. However a lot of the time data ends up being stored in insecure locations or in insecure ways. This could be:

  • Unencrypted storage
  • Misplaced data
  • Weakly encrypted or hashed storage - short encryption keys, old outdated hashing algorithms, hashless salting etc.

Unencrypted data

On the server side it's important that passwords are stored poperly hashed (PBKDF2, bcrypt, scrypt and friends) and data like credit card numbers etc. needs to be encrypted in proper ways. The same thing holds on the client side. We need to make sure we don't somehow store data in unencrypted way and leave it there.

There are several ways this can happen. One is using the offline cache for private data and not removing it on a logout. A second mistake is putting data in browser storage and not removing it on logout, allowing another user using the same machine to access the data. A third one very related to the seconds one, is leaving data in global objects in single page web apps. If there is no full refresh of the page on a logout.

Misplaced data

If the server is sending the wrong caching headers, the browser or a proxy may end up caching data it's not supposed to. Another user using the same machine or proxy can end up getting a cached response where the cache content belongs to someone else. This recently happened big time in Norway where several people was given the same individual's tax return. This was due to a firmware bug in a networking component though, not due to wrongly specified caching headers (as far as I know).

Putting sensitive data like passwords in URL-parameters also quickly becomes a problem. URLs tends to end up in web logs and proxies, and we certainly don't want passwords to end up there, making our logs really valuable for an attacker.

Weakly encrypted or hashed storage

This i normally a server side problem. We need to make sure data is stored in a properly encrypted way, and we need to store the encryption keys separated from the data. If you store the encryption keys in the same database as the data, a single SQL-injection may cause irreversible loss of data. Similarly unencrypted data stored on discarded backup tapes can be stolen by an attacker going through the trash.

If the data decryption is implemented the wrong way, it can also open server side up for padding oracle attacks.

Never ever implement your own encryption algorithms. Proper crypto is hard. It's better to trust well-established libraries like Bouncycastle or OpenSSL. If you are on node.js use the crypto API which is wrapping OpenSSL.


  • Make sure sensitive/private data is properlly encrypted
  • Make sure private data is deleted from the browser on logout
  • Make sure private data is not cached
  • Make sure you use well-established crypto libraries - don't roll your own
comments powered by Disqus