SoFunction
Updated on 2025-04-07

Risks and Preventions of Component Export in Android Development

Preface

In recent years, a very important problem with mobile APP is security issues. The consequences may be user privacy leakage and property losses. This is undoubtedly the most fatal for a mature APP or a financial banking APP, so it is also necessary to effectively prevent APPs.
Recently, the company has arranged a security company to conduct comprehensive security tests on our APP. According to the document inspection results, it is still very safe overall. One of them is the risk of component export. Next, let’s talk about the four major components, the necessity of component export, risks, and how to prevent them.

1. Four components

We all know that Android has four major components, namely:

  • Activity, used to express functions, is a visual interface for user operations, which provides users with a window to complete operation instructions;
  • Service (Service), runs services in the background, and does not provide interface rendering;
  • Broadcast Receive, used to receive broadcasts;
  • Content Provider supports storing and reading data in multiple applications, equivalent to a database.

From a brief introduction to these components, we know their importance and give the app richer functions, so the security of these four components is more important to our app and users.

2. Necessity of component export

What is component export? Component export means that components can be called by external applications. We can set whether the components are exported in the manifest file declared by these four components, as follows:

        <activity
            android:exported="true"
            android:name=".">
        </activity>

or:

        <activity
            android:name=".">
            <intent-filter>
                <action android:name=""/>
            </intent-filter>
        </activity>

The above two methods are the exported method of Activity components, mainly the exported value". When true, it means export. The default value of exported in Activity:

  • When there is no intent filter, the default is false;
  • When there is an intent filter, the default is true

The default values ​​of Broadcast Receive and Service are the same as those of Activity.

The default value of exported in Content Provider:

  • When minSdkVersion or targetSdkVersion is less than 16, the default is true.
  • If it is greater than 17, the default is false

During the development process, the app will have some specific needs and will use the three-party SDK, such as WeChat sharing, payment, push and other functions. We found that there is one thing in common here, which will involve component export issues, such as WeChat's

WXEntryActivity:

        &lt;!-- Share on WeChat --&gt;
        &lt;activity
            android:name="${applicationId}."
            android:exported="true"
            android:launchMode="singleTask"
            android:theme="@android:style/" /&gt;

This will be detected by the security agency. If WXEntryActivity is not set as component export, WeChat sharing and other functions cannot be adjusted at all. This is the official way of writing. We believe that this must be set as component export. Unless you kill the WeChat sharing requirements, the service will not scold you to death; or it may be a broadcast receiver that monitors network changes (only above version 7.0 can only be dynamically registered in the code to receive the broadcast), push functions, and some push SDKs are integrated with some push SDKs and some services will also declare android:exported="true" and so on.
For these inevitable component exports, we can reply to the security agency: WeChat sharing, push and other functions must be set up to export components, so we can only ensure that the four major components are set up and ensure that they are safe, so that the app is in a relatively safe state, deal with security detection, and give your leader an explanation.

3. Component export risk

The importance of components and component export have been explained earlier. So what are the risks of component export?

  • Activity, as one of the four components that make up Apk, is the interface for Android programs to interact with users. If Activity has opened the export permission, it may be directly called out and used by the system or third-party apps. Activity export may lead to risks such as bypassing the login interface, denial of service attacks, and malicious call of the program interface by third parties.
  • As one of the four components that make up Apk, Broadcast Receiver filters and receives external events and performs responses based on the message content. If the export permission is set, it may be directly called out and used by the system or third-party apps. Broadcast Receiver export may lead to risks such as leakage of sensitive information and bypassing the login interface. S
  • As one of the four components that make up Apk, ervice is generally used as a service process running in the background. If export permission is set, it may be directly called out and used by the system or third-party apps. Service export may lead to denial of service attacks, and the program functions are maliciously called by third parties, etc.
  • Content Provider is one of the four components of Apk, which is a container for sharing data between applications. It can provide the specified data set of the application to third-party apps. If the export permission is set, it may be called out and used directly by the system or third-party apps. Content Provider export may lead to risks such as leakage of sensitive information inside the program, database SQL injection, etc.

