As well as supplying Cryptosense Analyzer to our customers so they can test their applications, we frequently apply the tool ourselves to widely-used open source software including the Java JDK. The Oracle Critical Patch Update (CPU) of 17th October contained patches for two CVEs discovered at Cryptosense in collaboration with our partners at University of Venice Ca’ Foscari.
Cracking Java Keystores with Hashcat
The recent edition (no. 15) of hacker magazine POC||GTFO features a nice article on cracking JKS Java keystores. JKS is the default keystore in all current versions of Java and still the only kind available in several widely-used application frameworks, despite issues with its security.
The keystore works by password-based encryption (PBE): you supply a password and the private keys are encrypted under a key derived from that password. There are just two problems: the encryption is not real encryption and the key derivation is extremely weak. The PBE works by applying the hash function SHA-1 to the password (and a salt) to generate a keystream, and XORing the resulting stream against the key.
Default Cryptographic Credentials
Unchanged default access passwords are a pervasive problem in computer security. A recent high-profile example is the Mirai botnet that spread by using 61 common default login credentials.
In programs using crypto, passwords are often used to generate cryptographic keys. For example, they are used to generate the “key encrypting keys” that are used to protect private keys stored in keystores, or the master key used to protect persistent application data written to storage.
Unfortunately, these passwords are susceptible to the same problem: they have de facto “default values”, often coming from HOWTOs for setup. For example, the password “changeit” figures in several guides for configuring TLS private keys for Java web applications. We trace these passwords using our Analyzer tool, and we encounter a substantial number of “changeit”s in the wild.
Sometimes default crypto credentials are even easier to exploit. In the recent Primefaces bug, many applications were using the default password (“primefaces”) to generate the encryption key. This would lead to secret values encoded in encrypted URLs being leaked, and unlike access passwords, there would be no log to show that attack was being made.
Application frameworks can sometimes make it unnecessarily complicated to change default passwords, but still there’s little point encrypting if the password is unchanged. Our Analyzer tool checks crypto passwords against a dictionary of known defaults and common weak passwords.
You can read about more keystore and password-based encryption issues in our Java Crypto Whitepaper, or detect them automatically using our Analyzer software.
Weaknesses in the Java JCEKS Keystore
When strong cryptography was introduced into Java, the legacy JKS keystore with its “SHA-1 and XOR” encryption method was replaced by JCEKS, which uses Triple-DES (3DES) encryption to protect serialized keys when they are written to disk.
There is a lot of JCEKS still around. So how exactly does the encryption work?
Like JKS, JECKS uses password-based encryption. Before creating a key, the JCEKS key derivation routine creates a random 64-bit salt. If the first and second half of the salt are the same, the first half is inverted.
This is already pretty odd, but will be explained (to an extent) when we look at how the two halves of the salt are used. For now let’s just look at the code that does the inversion of the halves:
// if the 2 salt halves are the same, invert one of them int i; for (i=0; i<4; i++) { if (salt[i] != salt[i+4]) break; } if (i==4) { // same, invert 1st half for (i=0; i<2; i++) { byte tmp = salt[i]; salt[i] = salt[3-i]; salt[3-1] = tmp; } }
See anything strange? Yes 3-1, not 3-i. What's the effect of this typo? It means that halves aren't really inverted. The salt 12341234 becomes 41241234 instead of 43211234. This bug is present in Oracle Java and OpenJDK.
Weird bug, but it doesn't matter: the purpose is to make the two halves different. This is because of what comes next: the first half is attached to the password and hashed (using MD5) c times to produce the first 128 bits of the 3DES key. The second half is then attached to the same password and hashed c times to produce the last 64 bits of the 3DES key and the 64 bit IV to be used to encrypt the key using 3DES in CBC mode.
Why did the designers want to prevent the two salt halves from being the same? Remember that the salt will be stored in plaintext, so a would-be attacker can easily access it. Suppose he realises that the salt has two identical halves. Then he knows that the first and third 64-bits of the 3DES key are equal, and the IV is equal to the second 64-bits of the key.
Knowing these things are the same reduces the search space, but in practice it is very unlikely that this will make brute-forcing the key easier than a dictionary attack on the password.
What is more interesting is that in the Oracle Java JCEKS, that constant c for the number of iterations is just 20.
Note also that in the JCEKS scheme, the two calculations for the two key halves can be carried out in parallel, since the result of one does not depend on the result of the other.
While the "right" number of iterations is highly application-dependent, as a guide, most recommendations propose about 10000 iterations. Additionally, to counteract parallelized and specialist hardware-based attacks, it is considered prudent to use a hash function that requires considerable memory for each derivation. MD5 is certainly not such a function. Better alternatives are either PBKDF2-HMAC-SHA512, if you are restricted to NIST-approved schemes, or something like scrypt if not.
Conclusions
JCEKS is an improvement over the original JKS, but it cannot be considered secure: 20 iterations of MD5 is not considered a secure password-based key derivation method against today's attackers. Find out more about alternatives in our Java crypto security whitepaper.
Weak Key Derivation in OpenSSL
Update March 2017 Our Analyzer software for OpenSSL application audit is now available, get in touch to try it.
Original post:
Cryptosense software is designed to give our users visibility on the crypto their applications are using. We have tracing tools for PKCS#11 and Java, and recently we’ve been working on one for the OpenSSL crypto library (libssl and libcrypto). We’d like to share a couple of early results.
The idea of the tool is that it inserts a shim between an application that (dynamically) links to openSSL and the libraries themselves, and writes out an abstract logical trace of the operations. We can send this trace to our Analyzer where it will be checked for simple crypto issues like weak algorithms and short keys, as well as more complicated bugs like key-management issues, insecure interactions between crypto operations, bad nonce or randomness management etc. We needed some real applications that use OpenSSL to try it out, and it seemed logical to start with OpenSSL’s own command-line tools that carry out simple operations using the library.
Password-based key derivation in OpenSSL Commands
The OpenSSL command line tools give access to a lot of functionality. For our first tests, we concentrated on commands that derive an encryption key from a password. This was because the documentation isn’t too clear about how exactly this will be done, so it seemed an area where our tool could shed some light.
The principles of password-based key derivation are similar to that of hashing passwords for secure storage. The idea is to derive the key in such a way that it’s difficult for an attacker to guess the key starting from a dictionary of possible passwords. The same techniques apply, such as salting the hash with a unique (public) value for each key that’s derived, so that an attacker cannot test guesses against many keys at once, and using many iterations of a hash function to calculate the key from the password, so that the attacker has to do a lot of computational work to turn each password from the dictionary into a guess at the key. These days we often also want to choose the hash function so that it requires a lot of memory and is hard to parallelize, to resist against attacks using dedicated hardware.
So how do the OpenSSL commands stand up? Well not too well, at least not in version 1.0.1k that we tested (the current version in popular Linux distributions), though it looks like there will be some improvements in version 1.1 (currently in beta). Let’s look at a couple of results in detail.
Encrypting files
The enc
command allows you to encrypt a file using one of the symmetric-key ciphers included in OpenSSL under a key derived from a password. We ran
openssl enc -v -aes-256-cbc -salt -in file.txt -out file.enc -pass pass:mySillyPassword
We ran the analyzer over the resulting trace and obtained this:

