Insecure transmission of sensitive information in internal Service
INFO | |||
Detection method | DAST SENSITIVE INFO |
Description
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: Activity
, Service
, BroadcastReceiver
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. |
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 |
Creating and using a private Service
Private Services are Services which cannot be launched by the other applications and therefore it is the safest Service. When using Private Services that are only used within the application, as long as you use explicit Intents to the class then you do not have to worry about sending it to any other application.
Rules (creating a Private Service):
1. Explicitly set the exported attribute to false, exported="false".
2. Handle the received intent carefully and securely, even though the intent was sent from the same application.
3. Sensitive information can be sent since the requesting application is in the same application.
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.mobix.android.service.privateservice" >
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:allowBackup="false" >
<activity
android:name=".PrivateUserActivity"
android:label="@string/app_name"
android:exported="true" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- Public Service is inherited from Service class -->
<!-- *** 1 *** Explicitly set the "exported" attribute to "false" -->
<service android:name=".PrivateStartService" android:exported="false"/>
</application>
</manifest>
PrivateStartService.java
package com.mobix.android.service.privateservice;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.widget.Toast;
public class PrivateStartService extends Service {
@Override
public void onCreate() {
Toast.makeText(this, "PrivateStartService - onCreate()", Toast.LENGTH_SHORT).show();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// *** 2 *** Handle the received intent carefully and securely, even though the intent was sent from the same application.
// See section "Secure Handling of the Input Data"
String param = intent.getStringExtra("PARAM");
Toast.makeText(this,
String.format("PrivateStartService\nReceived parameters: \"%s\"", param),
Toast.LENGTH_LONG).show();
return Service.START_NOT_STICKY;
}
@Override
public void onDestroy() {
Toast.makeText(this, "PrivateStartService - onDestroy()", Toast.LENGTH_SHORT).show();
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
Rules (using a private 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 the explicit intent with class specified to call a service in the same application.
2. Sensitive information can be sent since the destination service is in the same application.
3. Handle the received result data carefully and securely, even though the data came from a service in the same application.
PrivateUserActivity.java
package com.mobix.android.service.privateservice;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
public class PrivateUserActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.privateservice_activity);
}
// StartService
public void onStartServiceClick(View v) {
// *** 1 *** Use the explicit intent with class specified to call a service in the same application.
Intent intent = new Intent(this, PrivateStartService.class);
// *** 2 *** Sensitive information can be sent since the destination // service is in the same application.
intent.putExtra("PARAM", "Sensitive Information");
startService(intent);
}
public void onStopServiceClick(View v) {
doStopService();
}
@Override
public void onStop() {
super.onStop();
doStopService();
}
private void doStopService() {
// *** 1 *** se the explicit intent with class specified to call a service in the same application.
Intent intent = new Intent(this, PrivateStartService.class);
stopService(intent);
}
}