Android InsecureBankv2 Walkthrough: Part 2

Hacktivities
InfoSec Write-ups
Published in
10 min readJul 28, 2020

--

In this article, I will be continuing my walkthrough of the InsecureBankv2 Android application created by the GitHub user dineshshetty. Check out Part 1 to see how to setup the application and some of the application’s insecurities I have already demonstrated. I have left a link to application’s GitHub repository in the references below.

Disclaimer

As I stated in Part 1, I was inspired to make this article out of an interest to learn more about Android mobile application security. This article will obviously contain spoilers about the vulnerabilities present in the InsecureBankv2 Android application. I encourage readers to exploit as many vulnerabilities as they can and then come back later to read this article if you get stuck or want to see a potentially different approach to exploiting an insecurity. Lets get started 😄!

Vulnerable Android Application Components

Continuing my walkthrough of the InsecureBankv2 application from Part 1, I decided to use a tool called Drozer to identify any vulnerabilities with the application’s Android components. I can use Drozer to enumerate the attack surface of the application and find any vulnerabilities using the command below.

run app.package.attacksurface com.android.insecurebankv2

After running the command above, the following output is provided.

Looking at the output, I can see that the application has exported five activities, one broadcast receiver and one content provider. If a component is exported in the applications manifest file, then any application on the device can access these components once they have the right permissions. The application also has set the manifest attribute debuggable to true, enabling the application to be debugged. This provides a helpful starting point for analyzing the application for vulnerable components.

N.B. It is worth mentioning that all this information can also be found in the application’s AndroidManifest.xml file manually.

Exported Activities

Drozer had identified five exported activities based on the output above. I already mentioned in Part 1 how the login functionality of the application could be bypassed due to exported activities. To find out more information about these activities, Drozer can be used to list all the exported activities of the application.

run app.activity.info -a com.android.insecurebankv2

The output below shows a list of all the activities exported by the application.

The output shows the name of the activity as well as the permission needed to launch it. The permissions for these activities are all null, which means any application can launch them. Using ADB as seen in Part 1 or Drozer, I can launch these activities and bypass the login activity.

run app.activity.start --component com.android.insecurebankv2 com.android.insecurebankv2.PostLogin

The Drozer command above can be used to start the “PostLogin” activity.

Exported Broadcast Receiver

The application has exported a broadcast receiver.

N.B. Broadcast receivers are designed to listen to system wide events called broadcasts (e.g. network activity, application updates, etc.) and then trigger something if the broadcast message matches the current parameters inside the Broadcast Receiver.

Using Drozer, I can find out more information about this receiver with the command seen below.

run app.broadcast.info -a com.android.insecurebankv2 -i 

The following information is returned.

I can see that the name of the receiver is called “MyBroadCastReceiver” and has been exported with null permissions. An intent filter has been set for the component, with the broadcast action the receiver subscribes to (i.e. “theBroadcast”). It’s important to identify what this broadcast receiver does before I can exploit it by looking at the source code. The file “MyBroadcastReciever.java” file contains the source code that will be executed when a broadcast is received.

In the source code, I can see that the intent used to trigger the broadcast receiver has two parameters (i.e. “phonenumber” & “newpass”) which are retrieved. The credentials in the “mySharedPreferences” file are then retrieved and decoded/decrypted before being combined into a single string that will be sent as a text message using the “smsManager” class. Using the information collected so far, I can trigger the broadcast receiver using Drozer. The command below uses the “theBroadcast” action and passes two string parameters which are required for the receiver to be triggered and the code for the receiver executed.

run app.broadcast.send --action theBroadcast --extra string phonenumber 123456789 --extra string newpass supersecurepass

I can now see on my emulator that the application has sent an SMS message with the users old password and the new password I specified.

This demonstrates how any application, including malicious ones, can send an intent to this broadcast receiver causing it to be triggered without any restrictions.

Exported Content Provider

The application has exported a content provider.

N.B. Content providers are used to share app data with other applications, which is normally stored inside a database or file.

I can use Drozer to learn more about this exported content provider with the command below.

run app.provider.info -a com.android.insecurebankv2

The image below shows the information returned about the content provider.

The read and write permissions are set to null, which means there’s nothing stopping me from querying the data stores through the content provider. To query this content provider, I can use Drozer to identify any accessible content URI’s.

N.B. Content Provider URI’s begin with “content://” and can be used to reconstruct a path that can retrieve data from the content provider.

run scanner.provider.finduris -a com.android.insecurebankv2

An accessible content provider URI was discovered as seen in the image below.

Using Drozer, I can query this content provider using the content URI identified with the following command.

run app.provider.query content://com.android.insecurebankv2.TrackUserContentProvider/trackusers

This returns a table of usernames and user ID’s from an SQLite database that tracks the login of users as implied by the name of the content provider.

Android Manifest File Security

