Insecure transmission of sensitive information in Service

  CRITICAL  
Detection method   DAST         SENSITIVE INFO  

Description

An application puts sensitive information into an implicit Intent to launch a Service. This can lead to interception of information by external applications.

Interprocess communication (IPC) on Android is conducted using a special object—Intent. Parameters of Intent handlers are set in the main file of the application manifest—AndroidManifest.xml, or, in case of dynamic BroadcastReceivers, in the application's code. If an implicit Intent is used (i.e. an Intent that does not specify a component; instead, it generally defines an action to be conducted, and lets the system determine which of the available components is best to run for that Intent. For example, if there is a need to display a place on a map, the implicit Intent object can request another application, which has such feature, to provide this information. Data in such messages could be compromised. Moreover, malicious applications could use mechanisms of delegation of process control, such as implicit calls to application components or objects like PendingIntent, for interception of control and fishing attacks.

The following object types are dangerous: ActivityServiceBroadcastReceiver and ContentProvider, because they are open to communication with other applications and don't belong to system Android calls (such as android.intent.action.MAIN).  BroadcastReceiver is, by default, open to interaction with other applications, so the interception of control or of an Intent with confidential information is possible.

Recommendations

Don't include sensitive information into parameters when using implicit Intent.

Risks from using a Service and corresponding countermeasures vary depending on the ways this Service is used. To find out what type of a Service you are supposed to create, follow the table and chart below.

 

Type of a Service

Description

Private Service

A Service that cannot be used by other applications, and therefore is the safest one.

Public Service

A Service that can be used by an unspecified large number of applications.

Partner Service

A Service that can only be used by specific applications created by trusted partner companies. There is a special list of such applications.

In-house Service

A Service that can only be used by other applications of the same developer.

 

Picture 1

 

There are various implementations of a Service. Possible combinations of an implementation method and a service type are shown in the table below. OK—stands for a possible combination and blank fields show impossible combinations.

 

Implementation

Private Service

Public Service

Partner Service

In-house Service

startService

OK

OK

OK

IntentService

OK

OK

OK

Local bind

OK

Messenger bind

OK

OK

OK

AIDL bind

OK

OK

OK

OK


‎The below example will show the correct process of creation of the external Service and its usage. It is important to remember that sensitive information must not be sent when using external public Service.

Note! To ensure security of your application, always use an explicit Intent object for starting a Service, and don't declare Intent filters for your services. Starting a service using an implicit Intent bears security risks, because there is no certainty in what service will react to the Intent, and a user doesn't see what service launches. Starting from Android 5.0 (API level 21) the system throws an exception by calling the bindService() method using an implicit Intent object.

Creating and using a public Service

Public Service is a Service that can be used by any external application. It is worth mentioning that:

  • Public Service can receive an Intent from a malicious application
  • A malicious application can receive an Intent sent to a Public Service and/or read its data

Rules (creating a Public Service):

1. Explicitly set the "exported" attribute to "true"

2. Verify the received Intent and handle it in a secure manner

3. Do not include sensitive information into the resulting Intent

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.mobix.android.service.publicservice" >
        <application
                android:icon="@drawable/ic_launcher"
                android:label="@string/app_name"
                android:allowBackup="false" >
                <!-- Public Service is inherited from IntentService class -->
                <!-- *** 1 *** Explicitly set the "exported" attribute to "true" -->
                <service android:name=".PublicIntentService" android:exported="true">
                        <intent-filter>
                                <action android:name="com.mobix.android.service.publicservice.action.intentservice" />
                        </intent-filter>
                </service>
                </application>
</manifest>

PublicClientService.java

package com.mobix.android.service.publicservice;
import android.app.IntentService;
import android.content.Intent;
import android.widget.Toast;
public class PublicIntentService extends IntentService{
        /**
        * When inheriting IntentService class, a default constructor should be implemented, otherwise an error will arise
        */
        public PublicIntentService() {
                super("CreatingService");
        }
        @Override
        public void onCreate() {
                super.onCreate();
                Toast.makeText(this, this.getClass().getSimpleName() + " - onCreate()", Toast.LENGTH_SHORT).show();
        }
        @Override
        protected void onHandleIntent(Intent intent) {
                // *** 2 *** Verify the received Intent and handle it in a secure manner
                // See section "Secure Handling of the Input Data"
                String param = intent.getStringExtra("PARAM");
                Toast.makeText(this, String.format("Recieved parameter \"%s\"", param), Toast.LENGTH_LONG).show();
        }
        @Override
        public void onDestroy() {
                Toast.makeText(this, this.getClass().getSimpleName() + " - onDestroy()", Toast.LENGTH_SHORT).show();
        }
}

Rules (using a public Service):

Note! To avoid an accidental launch of another application's Service always use explicit Intent objects for starting your own services and don't declare Intent filters for them.

1. Use an explicit Intent

2. Do not include sensitive information into the data to be sent

 

package com.mobix.android.service.publicserviceuser;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
public class PublicUserActivity extends Activity {
        // Information about the target service
        private static final String TARGET_PACKAGE = "com.mobix.android.service.publicservice";
        private static final String TARGET_START_CLASS = "com.mobix.android.service.publicservice.PublicStartService";
        private static final String TARGET_INTENT_CLASS = "com.mobix.android.service.publicservice.PublicIntentService";
        @Override
        public void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.publicservice_activity);
        }
        public void onStopServiceClick(View v) {
                doStopService();
        }
        // Starting IntentService
        public void onIntentServiceClick(View v) {
                Intent intent = new Intent("com.mobix.android.service.publicservice.action.intentservice");
                // *** 1 *** Use an explicit Intent
                intent.setClassName(TARGET_PACKAGE, TARGET_INTENT_CLASS);
                // *** 2 *** Do not include sensitive information into the data to be sent
                intent.putExtra("PARAM", "Not sensitive information");
                startService(intent);
        }
        @Override
        public void onStop(){
                super.onStop();
                 doStopService();
        }
        private void doStopService() {
                Intent intent = new Intent("com.mobix.android.service.publicservice.action.startservice");
                // *** 1 *** Use an explicit Intent
                intent.setClassName(TARGET_PACKAGE, TARGET_START_CLASS);
                stopService(intent);
        }
}

Links

  1. https://developer.android.com/guide/components/intents-filters?hl=ru
  2. https://github.com/OWASP/owasp-mstg/blob/master/Document/0x05h-Testing-Platform-Interaction.md
  3. https://developer.android.com/training/basics/intents/index.html