We saw a very large increase in the number of mobile applications we tested in 2014. Among them, there were slightly more iOS applications than Android ones. In this blog post I will cover high level trends and the top 10 critical vulnerabilities we saw in 2014 during mobile applications penetration tests.
High Level Trends
There were a lot of new trends in 2014 compared to previous years. I’ve listed some of the more interesting ones below.
- An increase in the use of cross-platform development frameworks such as PhoneGap, Appcelerator, and Xamarin to write applications that can be deployed to both iOS and Android
- A decrease in wrapped browser (webview) applications
- An increase in the use of MDM solutions to push out applications to enterprise devices
- An increase in the use of MDM solutions to encrypt application traffic
- A decrease in applications using the local SQLite database to store anything but configuration information
- An increase in applications using root/jailbreak detection to prevent installation
- An increase in certificate pinning to help prevent encrypted traffic interception
In my previous Top 10 blog post on Thick Applications, I pointed out that we spend most of our time testing web services. This is also true with mobile applications. You may also notice that many of the findings listed here are also found in the thick application post. It just goes to show that new hot-off-the-press mobile applications suffer from the same problems that plague thick applications created fifteen years ago.
So without further ado, here are the top 10 critical mobile applications findings for 2014 list in order from most to least common.
SQL injection is still very prevalent via the web services of a mobile application. Rarely if ever do we see it against an application’s local SQLite database however. We often see that application developers take the mobile aspect for granted and don’t properly protect their web services on the backend. However, it is very easy to proxy a connection between a device and a server on iOS and Android. Don’t rely on protective measures such as certificate pinning to prevent traffic tampering, it’s not effective. Fix the issue at it’s heart.
Cleartext Credential Storage
We often see that mobile applications store unencrypted credentials within configuration files and local SQLite databases on a device. Usually they can be used to access potential sensitive data and external services. This is bad. Never store credentials anywhere on a device. If your application stores credentials to re-authenticate to a backend service without the user having to provide them again, consider using a time-limited session key that can be destroyed.
Hardcoded Credentials in Source Code
This is pretty common for us to find and primarily affects Android applications because they can be decompiled back to nearly complete Java code if they’re not obfuscated. It is possible to disassemble iOS binaries and search for credentials in them too. Never hardcode credentials in the code of an application. If a user can access your application, they can undoubtably access anything within the source code as well. Never assume people aren’t looking.
Hardcoded Encryption Keys
We see encryption keys hardcoded in source code all the time. Again, this primarily affects Android applications because of the relatively ease of decompiling APK files. As I said in my thick application post, encryption is only as strong as where the key is held. The recommendation is also the same. If data requires encryption with a key, move it from the client to the server to prevent access to keys.
Hardcoded or Nonexistent Salts
I’ll take the exact blurb that I used in my thick application post. When using encryption, it is always a good idea to use a salt. However, if that salt is hardcoded in an application with an encryption key, it becomes pretty much useless. When it comes to encryption being a salty S.O.B. is a good thing. Randomize! Randomize! Randomize!
XML External Entity Injection
This has become more prevalent in the past year with many mobile web services communicating with XML. XXE often results in read access to files on the server and UNC path injection that can be used to capture and crack credentials used to on associate web server if it is running Windows. Most XML parsing libraries support disallowing declared DTDs and entities. This should be set as the default when reading XML to help prevent injection. Another possible fix is to scrap XML all together and instead use JSON where this isn’t an issue.
Logging of Sensitive Information
Logging of data is fairly common in applications that we test both in production and QA environments. Often times it comes from having some type of debugging option enabled. This isn’t necessarily a bad thing until there’s data that you don’t want anyone to see. The most common sensitive data we see are credentials. Make sure that debugging is disabled for productions applications and check application and system logs during testing to ensure unintended data is not there.
Unencrypted Transmission of Data
This is still common to see in mobile applications. Every application we test uses web services, but not all use encryption. Utilizing TLS should be the default on all traffic coming to and from the application. Often times we see this in mobile applications developed for use in internal environments where security requirements are unfortunately more relaxed. Throw that notion out the window and encrypted everything.
As with thick applications, we see a lot of mobile applications use the GUI to enforce security controls without checking authorization on the backend. A user could access what they need by bypassing the GUI entirely and sending the requests they want directly through a proxy such as Burp. We have also seen applications pulling user permissions from the server and storing them on the client. A user could modify the permissions from the HTTP response before it reaches the client. Usually these permissions are worded in such a way that there meaning is obvious such as has_access_to_secret_information=false. Replacing everything with true is an easy way to bump up your privileges and bypass intended application authorization. The solution is to never rely on the client for authorization checks.
Sensitive Data Displayed in the GUI
This finding is pretty self explanatory. An application displays cleartext passwords, social security numbers, credit card numbers, etc… unmasked within the GUI. This is bad not only because that information should generally not be displayed to the user, but also because it has to be stored either on the device or within a backend database somewhere. This is also bad if coupled with mobile applications not requiring users to re-authenticate if the application has been put into the background on the device. For example, it you have an application open and you hit the home button on an iOS device, the application is paused in the background. Selecting the application again will generally reopen it where you left off. So if you give someone your iPad after you looked at an application that doesn’t mask sensitive information about you, that someone could just open it up again and see everything. This can be especially bad if you don’t have a password set on your lockscreen.
Everything is going mobile, and the security of the information that can be accessed and stored should be priority number one. Take the above information in consideration when developing your mobile applications and always remember to test. If you’re not testing your apps, someone else will, and they probably won’t be so candid about what they find.