Next, take Activity export as an example to illustrate its risks, and other components are just a good comparison. First, the Activity needs to be registered in the manifest file:

        <activity android:name=""/>

There are usually two ways to start an activity

  • To start explicitly, you need to specify the startup activity:
        Intent intent = new Intent(getContext(),);
        ("URL","");
        startActivity(intent);
        
  • Implicitly start, the Intent no longer contains the specific Activity class that needs to be started, but provides certain information through the Intent, and the system retrieves the Activity that meets the startup intention. Here, the Intent information is declared through the intent filter: action (action), data (data), classification (Category), type (Type), component (Component), and extension information (Extra).
        &lt;!-- Implicit startup requires declaration in the file--&gt;
        &lt;activity android:name="."&gt;
            &lt;intent-filter&gt;
                &lt;action android:name=".VIEW_URL" /&gt;
                &lt;category android:name=""/&gt;
            &lt;/intent-filter&gt;
        &lt;/activity&gt;

        //Calling WebActivity by calling        Intent intent = new Intent();
        (".VIEW_URL");
        ("URL","");
        startActivity(intent);

Use Action Jump. If an IntentFilter section of an Activity in a program defines the same Action that contains, then this Intent matches the target Action. If Type or Category is not defined in this IntentFilter segment, then this activity matches. However, if there are more than two programs in the phone that match, a dialog box will pop up to prompt the explanation.
As mentioned above, there is an IntentFilter. If android:exported is not specified, the value defaults to true. External applications can also start the corresponding components through implicit intent. In this case, we are the component export we are talking about, and export means that there is a very likely security problem. Let’s take a look at the WebActivity page:

        Intent intent = getIntent();
        String url = ("URL");
        (TAG, (0));
        (url);
        

We noticed that WebActivity only receives a URL and displays it (the URL is not loaded). From here we can see that the URL has not been checked for parameter, and the application may crash; because the page can be called by a three-party application. At this time, if someone maliciously passes some bad web page information, then your application will be loaded directly without intercepting it, and the application may be removed from the shelves.

4. How to prevent

We use the most common Activity as an example to illustrate the risks of component export, because this URL parameter is handled by us, and we can prevent the application of null pointer exceptions. This is OK, but the above also says what if a bad URL is loaded? In fact, the most fundamental reason for the risk of component export is that it is called by others. Is there any way to control the scope of others and only allow people we trust to call it.
Here we have to mention the permission mechanism of Android. Android's Permission check mechanism is used to control which execution rights an application has. For example, an application has the right to take photos to have the right to take photos. So can we control whether an application has the right to start WebActivity through permissions?
Android provides the ability to customize permissions. Applications can define their own permissions, such as customizing a permission in the manifest file:

    &lt;permission
        android:label="Allow permission to open WebActivity pages"
        android:name=""
        android:protectionLevel="signature" /&gt;
        

label: a description of permissions

name: The name of the permission, and the permission to be used is specified by the name when using this permission.

protectionLevel: This permission is protected, which is important, it has three levels

  • signature: signature level permission, that is, the defining party and the registrant of the permission must have the same signature to be valid
  • system: system-level permissions, that is, the definer and registrant of the permissions must be applied to the system
  • signatureOrSystem: same signature or system application, one of the above two is enough

The permission definition is completed. How to use it to protect exposed components? See the following code:

        &lt;!-- Implicit startup requires declaration in the file--&gt;
        &lt;activity
            android:permission=""
            android:name="."&gt;
            &lt;intent-filter&gt;
                &lt;action android:name=".VIEW_URL" /&gt;
                &lt;category android:name="" /&gt;
            &lt;/intent-filter&gt;
        &lt;/activity&gt;

When the activity is declared, there is a permission under the activity tag. Through permission, you can specify the permission name to protect the activity. In this way, only the activity with this permission can be started (note that both the definition party and the user must define and declare custom permissions in the manifest file), and declare and use the permission in the caller's manifest file:

    &lt;!--The caller does not need to declare it--&gt;
    &lt;permission
        android:label="Allow permission to open WebActivity pages"
        android:name=""
        android:protectionLevel="signature" /&gt;
    &lt;!--The caller must apply for this permission--&gt;
    &lt;uses-permission android:name=""/&gt;

