At this rate it will hit the launch codes in... 5.3 minutes.

Or, how not to do a password manager..

Hello everyone, in this post I would like to analyze an Android application which purpose is to manage and generate passwords securely. On their Play Store page they claim to use DES to encrypt passwords on local device and that DES key is derivated from you PIN code

So, let's see how securely they store your passwords...

Analyzing the APK

First of all I started decompiling the APK, which seems to use some sort of obfuscation in order to prevent a nice reading, which means that variable's names are just a shit; I'll try to rename some of them in order to make it more easy to understand.

We actually have two very interesting files:
com/#####/android/###/d/b.java com/#####/android/###/bj.java

Let's take a look at the first file; where we have the password decryption method:

Decrypting the password, retrieving the key


public static String b(String s, String s1)
{ 
          int i;
        int j;
        SecretKeySpec secretkeyspec;
        Cipher cipher;
        String s2;
        try
        {
            i = s.getBytes().length;
        }
        catch (BadPaddingException badpaddingexception)
        {
            return null;
        }
        catch (Exception exception)
        {
            exception.printStackTrace();
            return null;
        }
        j = 0;
        if (i >= 8) goto _L2; else goto _L1
_L1:
        if (s.getBytes().length >= 8)
        {
            break;
        }
        s = (new StringBuilder()).append(s).append("074289412373".charAt(j)).toString();
        j++;
        if (true) goto _L1; else goto _L2
_L2:
        secretkeyspec = new SecretKeySpec(s.getBytes(), "DES");
        cipher = Cipher.getInstance("DES");
        cipher.init(2, secretkeyspec);
        password = new String(cipher.doFinal(Base64.decode(encrypted_password, 0)), "UTF-8");
        return s2;
    }
}

There are at least three main errors here:

  • Use of ECB mode for DES[1]
  • Hardcoded key if PIN is < 8 chars: 074289412373, used for padding
  • Use the PIN code as it is as key

So, if for example my PIN code is: 1111 to encrypt my passwords the application will use DES/ECB with key 1111 + 074211110742, which, in my honest opinion is not enough.
Let's make some math, for a real random DES key we have 2^64 possible combinations ( which in real are just 2^54[2] ). But as we saw before the application uses only digits to generate our key, which reduces the possible combinations to 10^8.

→ 2^54 = 18014398509481984
→ 10^8 = 100000000

You can see the difference..
Noticed that, bruteforcing is feasible: my python PoC can try all the combinations in around 35 minutes. A Java or C code can do it in some seconds, or a couple minutes.
But, since the key is nothing else the our PIN code, with maybe some padding to make it 8 char long, once we found the key, we have also found the PIN, which allow us to decode all other passwords without further calculation.
And this is the first reason to not use this application to store sensitive password.

Get the PIN code in 2 seconds

Okay, that's cool. But I said that there were two interesting files, let's take a look at the second one:


private boolean K()
{
    return c().getSharedPreferences(,0).getString("manager_pin", "invalid").equals(ab.getText().toString());
}

This is a very interesting function. The application when we generate a PIN code save it in clear-text into an xml file, located in the data folder of app. Then, when you want to see your saved passwords, it will check if the PIN you write is correct, comparing it to the one saved in the file. Very secure.

Conclusion

We saw that with access to the application folder we can:

  • Bruteforce the key and then retrive all passwords and the PIN code
  • Retrive the PIN code because it is saved in clear and then use it to decrypt on the fly all passwords

1. A friend's post about why you should laugh when you see people using ECB: https://filippo.io/the-ecb-penguin/
1. Wikipedia: DES