This is a blog post which I wrote partially a lot of time ago (like other posts that I have never published) because currently I am busy with my job and other stuff that I like to do. In addition, currently I am doing the OSEP course of Offensive Security which is funny but the course is very large (maybe I will write about that course in future).

In my latest project that I have been involved with,  I have been performing some penetration testing against mobile devices and I would like to let some anotation about how to perform some parts of this penetration test.

In this first post I am going to write about how to perform the static analysis of the applications (APK) finding exported components like content providers, services, receivers and activities.

In addition, after find some exported components, we interacts with these components in order to exploit (or abuse) them. Thus, this post will cover three points:

  1. Obtain the APKs available in the Android device;
  2. Static analysis of the APKs; and
  3. Dynamic test of the componentes.


Obtaining APKs from Android device

There are a lot of tools that perform this task, but in this post we are goint to use the minimum of tools necesesary to perform the obtaining and analysis of the applications. So, in this case we just use adb and bash.


After API level 8 you can install the applications in the external storage. It can be performed adding android:installLocation="preferExternal" to the manifest, although if external storage is full, the application will be installed in internal storage.

The applications are stored in multiple path, depending of the kind of application:

  • /system/app -> system applications and pre-installed applications
  • /system/priv-app -> system applications and pre-installed applications
  • /product/priv-app -> System applications (Android 9 and higher) 
  • /vendor/priv-app -> System applications (Android 9 and higher)
  • /data/app -> normal applications
  • /data/app-private -> some applications


With this information and a little knowledge in bash:

Listing the installed packages:

adb shell pm list packages

Show path where is installed a package:

adb shell pm path package

All together:

for i in $(adb shell pm list packages | awk -F':' '{print $2}'); do adb pull "$(adb shell pm path $i | awk -F':' '{print $2}')"; mv base.apk $i.apk 2> /dev/null ;done


Exported components

This point has their own CWE, CWE-926: Improper Export of Android Application Components [3]. Android applications have different kinds of components, activities, receivers, services and content providers. These components are declared in the AndroidManifest.xml

An activity is a components that provides a user interface for the user interact with visually.

A broadcast receiver is a component that allows to applications to send and receive messages from Android system or other applications.

A service is an application component that performs operations in background without user interface.

A content provider is a component of an android application that provides its own UI for working with the data.

The android components can be defined with different arguments, one of them is android:exported . If this parameter is true the activity can be called  by different applications (and users), depending of other argument android:permission. By default, if the activity does not have intent filters the value is false. These activities can receive arguments called extras. 

For services, the default value of exported depends on if the service contains intent filters. If the component does not contains intent filters, it can be only called from the own application, in that case the default value is false. On the other hand, if the component contains one or more intent filters implies that the service is exported by default.


This exported component can be tested with the following command line (these commands run with the associated used to adbd in Android device):

adb shell am start -n com.xxxx/xxxx.LaunchActivity --es "aaaa" aaaa 


Or making an application and calling the exported activity:

try {
    output.setText("Trying to open activity...");
    Intent intent = new Intent();
    intent.setClassName("com.xxxx","com.xxxx.LaunchActivity");
    intent.putExtra("flags", "com.xxx.SomeExtras");
    startActivity(intent);
} catch (Exception ee) {
    Toast.makeText(getApplicationContext(), ee.toString(), Toast.LENGTH_SHORT).show();
}

For a broadcast receiver:

adb shell am broadcast -a xxx.ACTION com.xxxx/xxxx.Receiver
Service:
adb shell am startservice com.xxxx/com.xxxx.SAService
Content provider:

adb exec-out content query --uri content://com.xxxx


Obtaining all exported components
At this point the creativity is the most important thing. It can be performed by different ways and commands. As has been explained before, the exported components are in AndroidManifest.xml, thus if we parse these AndroidManifest.xml in order to find exported components in all the applications we have downloaded we will obtain all the exported components and we can prove them.


# Getting providers
find . -mindepth 3 -maxdepth 3 -name AndroidManifest.xml -exec cat {} \; | grep "<provider android" | grep "android:exported=\"true\"" | grep -Eio "android:authorities=\".*\" " | awk '{print $1}' | sed "s/android:authorities=//; s/\"//g"
# Getting services
find . -mindepth 3 -maxdepth 3 -name AndroidManifest.xml -exec cat {} \; | grep "<service android" | grep "android:exported=\"true\"" 
# Getting receivers without permissions
find . -mindepth 3 -maxdepth 3 -name AndroidManifest.xml -exec cat {} \; | grep "<receiver android" | grep "android:exported=\"true\"" |grep -v "android:permission"


To be continue... Because it can be extended a lot.


More information

[1] https://developer.android.com/guide/topics/data/install-location

[2] https://source.android.com/devices/tech/config/perms-allowlist

[3] https://cwe.mitre.org/data/definitions/926.html