Recently at Packet Ninjas, we have been getting a lot of questions about the kind of testing we do here. I thought this would be a good opportunity to write a few articles about some of my favorite findings. I am officially kicking off a new series today called My Favorite Findings.
Today I will be sharing a finding that we found about 6 months ago while testing a mobile application for a client.
One big component of mobile application assessments is installing the application and then looking into what files are stored on the actual device. Many applications are riddled with issues that involve storing sensitive data on the device in a manner that is insecure.
Today’s finding involves this concept, with a bit of a twist.
Looking for juicy strings
For this finding we will be searching through the Android file system. If you are not familiar with the android file system, most apps will store their data in a directory that looks like /data/data/<appname>.
While going through the files in the shared_prefs directory of this particular app, I noticed that there was an application.xml file that contained several keys. The names of the keys were things such as:
This led me to believe that these strings were being used by the application to store user data. The key “user_p” might just be where user passwords were being stored locally. And “user_e” could be the email.
“JACKPOT!” you might say. Well, not quite. The values for these keys appeared to be encrypted. So, back to the drawing board (or maybe not).
Looking for keys
Keeping the encrypted strings in mind, I started looking to see if the devs had left any keys (or clues) lying around. In the same directory, I noticed that there was a file called “crypto.KEY_256.xml”.
Promising! Could this key be useful for decrypting the data in the application.xml file? Popping the file open, we found a string called “cipher_key.”
Could it really be this easy? Typically, this key should only work if the encryption in use was symmetric or “single key” encryption.
I figured it was worth a shot.
I read up a little bit on AES 256 symmetric encryption and wrote up a quick python script to use the encrypted value, the crypto key, and an initialization vector which appeared to be kept at the end of the encrypted value.
Lo and behold, it worked! With this, I was able to decrypt the encrypted strings we found earlier and gain the password of the user that was stored on the device.
Avoiding this mistake
So, this brings us to the question of how does one securely store credentials on the device?
The best answer is to use asymmetric encryption. This works by encrypting the password with a public key and storing it on the device. Each time the password needs to be checked, the encrypted password is sent to the server where it is decrypted on the backend and checked against the database. If successful, a token is passed to the android client to allow access to the application. At no time is the password visible on the phone’s filesystem.
That’s all for now
Hope this was a fun read for you. I know I had a lot of fun with this one. Part of the thrill of this job is being able to test hunches and follow clues to get into “secured” spaces — whether that’s in code or in the physical world. Sometimes it’s easy and sometimes it takes persistence. Either way, you can count on the Packet Ninjas finding a way in.