Reversing and Auditing Android Apps - Learning Pentesting for Android Devices (2014)

Learning Pentesting for Android Devices (2014)

Chapter 3. Reversing and Auditing Android Apps

In this chapter, we will look inside an Android application, or the .apk file, and understand its different components. We will also go ahead and reverse the applications using tools, such as Apktool, dex2jar, and jd-gui. We will further learn how to find various vulnerabilities in Android applications by reversing them and analyzing the source code. We will also use some static analysis tools and scripts in order to find vulnerabilities and exploit them.

Android application teardown

An Android application is an archive file of the data and resource files created while developing the application. The extension of an Android application is .apk, meaning application package, which includes the following files and folders in most cases:

· Classes.dex (file)

· AndroidManifest.xml (file)

· META-INF (folder)

· resources.arsc (file)

· res (folder)

· assets (folder)

· lib (folder)

In order to verify this, we could simply unzip the application using any archive manager application, such as 7zip, WinRAR, or any preferred application. On Linux or Mac, we could simply use the unzip command in order to show the contents of the archive package, as shown in the following screenshot:

Android application teardown

Here, we have used the -l (list) flag in order to simply show the contents of the archive package instead of extracting it. We could also use the file command in order to see whether it is a valid archive package.

Android application teardown

An Android application consists of various components, which together create the working application. These components are Activities, Services, Broadcast Receivers, Content providers, and Shared Preferences. Before proceeding, let's have a quick walkthrough of what these different components are all about:

· Activities: These are the visual screens which a user could interact with. These may include buttons, images, TextView, or any other visual component.

· Services: These are the Android components which run in the background and carry out specific tasks specified by the developer. These tasks may include anything from downloading a file over HTTP to playing music in the background.

· Broadcast Receivers: These are the receivers in the Android application that listen to the incoming broadcast messages by the Android system, or by other applications present in the device. Once they receive a broadcast message, a particular action could be triggered depending on the predefined conditions. The conditions could range from receiving an SMS, an incoming phone call, a change in the power supply, and so on.

· Shared Preferences: These are used by an application in order to save small sets of data for the application. This data is stored inside a folder named shared_prefs. These small datasets may include name value pairs such as the user's score in a game and login credentials. Storing sensitive information in shared preferences is not recommended, as they may fall vulnerable to data stealing and leakage.

· Intents: These are the components which are used to bind two or more different Android components together. Intents could be used to perform a variety of tasks, such as starting an action, switching activities, and starting services.

· Content Providers: These are used to provide access to a structured set of data to be used by the application. An application can access and query its own data or the data stored in the phone using the Content Providers.

Now that we know of the Android application internals and what an application is composed of, we can move on to reversing an Android application. That is getting the readable source code and other data sources when we just have the .apk file with us.

Reversing an Android application

As we discussed earlier, that Android applications are simply an archive file of data and resources. Even then, we can't simply unzip the archive package (.apk) and get the readable sources. For these scenarios, we have to rely on tools that will convert the byte code (as in classes.dex) into readable source code.

One of the approaches to convert byte codes to readable files is using a tool called dex2jar. The .dex file is the converted Java bytecode to Dalvik bytecode, making it optimized and efficient for mobile platforms. This free tool simply converts the .dex file present in the Android application to a corresponding .jar file. Please follow the ensuing steps:

1. Download the dex2jar tool from https://code.google.com/p/dex2jar/.

2. Now we can use it to run against our application's .dex file and convert to .jar format.

3. Now, all we need to do is go to the command prompt and navigate to the folder where dex2jar is located. Next, we need to run the d2j-dex2jar.bat file (on Windows) or the d2j-dex2jar.sh file (on Linux/Mac) and provide the application name and path as the argument. Here in the argument, we could simply use the .apk file, or we could even unzip the .apk file and then pass the classes.dex file instead, as shown in the following screenshot:

Reversing an Android application

