Walgreens Android Apps Encryption Flaw

Installing the App

Here's the app I installed, from Google Play.

 

I logged in to a test account, and approved the app's saving my password.

 

Viewing the Locally Stored Password

Using Android Debug Bridge, I connected to the phone and retrieved the locally stored credentials as shown below.

The credentials are stored in an encrypted form.

Analysis and Recommendations

At this point, the likely conclusion is clear: the Walgreens app is insecure, because it stores the password on the phone using custom encryption. As discussed here, passwords should not be stored on the phone at all. Because users re-use passwords, they are very sensitive information and handling them carelessly is a disservice to your customers. Locally stored passwords could be stolen by malware on the phone, or by simply stealing the phone itself. Instead, a random cookie should be stored on the phone, which is useless at any company other than Walgreens.

This is the #2 most important security vunerability on mobile devices, according to OWASP.

If a developer is forced to store a password locally, there are far better options, such as the Android Keystore. The Android Keystore can be breached on a rooted phone, so the app should test for this, and refuse to run on a rooted phone.

Curiously, the Walgreens app actually does use the Android Keystore, but not for storing the encryption key used to encrypt user data.

The remainder of this page merely proves this simple point by explicitly reverse-engineering the encryption used by Walgreens, and using Python to decrypt the password.

The Walgreens Encryption Key

The Walgreens userdata encryption key is always the same. It is calculated from a seed, which is hard-coded in the app in three places:
./res/values/strings.xml:    phW5854acbc576=
./res/values/strings.xml:    phW5854acbc576=
./smali_classes5/com/walgreens/quickprint/sdk/html5/c.smali:    const-string/jumbo v0, "phW5854acbc576="
The actual encryption key is calculated from that seed using PBKDF2, as shown below.

Decrypting the Data

Decrypting the stored data requires only a few lines of Python, as shown below.

Developer Notification

I notified the developer of this problem on 5-3-17, as shown below.

Retest on June 20, 2017

I tested this version:

Nothing had changed; the password is stored the same way:

And it decrypts the same way:

Retest 7-28-17

I tested the newest version and it still has the same vulnerability.
Posted 5-3-17 by Sam Bowne
Updated 6-20-17
Updated 7-28-17