OpenSSL trace analysis
So OpenSSL is using one iteration of salted MD5 to derive the key (if there were no salt or a zero string, the Analyzer would have raised another warning). This is not good, and you may want to reconsider your password policy if you use this command for anything serious. It doesn’t look like things will improve much in OpenSSL 1.1.0 – the manpage suggests that SHA-256 will replace MD5 but no iteration parameter will be added.
Encrypting Private Keys
The pkcs8
command allows you to store a private key in an encrypted container. If you call it using the first example in the manpage:
openssl pkcs8 -in key.pem -topk8 -v2 des3 -out enckey.pem
Our tracer reveals that the key derivation uses PBKDF2 and 2048 iterations of HMAC-SHA-1. There is no command line option to change iterations (except to remove them). Using 2048 is not too bad, but it’s not considered best practice (see our article on PBKDF2 parameter choice). OpenSSL v1.1 adds an iteration parameter to allow this to be increased further. You can also beef up the hash function used inside PBKDF2 using a switch like -v2prf hmacWithSHA512
There are also host of other, weaker, password-based encryption methods available, but you would have to deliberately choose them with command line switches like -v1 PBE-SHA1-3DES
Conclusions
Password-based key derivation in OpenSSL command-line functions could do with some modernization. Meantime, if you have an application that calls the OpenSSL libraries and you’d like to try it out with our tracer tool, we’d be very interested to hear about it.