As we can see in the preceding screenshot, dex2jar has successfully converted the .dex file of the application to a .jar file named helloworld-dex2jar.jar. Now, we can simply open this .jar file in any Java graphical viewer such as JD-GUI, which can be downloaded from its official website at http://jd.benow.ca/.

4. Once we download and install JD-GUI, we could now go ahead and open it. It will look like the one shown in the following screenshot:

Reversing an Android application

5. Here, we could now open up the converted .jar file from the earlier step and see all the Java source code in JD-GUI. To open a .jar file, we could simply navigate to File | Open.

Reversing an Android application

In the right-hand side pane, we can see the Java sources and all the methods of the Android application. Note that the recompilation process will give you an approximate version of the original Java source code. This won't matter in most cases; however, in some cases, you might see that some of the code is missing from the converted .jar file. Also, if the application developer is using some protections against decompilations such as proguard and dex2jar, when we decompile the application using dex2jar or Apktool, we won't be seeing the exact source code; instead, we will see a bunch of different source files, which won't be the exact representation of the original source code.

Using Apktool to reverse an Android application

Another way of reversing an Android application is converting the .dex file to smali files. A smali is a file format whose syntax is similar to a language known as Jasmine. We won't be going in depth into the smali file format as of now. For more information, take a look at the online wiki athttps://code.google.com/p/smali/wiki/ in order to get an in-depth understanding of smali.

Once we have downloaded Apktool and configured it, as instructed in the earlier chapters, we are all set to go further. The main advantage of Apktool over JD-GUI is that it is bidirectional. This means if you decompile an application and modify it, and then recompile it back using Apktool, it will recompile perfectly and will generate a new .apk file. However, dex2jar and JD-GUI won't be able to do this similar functionality, as it gives an approximate code and not the exact code.

So, in order to decompile an application using Apktool, all we need to do is to pass in the .apk filename along with the Apktool binary. Once decompiled, Apktool will create a new folder with the application name in which all of the files will be stored. To decompile, we will simply go ahead and use apktool d [app-name].apk. Here, the -d flag stands for decompilation.

In the following screenshot, we can see an app being decompiled using Apktool:

Using Apktool to reverse an Android application

Now, if we go inside the smali folder, we will see a bunch of different smali files, which will contain the code of the Java classes that were written while developing the application. Here, we can also open up a file, change the values, and use Apktool to build it back again. To build a modified application from smali, we will use the b (build) flag in Apktool.

apktool d [decompiled folder name] [target-app-name].apk

However, in order to decompile, modify, and recompile applications, I would personally recommend using another tool called Virtuous Ten Studio (VTS). This tool offers similar functionalities as Apktool, with the only difference that VTS presents it in a nice graphical interface, which is relatively easy to use. The only limitation for this tool is it runs natively only on the Windows environment. We could go ahead and download VTS from the official download link, http://www.virtuous-ten-studio.com/. The following is a screenshot of the application decompiling the same project:

Using Apktool to reverse an Android application

Auditing Android applications

Android applications often contain numerous security vulnerabilities, most of the time due to a developer's mistakes and ignorance of secure coding practices. In this section, we will go through the Android application-based vulnerabilities, and how they could be identified and exploited.

Content provider leakage

Many of the applications use content providers to store and query data within the application or the data from the phone. Unless the content providers have been defined to be accessed with permission, any other application could also access the application's data using the application's defined content providers. All content providers have a unique Uniform Resource Identifier (URI) in order to be identified and queried. The standard convention of naming the content provider's URIs is to start it with content://.

With an Android API-level lower than 17, the default property of a content provider is always exported. This means that unless the developer specifies the permissions, any application can access and query the data using the application's content provider. All content providers need to be registered in AndroidManifest.xml. So, we could just use Apktool on an application and check out the content providers by simply looking at the AndroidManifest.xml file.

The general way of defining a content provider is as follows:

<provider

android:name="com.test.example.DataProvider"

android:authorities ="com.test.example.DataProvider">

</provider>

So now, we will take an example of a vulnerable application and will try to exploit the content provider leakage vulnerability:

