Android hacking and security, part 3: Exploiting broadcast receivers
In the first two articles, we discussed attacks associated with Activity Components, content provider leakage and ways to secure them. In this article, we will discuss attacks on broadcast receivers.
What are broadcast receivers?
A broadcast receiver is another important component of the Android system. Broadcast receivers are registered for specific events to occur. When the event occurs, the receiver gets invoked and performs tasks, such as showing a message to the user. What we can do with broadcast receivers is up to the creativity of the developer, as a lot of stuff can be carried out with them.
To understand the security risks associated with the broadcast receivers, we should know how the events are broadcasted. There are two types of events.
- System Events
An application can be registered to receive broadcasts occurred by system events such as BOOT COMPLETE, SMS RECEIVED, BATTERY LOW, etc. When an application is registered for an SMS RECEIVED event, its receiver will be invoked every time a new SMS is received.
- Custom Broadcasts
Apart from the system-generated events, an application also can generate custom broadcast intents for which we can register a receiver.
Now, let’s ask ourselves a few questions.
- When our app is sending a broadcast intent, is it received only by the intended application, or can all the applications receive it?
- When we register a receiver, are we receiving the broadcasts only from legitimate sources, or can any other malicious app spoof those broadcasts?
If the developer doesn’t enforce controls on who can broadcast and who cannot broadcast, obviously the answer is YES. If the receiver accepts broadcasts from untrusted sources, it may put our application at serious risk.
To demonstrate how one can exploit such scenarios, I have developed a simple application.
Please fill out the form below to download the APK file and Source Code.
Prerequisites to follow the steps
- Computer with Android SDK Installed
- Two Emulators (In my case, emulator-5554 is where the vulnerable app is installed; emulator-5556 is to receive an SMS from the vulnerable app).
Test application’s functionality
Once after downloading the test application, install it in an emulator in order to test and exploit it.
It can be installed with adb using the following command:
[c]adb install <name of the apk>.apk[/c]
When we launch the application, it appears as shown in the figure below. We need to register a specific mobile number using the registration activity as shown in the figure. Once, after clicking the submit button, a custom broadcast will be sent and we will receive a confirmation SMS to the registered number (emulator-5556 in my case).
App running on Emulator-5554
The Goal is to send spoofed broadcast intents and see if the application is accepting them. If yes, we will exploit the application to send an SMS to some random mobile numbers using the fake broadcasts.
- Understanding the application functionality
- Attacking vulnerable broadcast receivers
- Securing the applications
Understanding the application functionality
A broadcast receiver “MyBroadCastReceiver” is registered in the AndroidManifest.xml file.
Broadcast receivers are generally registered in the following format. The code seems insecure since the receiver is exported.
The application is sending intent using the following piece of code, in which “input” is the mobile number we are receiving as the user input.
The following piece of code takes the mobile number from the broadcast and sends a confirmation SMS to the registered number.
In the next section, we will try to exploit the above functionality by sending broadcasts from untrusted sources.
Attacking vulnerable broadcast receivers
Let’s now try to send some spoofed broadcasts to the above receiver. This can be done in multiple ways.
- Using am tool available in adb
- Using a Malicious app to query
- Using Mercury Framework
. Get an adb shell on the device and type the following command to send a spoofed broadcast.
am broadcast -a MyBroadcast -n com.isi.vul_broadcastreceiver/.MyBroadCastReceiver
The above command sends a broadcast, but it has no mobile number included. We can pass the mobile number as a string using the –es option available with the am tool. Now, the above command becomes:
am broadcast -a MyBroadcast -n com.isi.vul_broadcastreceiver/.MyBroadCastReceiver –es number 5556.
The same is shown in the figure below.
Now, a broadcast event is sent in the background, and since the application is not validating the input source, an SMS will be send to emulator-5556 without user intervention.
Using a malicious app to query
We can also write a malicious app to send broadcasts and exploit the functionality of the vulnerable app. The best part is, malicious app doesn’t need SEND_SMS permission since it uses the permission registered by the vulnerable app.
Using Mercury framework
The entire process can be carried out using Mercury framework in even more efficient and simple way.
Securing the applications
- Setting android:exported attribute’s value to false
In the AndroidManifest.xml file of our application, we should add the following attribute to the receiver to be secured.
- Limiting access with custom permissions
We can also impose permission-based restrictions by defining custom permissions for each receiver. This is helpful if the developer wants to limit the access to his app’s components to those apps which have permissions.
This is the reason why we need to specify “android.permission.RECEIVE_SMS” permission in the AndroidManifest.xml file if any app wants to listen for the Receive SMS event using the action “android.provider.Telephony.SMS_RECEIVED”
In Android, broadcast receivers provide great functionality to develop creative applications. But when proper security controls are not enforced, that may lead to serious attacks. So, it is always a good idea to test all the application components during a pentest.