With permission control, the scope of export of activity components can be controlled. When there are mutual component calls between our company applications, the permissions with the same signature can be used to restrict it. As for other applications, they cannot call the components we exposed, which effectively avoids risks.
Activity is our most common component, but BroadcastReceiver also uses a lot of places. Generally, security evaluations mention this component. We need to mention it. In fact, the security control of each component can also be controlled through permission.
There are two ways to register BroadcastReceiver

  • Static registration, declare registration in Manifest
  • Dynamic registration, rely on other components in the code, register through registerReceiver

BroadcastReceiver has the sender and receiver of the broadcast, so when using permission to verify communication, it generally requires two-way verification, that is, both the sender and the receiver of the broadcast need to add permission verification to ensure that the sender only sends the broadcast to the trusted receiver, and the same receiver only accepts broadcasts from the trusted party.

Broadcast sender

The sender needs to declare permissions in the manifest file:

    &lt;permission
        android:label="Declare sender permissions"
        android:name=".BROADCAST_SEND"
        android:protectionLevel="signature" /&gt;
        

Then use the sendBroadcast(Intent intent, String receiverPermission) method to send the broadcast:

        //Send broadcast        Intent intent = new Intent();
        ("");
        sendBroadcast(intent, ".BROADCAST_SEND");

From the literal meaning of receiverPermission, you know that the receiver must apply for the custom permission.BROADCAST_SEND, otherwise, you will not be able to receive the action notification, such as the receiver's manifest file:

    &lt;!-- The receiver needs to apply for sender permissions--&gt;
    &lt;uses-permission android:name=".BROADCAST_SEND"/&gt;

If the receiver's broadcast receiver does not control its own permissions, the same developer application can only listen to this action, but for double verification, we also need to declare our own permissions to the receiver.

Broadcast Receiver

We define a broadcast receiver TestReceiver:

public class TestReceiver extends BroadcastReceiver {
    private static final String TAG = "TestReceiver";

    //Received a callback of broadcast information    @Override
    public void onReceive(Context context, Intent intent) {
        //Some legal checks should be made for external parameters        String action = ();
        if ((action)) {
            return;
        }
        (TAG, "action:" + action);
    }
}

Then declare control permissions in the manifest file:

    &lt;permission
        android:label="Declare the recipient's permission"
        android:name=".BROADCAST_RECEIVER"
        android:protectionLevel="signature" /&gt;

Then give this control permission to the broadcast receiver. The receiver has two ways to register.
Static registration method, in the manifest file:

        <receiver
            android:name="."
            android:permission=".BROADCAST_RECEIVER">
            <intent-filter>
                <action android:name=""/>
            </intent-filter>
        </receiver>

Then there is the dynamic registration method, which states where you need to register:

Receiver receiver = new Receiver();
IntentFilter intentFilter = new IntentFilter();
("");
registerReceiver(receiver, intentFilter, ".BROADCAST_RECEIVER", null);

Both of these registration methods are OK, but it is recommended to use dynamic registration broadcasting method, because Android O has put a lot of restrictions on static registered broadcasting for the sake of App performance and power consumption. As for what limitations are, I won't talk about it here.
We have also restricted the permissions of the receiver, so the sender must also apply for this permission to send an action to it. Therefore, the sender's list file needs to be added on the original basis:

    &lt;!-- The sender needs to apply for the recipient's permission--&gt;
    &lt;uses-permission android:name=".BROADCAST_RECEIVER"/&gt;

At this point, the two-way inspection of broadcasts has been completed. All the above codes have been tested, without any problems, filtering irrelevant broadcasts well and protecting the security of components.

Summarize

The article mainly talks about the meaning and importance of the four major components, and then explains why component export and export risks are required. Some components are exported because some specific functions are to be implemented, but for controllable components, try not to export. If we need to export components, we need to strictly check the parameter to prevent crashes; in addition, the best prevention is to add permissions, so as to effectively prevent malicious calls and unnecessary losses.

This is the end of this article about the risks and prevention of component export in Android development. For more related content on Android component export, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!