1. To decompile the application we will use Apktool in order to decompile the application using apktool d [appname].apk.

2. In order to find the content providers, we could simply look at the AndroidManifest.xml file where they are defined, or we could use a simple grep command in order to get the content providers from within the application code, as follows:

Content provider leakage

3. We could use the grep command to look for content providers using grep –R 'content://'. This command will look for content providers in each and every subfolder and file and return them to us.

Content provider leakage

4. Now, we install the application in the emulator. In order to query the content provider and confirm that the vulnerability is exploitable, we need to install the app in an Android device or an emulator. With the following code, we will be installing the vulnerable-app.apk file onto the device:

5. $ adb install vulnerable-app.apk

6. 1869 KB/s (603050 bytes in 0.315s)

7. pkg: /data/local/tmp/vulnerable-app.apk

Success

5. We could query the content provider by creating another application without any permission and then query the vulnerable application's content provider. In order to have quick information, we could also use adb in order to query the content provider, as we can see in the following command:

6. adb shell content query - - uri [URI of the content provider]

The following is the command being run on the vulnerable application, with the output displaying the notes stored in the application:

Content provider leakage

Here, we could also use another tool named Drozer by MWR Labs in order to find the leaking content provider vulnerability in Android applications. We could download and install Drozer from the official website at https://labs.mwrinfosecurity.com/tools/drozer/.

6. Once we have installed it, we need to install the agent component agent.apk located inside the downloaded .zip file to our emulator. This agent is needed for the system and the device to interact with each other. We also need to forward a specific port (31415) each time we start the emulator in order to have the connection. For installing the device on Mac and other similar platforms, we could follow the online guide available at https://www.mwrinfosecurity.com/system/assets/559/original/mwri_drozer-users-guide_2013-09-11.pdf.

Content provider leakage

7. Once this is done, we could launch the application and click on the text saying Embedded Server. From there, we need to go back to the device, start the Drozer application, and enable the server by clicking on the top-left toggle button named Disabled.

Content provider leakage

8. Thereafter, we need to go to the terminal and start up Drozer and connect it to the emulator/device. To do this, we need to type in drozer console connect, as shown in the following screenshot:

Content provider leakage

9. Here, we could simply run the app.provider.finduri module to find all the content providers as follows:

10.dz> run app.provider.finduri com.threebanana.notes

11.Scanning com.threebanana.notes…

12.content://com.threebanana.notes.provider.NotePad/notes

13.content://com.threebanana.notes.provider.NotePadPending/notes/

14.content://com.threebanana.notes.provider.NotePad/media

15.content://com.threebanana.notes.provider.NotePad/topnotes/

16.content://com.threebanana.notes.provider.NotePad/media_with_owner/

17.content://com.threebanana.notes.provider.NotePad/add_media_for_note

18.content://com.threebanana.notes.provider.NotePad/notes_show_deleted

content://com.threebanana.notes.provider.NotePad/notes_with_images/

10.Once we have the URIs, we could now go ahead and query it using the Drozer application. In order to query it, we need to run the app.provider.query module and specify the content provider's URI, as shown in the following screenshot:

Content provider leakage

If Drozer is able to query and show the data from the content provider, it means that the content provider is leaking data and is vulnerable since Drozer has not been explicitly granted any permission to use the dataset.

11.In order to fix this vulnerability, all a developer needs to do is specify the parameter android:exported = false while creating the content provider, or create some new permissions which must be requested by another application before accessing the provider.

Insecure file storage

Often, developers make the mistake of not specifying the correct file permissions to the files while storing data for an application. These files are sometimes marked as world-readable and could be accessed by any other application without requesting permissions at all.

In order to check this vulnerability, all we need to do is go to the adb shell and then cd to /data/data/[package name of the app].

If we do a quick ls -l over here, we are able to see the file permissions of the files and folders:

# ls -l /data/data/com.aditya.example/files/userinfo.xml

-rw-rw-rw- app_200 app_200 22034 2013-11-07 00:01 userinfo.xml