Apart from declaring the components of an application (i.e. activities, services, broadcast receivers, and content providers), the manifest file is also used to define attributes to enable certain features and declare permissions needed by the application. A developer can leave their application vulnerable if they enable or misuse certain attributes.

Debug Mode Enabled

Drozer identified that the application was debuggable. This is due to the developer leaving the android:debuggable attribute set to true in the manifest file.

If an Application is marked as debuggable then an attacker can access the application’s data by assuming the privileges of that application. For example, I can start a shell on my emulator and then switch to a non-root user. I can then use run-as to view the contents of the package’s directory where normally I would not have permission.

I can even use run-as to retrieve files that would normally be stored securely in the applications data directory.

adb exec-out run-as com.android.insecurebankv2 cat databases/mydb > mydb-copy

Another approach is to use a tool called jdp (Java Debugger) to debug the application and discover interesting information. The first step is to use jdwp to identify what port the application is running on. Run the command below while the target application is closed and then run it again while the application is active. Note the new port number that has appeared.

N.B. The application port will most likely be different to the one seen in this article.

adb jdwp

I can then create a communication channel with ADB between the application port and my workstation.

adb forward tcp:7777 jdwp:2906

Using jdb, I then attach the debugger to the target application.

jdb -attach localhost:7777

The following output should be displayed when the debugger is attached.

I can view what classes and methods are in the application by using the “classes” and “methods” commands. I can also use jdb to setup a breakpoint at certain methods and control the execution of the app by using the “stop in” command. For example, I can see what methods are in the “LoginActivity” class.

> methods com.android.InsecureBankv2.LoginActivity

This provides a long list of methods. I decided to use the “creatUser()” method to demonstrate how to change the value of a local variable.

I set a breakpoint at this method and then click the create user button.

N.B. If you do not see a create user button then check out Part 1 of this article series on how to patch the APK.

> stop in com.android.InsecureBankv2.LoginActivity.createUser()

This causes the breakpoint to be hit. I can use the “step” command to execute the next line of code and the “locals” command to see any local variables at a certain point in the codes execution, as seen in the figure below.

I can change the text message displayed by using “set” and then continue the execution of the code with “run”.

This will then print my new message in place of the original.

Application Backup Enabled

The application has the android:allowBackup attribute set to true in the manifest file.

This allows an attacker to make a backup of the application data via ADB even if the device is not rooted. I can use the adb backup command to create a backup of the “com.htbridge.insecurebankv2” package. Depending on the Android OS version you have, you may be prompted for a password that will be needed later to unpack the backup file.

adb backup com.android.insecurebankv2

This creates a “backup.ab” file that must be unpacked. I can accomplish this by using the abe.jar file to convert the backup file to a tar file. I also provided the password used when creating the backup file (i.e. password), as seen below.

java -jar abe.jar unpack backup.ab application-data.tar password

I can then untar the “application-data.tar” file and view the contents of the backup file.

tar xvf application-data.tar

Looking through the contents of the backup, I can see files such as “mySharedPreferences” and “mydb” which contain sensitive information about users.

Insecure Logging

In some of the previous snippets of source code shown in this article, you may have noticed that the application produces log messages when performing a lot of tasks. For example, the “DoLogin” activity produces a debug log message whenever a user attempts to login.

These logs can be dumped using logcat. The command below will show all the log messages for the application while it is running.

adb logcat | grep "$(adb shell ps | grep com.android.insecurebankv2  | awk '{print $2}')"

If I attempt to login while logcat is running, I will see a log message that shows the username and password I used to successfully login.

Intent Sniffing and Injection

The application is vulnerable to both intent sniffing and intent injection.

N.B. An Intent is a messaging object you can use to request an action from another app component.

The applications uses an implicit intent when changing the password for a user. This message is broadcasted to every application on the device and contains sensitive data.

N.B. There are two types of intents, implicit and explicit. An explicit intent is one that you use to launch a specific app component, such as a particular activity or service in your app. An implicit intent specifies an action that can invoke any app on the device able to perform the action.

I can perform intent sniffing using Drozer and look at the sensitive content of the intent. The command below is used to register a broadcast receiver that can sniff particular intents based on the action. I know the action used by the intent filter for the receiver (i.e. “theBroadcast”) component from analyzing the manifest file earlier

run app.broadcast.sniff --action "theBroadcast"

When I attempt to change the password, Drozer receives the intent and I can view the sensitive data.

An intent injection attack works by injecting an intent into the application component to perform a task that is usually not allowed by the application workflow. I demonstrated earlier how to exploit a vulnerable broadcast receiver that had been exported by injecting the component with an intent containing my own data.

run app.broadcast.send --action theBroadcast --extra string phonenumber 123456789 --extra string newpass supersecurepass

Closing Remarks

This concludes Part 2 of my walkthrough for the the InsecureBankv2 Android application. In Part 3, I will be looking at more vulnerabilities that can be found in the application and demonstrate how they can be exploited. Thank you for reading to the end and I’ll see you in Part 3😄!

--

--