Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Insecure key storage: secrets are very easy to retreive #30

Open
max-r-b opened this issue Aug 8, 2018 · 0 comments
Open

Insecure key storage: secrets are very easy to retreive #30

max-r-b opened this issue Aug 8, 2018 · 0 comments

Comments

@max-r-b
Copy link

max-r-b commented Aug 8, 2018

Description

The password used to encrypt the secret (when the project is configured to encrypt them) is embedded in the app and can be easily retrieved.

The password used to generate the key (in a weak way but this is an other matter) is stored in the binary as a string constant. And from what I saw, the IV is always 0000 (which is bad, you should use a random number instead).

In AESEncryptor.java

private static byte[] iv = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

In extern-key.h

#define SECRET_KEY "Cipher.so@DEFAULT"

In cipher-lib.cpp

jstring
Java_net_idik_lib_cipher_so_CipherCore_getString(JNIEnv *env, jobject instance, jstring key_) {
    const char *key = env->GetStringUTFChars(key_, 0);
    string keyStr(key);
    string value = _map[keyStr];
    const char *result = encryptor->decrypt(SECRET_KEY, value.c_str());

It means that you will have to look for strings in the binary which makes it quite easy to find.
Also the password is stored as a constant (read only data). In the ELF file generated with clang this value is stored in the .rodata section.

Reproduction

You first need to unzip the APK to exctract the so file.

$ readelf -p .rodata lib/x86/libcipher-lib.so
String dump of section '.rodata':
  [     0]  HelloSecretKey
  [     f]  9Lh16XTo0e+6tw+oD7jVx9cBTty2WSxRi75FJTEPpbA=
  [    3c]  5d41402abc4b2a76b9719d911017c592
  [    5d]  NkXVm1rkyXcK1SsYkV8l8mgu6BDpwBIt2iqCVjVIQRg=
  [    8a]  58b49c7df6e825734005b0185607e8d7
  [    ab]  basic_string
...

We can clearly identify a the password here: HelloSecretKey. As well as the encrypted secrets 9Lh16XTo0e+6tw+oD7jVx9cBTty2WSxRi75FJTEPpbA= and NkXVm1rkyXcK1SsYkV8l8mgu6BDpwBIt2iqCVjVIQRg=

Then it is easy to decrypt the secrets, you generate the key the same way you did (you should at least use a safe key generation algorithm like PBKDF2 or bcrypt).

echo -n HelloSecretKey | md5sum -
88c5ef0a90786ede576a9cb8ab0190a3

To finish you can decrypt the secret using openssl or whatever

echo "9Lh16XTo0e+6tw+oD7jVx9cBTty2WSxRi75FJTEPpbA=" |openssl base64 -d|openssl enc -aes-128-cbc -d -K "88c5ef0a90786ede576a9cb8ab0190a3" -iv 0000000000000000
Hello From Cipher.so😊

Solution

Sadly, there is no solution I recommend. Developers should avoid to embed secret keys in their application. The problem you try to solve is actively researched and is called whitebox cryptography. Some solutions try to replace AES implementation and a key by a huge lookup table. However all the public proposal have been broken...

In the meantime, you can try to better generate and hide the key. But understand this will never be safe. Here are some ideas:

  • Use a random IV. IV does not require to be hiden. Use a different IV per secret you encrypt.
  • Use a randomly generated key instead of a password. You can have a look to KeyGenerator
  • You can try to hide the key in other sections of the ELF file, maybe in .text area among code
  • You can try to randomize a bit the place where the key is stored so it is different for each project
@max-r-b max-r-b changed the title Insecure key storage: secrets very easy to retreive Insecure key storage: secrets are very easy to retreive Aug 8, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant