POC||GTFO journal edition 0x15 came out a while ago and I’m happy to have contributed the article “Nail in the JKS coffin”. You should really read the article, I’m not going to repeat myself here. I’ve also made the code available on my “JKS private key cracker hashcat” github repository.
For those who really need a TL;DR, the developed cracking technique relies on three main issues with the JKS format:
- Due the unusual design of JKS the key store password can be ignored and the private key password cracked directly.
- By exploiting a weakness of the Password Based Encryption scheme for the private key in JKS described by cryptosense, the effort to try a password is minimal (one SHA-1 calculation).
- As public keys are not encrypted in the JKS file format, we can determine the algorithm and key size of the public key to know the PKCS#8 encoded fingerprint we have to expect in step 2.
For a practical TL;DR, see the github repository on how JksPrivkPrepare.jar can be used together with the hashcat password cracking tool to crack passwords.
Not affected of the described issues are other key store file formats such as JCEKS, PKCS12 or BKS. It is recommended to use the PKCS12 format to store private keys and to store the files in a secure location. For example it is recommended to store Android app release JKS files somewhere else than a repository such as git.
There is a lot of discussion going on how to store credentials on the Android platform. What I’m going to discuss is focused on the Android platform, but you’ll notice that most of the things can be applied to all mobile plattforms. There are some differences, e.g. that you should use the much more evolved secure keystore of the iOS. There will be a keychain in Android 4.0. But of course you can screw up the secure storage on all platforms or even examples of the vendor show you how to screw up.
Before you start storing credentials the most important question is:
- Do I really want to store that data and why?
Before you simply answer “yes”, consider the following:
- Do you want to authenticate the user inside the app to check if he is allowed to access the app and other data?
- Then use a secure cryptographic hash function (e.g. SHA-2). Use a salt which is long enough and randomly generated on the fly. You can store the salt in plain along with the generated hash. Use multiple hashing rounds (e.g. 10’000).
- Don’t forget to check in every Activity that the user is already authenticated, because Activities can be invoked directly.
- Do you want to authenticate the user against a server?
- Before I go back to how you should store the credentials: Please use a secure channel to the server. One possibility is to use SSL (e.g. a HTTPS connection), but make sure you check the server certificate. Another possibility is to include a public key and have the corresponding private key on the server (actually I like this version even better, because you don’t have to trust hackable CA root companies).
- Change the server side. Talk to your customer if you are developing an app for someone else, it’s not a big deal to change something on the server side. Try to store a session token instead of the password. Even increasing the expiry time for sessions is better than storing passwords on the client. Only increase it if the request is coming from the Android app, but not for all clients (like standard browser authentication).
- If your really can’t change the server side and you can not use a token, you have a problem. Whatever you are doing from now, you have to store the password in reversable form, but the client isn’t a good option for that. Attackers equipped with root exploits and reverse engineering skills will always be able to get that password from somewhere (most of the time from the code or the filesystem). Consider that people often reuse passwords, which is a bad habit and if the password for your application is extracted, there might be other services that have to suffer from the laziness of the user.
- There are several ways of how you could try to protect the credentials, but again, they’re all useless against a sophisticated attacker: E.g. encryption (key in the source code) and good obfuscation (some are just useless). EDIT: With the new Android KeyChain you are even better off if you have a hardware-backed storage on the device. Simply use the KeyChain to store a private key that you use to encrypt the password. The password can only be decrypted when the attacker is in the posession of the device, as he can not extract the private key from the device. Well of course he can extract the key, but root permissions are not sufficient and it means messing with the hardware (which is very expensive).
- At least tell the user how the credentials are stored, why it could be a problem and what they can do to be protected (e.g. disable “remember password”).
- Don’t screw up and write the password somewhere to the logs…
Extracting Windows hashes for password cracking is pretty basic, right? If you try to copy the SAM and SYSTEM file from C:\WINDOWS\system32\config\ on a running Windows 2003 server you get an error message, saying that it’s already in use. So before you start using shadowcopies or ntbackup or any other tools, consider just copying C:\WINDOWS\repair\SAM and SYSTEM. Basically the same files, altough it seems that the repair folder is not always up to date.
Update: There is some more research going on pauldotcom.