Here, we could also use find in order to search for the permissions.

find /data/data/ -perm [permissions value]

If we do a cat userinfo.xml, it is storing the username and password of the application's user.

#grep 'password' /data/data/com.aditya.example/files/userinfo.xml

<password>mysecretpassword</password>

This means any other application could also view and steal the user's confidential login credentials. This vulnerability could be avoided by specifying the correct file permissions while developing the application, as well as properly hashing the password along with a salt.

Path traversal vulnerability or local file inclusion

As the name suggests, a path traversal vulnerability in an application allows an attacker to read other system files using the vulnerable application's providers.

This vulnerability can also be checked using Drozer, the tool that we discussed earlier. Here, we will take the example of an Adobe Reader Android application vulnerability discovered by Sebastian Guerrero of ViaForensics (http://blog.seguesec.com/2012/09/path-traversal-vulnerability-on-adobe-reader-android-application/). This vulnerability existed in Adobe Reader 10.3.1 and is patched in later versions. You could download the older versions of various Android applications from http://androiddrawer.com.

We will start up Drozer and run the app.provider.finduri module in order to find the content provider URIs.

dz> run app.provider.finduri com.adobe.reader

Scanning com.adobe.reader...

content://com.adobe.reader.fileprovider/

content://com.adobe.reader.fileprovider

Once we have found the URIs, we could now use app.provider.read in order to find out and exploit the local file inclusion vulnerabilities. Here, we will try to read some files from the system such as /etc/hosts and /proc/cpuinfo, which are present in all the Android installations by default, since it is a Linux-based filesystem.

dz> run app.provider.read content://com.adobe.reader.fileprovider/../../../../etc/hosts

127.0.0.1 localhost

As we can see in the following screenshot, we have successfully read the file present in the Android filesystem using the Adobe Reader vulnerable content provider.

Path traversal vulnerability or local file inclusion

Client-side injection attacks

Client-side attacks usually happen when the application is not checking for proper sanitization in the user input. For example, during a query to the SQLite database, the application is parsing the user input as it is in the query.

Let's take an example of an application which is checking the local SQLite database for validating the user against the login credentials. So, the query which is running when the user provides the username and password will be as follows:

SELECT * FROM 'users' where username='user-input-username' and password='user-input-password'

Now, this would work fine in a normal scenario where a user enters their genuine login credentials and the query would return true or false depending on the condition.

SELECT * FROM 'users' where username='aditya' and password='mysecretpassword'

But what if an attacker inputs a SQL statement instead of a normal username? Refer to the following code:

SELECT * FROM 'users' where username='1' or '1' = '1' - - and password='mysecretpassword'

So, in this case, even when the user doesn't know of the username and password, they can easily bypass it by using the 1'or'1'='1 query, which will return true in all cases. So, the application developer must have proper checks in the application, which will check for the user inputs.

We could also use Drozer's app.provider.query in order to exploit the SQL injection vulnerabilities. Here is what the syntax looks like:

run app.provider.query [Content Provider URI] --projection "* FROM SQLITE_MASTER WHERE type='table';- -"

Now, this will return the entire table's list present in the SQLite database whose information is stored in SQLITE_MASTER. You could also go ahead and run more SQL queries in order to extract further information from the application. In order to practice exploitation with Drozer, you could download their vulnerable application Sieve from https://www.mwrinfosecurity.com/products/drozer/community-edition/.

OWASP top 10 vulnerabilities for mobiles

Open Web Application Security Project (OWASP) is one of the standards when it comes to security and finding vulnerabilities. It also releases a top 10 list that includes the most common and important vulnerabilities in various platforms.

The OWASP top 10 guide for mobile could be found at https://www.owasp.org/index.php/Projects/OWASP_Mobile_Security_Project_-_Top_Ten_Mobile_Risks. If we have a look at the OWASP mobile project, here are the 10 security issues it covers for mobile applications:

· Weak Server Side Controls

· Insecure Data Storage

· Insufficient Transport Layer Protection

· Unintended Data Leakage

· Poor Authorization and Authentication

· Broken Cryptography

· Client Side Injection

· Security Decisions Via Untrusted Inputs

· Improper Session Handling

· Lack of Binary Protections

Let's go into each of them one by one and have a quick understanding of what they relate to in mobile applications and how we could detect them:

· Weak Server Side Controls: In the first OWASP vulnerability, Weak Server Side Controls, as the name suggests, is not sending the data from the mobile application to the server side in a secure way, or exposing some sensitive APIs while sending data. For instance, consider an Android application login credentials to the server for authentication, without validating the inputs. An attacker could modify the credentials in such a way so as to get access to sensitive or unauthorized areas of the server. This vulnerability could be considered as a vulnerability in both mobile applications as well as web applications.

· Insecure Data Storage: This simply means storing the application-related information in a way on the device accessible by the user. Many Android applications store secret user-related information, or app information, in shared preferences, SQLite (in plain form) or in external storage. Developers should always keep in mind that even if the application is storing sensitive information in the data folders (/data/data/package-name), it will be accessible by a malicious application/attacker as soon as the phone is rooted.

· Insufficient Transport Layer Protection: Many Android developers rely on insecure mode of sending data over the network such as in the form of HTTP or not properly implementing SSL. This makes the app vulnerable to all the different types of attacks happening on the network, such as traffic interception, manipulation of parameters while sending data from the application to the server, and modifying responses in order to gain access to locked areas of the application.

· Unintended Data Leakage: This vulnerability occurs in applications when the application stores data at a location which in itself is vulnerable. These might include the clipboard, URL Caches, Browser Cookies, HTML5 data storage, analytics data, and so on. An example would be a user logging in to their banking application who has copied their password to the clipboard. Now, even a malicious application could access that data in the user's clipboard.

· Poor Authorization and Authentication: Android applications, or in general mobile applications, are mostly vulnerable if they try to authenticate or authorize a user based on client-side checks without proper security measures. It should be noted that most client-side protections could be bypassed by an attacker once the phone is rooted. Therefore, it is recommended that application developers use server-side authentication and authorization with proper checks, and once that is successfully done, use a random-generated token in order to authenticate the user on the mobile device.

· Broken Cryptography: This simply means use of nonsecure cryptographic functions in order to encrypt the data components. This might include some of the known vulnerable ones, such as MD5, SHA1, RC2, or even a custom developed one without proper security measures.

· Client Side Injection: This is possible in Android applications mostly due to the use of SQLite for data storage. We will be dealing with injection attacks in various chapters of this book as well.

· Security Decisions Via Untrusted Inputs: In mobile applications, developers should always sanitize and verify user-supplied inputs or other related inputs, and shouldn't use them as they are in the application. Untrusted inputs could often lead to other security risks in the application such as Client Side Injection.

· Improper Session Handling: While performing session handling for a mobile application, the developer needs to take care of a lot of factors, such as proper expiration of the authentication cookies, secure token creation, cookie generation and rotation, and failure to invalidate sessions at the backend. A proper secure sync has to be maintained between the web application and the Android application.

· Lack of Binary Protections: This means not being able to properly prevent the application from being reversed or decompiled. Tools such as Apktool and dex2jar could be used to reverse an Android application, which exposes the application to various kinds of security risks if proper developing practices have not been followed. To prevent analysis of applications by reversing from attackers, developers could use tools such as ProGuard and DashO.

Summary

In this chapter, we learned about reversing Android applications using various methods and analyzing the source code. We also learned how we could modify the source code and then recompile the application in order to bypass some of the protections. Also, we saw how to find vulnerabilities in Android applications using tools such as Drozer. You could also get your hands-on with various vulnerabilities in the Exploit-Me labs developed by Security Compass available at http://labs.securitycompass.com/exploit-me/.

In the next chapter, we will go a step further and do traffic interception of Android applications and use it in our pentesting.