We’re delighted to present the third post in the Android security series. This series aims to cover Android security from the basics to advance. We have previously covered many of the basics and intermediate topics in this series, so in this blog post, we will dive deeper into Android security.
Here is the simple flow diagram we have created for better understanding,
In short, white lines indicate prerequisites, red lines indicate deeplink vulnerabilities, and green lines indicate vulnerabilities that can be exploited using webView. The same vulnerabilities may be exploitable if we can control deep links via webView.
We need to start by looking at AndroidManifest.xml. It is important first to identify whether the activity is exported or not. If we found activity exported and permissions are well configured, then it becomes not exploitable. In some cases, activities are not exported, but permissions are incorrectly configured. As long as that’s the case, we may exploit the activity. As a result, there are two scenarios: Either the activity should be exported without permission or not exported, but its permissions should be misconfigured.
In addition, it is important to determine whether the activity is a webview or a deep link, although each activity might have its purpose. Once we confirm these things, we can move and analyze the Java class files. We have to look for sensitive functions in activityclass.java like
setAllowContentAccess() or file accessing functions. Now it depends on the purpose of the activity. For example, if the activity uses the
I hope you got some idea about the flow diagram. Now let’s have a quick look into vulnerabilities one by one.
Deep links allow us to trigger an intent via a URL embedded in a website. This allows the app to start and pass the data. We can look for the scheme tag with Browsable Category in AndroidManifest.xml File.
The general representation of deep link is as follows
So accordingly, our deep link will be
http://example.com/webview, which will help us to trigger the app, which we’ll cover later, but let’s understand how to exploit the deep link.
For demo purposes, we need insecureshop apk. In the androidmanifest.xml file, we can look for deep link activity
As previously explained, our deep link will be
insecureshop://com.insecure shop because we got only this much information from the AndroidManifest file first to test whether we can trigger the app with this. Save the following code in exploit.html
Host the file locally by pushing the exploit on the device
or Remote server
Now just open the file in the browser and click on start attack
As you can see, we can trigger the app via a deep link on a web page. But wait, that’s not a flaw. It’s a feature. This is just for understanding how deep links actually work.
Let’s check the class of the activity if we find something that might become exploitable.
If we look into the code, we have two paths,
/webview, where the input string “url” will execute according to the condition.
so our exploit will be
Let’s have a look if it works –
It’s worked. This is one example of how we can load arbitrary websites to the victim’s app. Depending on the activity class’s path, functions and conditions, this may vary from app to app.
Another attack vector for exploiting deep links could be stealing sensitive information from the victim app. Let’s assume that while playing with burpsuite or while testing for hardcoded data or by any other method, we found one endpoint, which may be
api/v2/apikey="", api/v2/userinfo="", /sessionID="" which can give access to some sensitive information. Now we can design our payload according to the same
"insecureshop://com.insecureshop/web?sessionID=" as the victim clicks on that link, the app will trigger, and it will visit the session ID in his app, the webview will render with the directory information present, and we get that info on our server.
This is how we can steal sensitive information from the victim’s app.
If any app has functionality triggered with a deeplink, we can trick the user into performing unwanted actions; the best example of CSRF is https://hackerone.com/reports/583987. In the periscope, the app researcher can force the victim to follow. It may vary case by case. For example, if we have delete account functionality which triggers via deep-link, then our link will be “Insecureshop://com.insecureshop/delete”, and our exploit could be
Most of the time, the app does not correctly validate the URL. For example, it ignores backslash, forward slash, IDN Homographic characters etc., which leads to attacks such as Open Redirection, Injecting malicious script or disclosing internal information. Consider
"Insecureshop://com.insecureshop/?url=http://example.com" This is the expected URL to the app, but what if we might submit “
Insecureshop://com.insecureshop/?url=bing.com/\\alert()” to the app. It ignored the first URL and executed our payload, or with this domain, it also executed our payload, which will become a significant attack vector for us. Let’s have a look at Webview
WebViews are effectively web browsers embedded into Android Apps. WebViews content can be pulled from remote sites or files included in the app. WebViews are vulnerable to the same vulnerabilities affecting any web browsers. However, some configurations can be useful to limit the attack surface. Types: WebChromeClient & WebViewClient.
How WebBrowser & WebView are different?
In case we find a webviewactivity exported without any permissions, we will firstly look for
The following code is an example. If we found the loadData function firstly, we would store our HTML in one string, and then it passed to the function.
If we have the
In the android manifest file, we can check that the webviewactivity is exported without configured permission.
When we look into class, we understand that code is not readable because of obfuscation.
but after deobfuscation, we can read the code and analyze that the function is accepting string via setUrl function
To test that, we can start an activity and pass the data to it. We can either test it via adb or create a third-party app., but for now, we will test it with adb by using the following command.
Let’s see if it works.
There is a vulnerability in the system that can allow malicious third-party apps on the device to steal any file from the local storage of the victim’s app. The following functions allow passing
file:// scheme and local files via webview.
but not limited, you can also call loadUrl(“file:///”) function for Arbitrary File Access as we have setUrl() function we can look for if it is possible to steal sensitive files by using the following command where we used “file:///” scheme.
Let’s see if it’s works.
And see it’s worked!
In this way, we can test for arbitrary file access
If you find
navigator.Contacts. Other than this, we have the setAllowConentAccess() function, which invokes content providers to pass URI with content:// scheme, so if any content provider is handling sensitive information, then we might be able to retrieve that information.
This section is with rare scenarios.
1. Suppose we have three activities login, 2FA & Dashboard activity. If Dashboard Activity is exported and permissions are missing, then after login, we may be directly able to start the dashboard activity. Likewise, if there is no proper configuration, we can bypass 2FA.
2. Now Another case, while looking into source code, we may find the activity of function only accessible by admin and not by normal users, so if that activity is exported and with no mandatory permission, we can start that activity access that functionality. In this way, we can bypass Authorization.
Sometimes one activity is protected, but it can start with another export action. For example, read this report. In this report, the researcher started webview activity with exported activity.
These kinds of vulnerabilities are rare and may vary from app to app.
A content provider is a component that fetches data that the app requests from a repository in a secure manner. Let’s understand with one example how it works.
In this example, we took two apps, WhatsApp and the contact app, so as we know, WhatsApp needs contact access. So firstly, with the help of the content resolver, WhatsApp creates a request for accessing contacts, and then the contact application checks whether the content provider is implemented. If yes, it will look for the data which WhatsApp requested. Then, after checking permissions, the cursor returns to WhatsApp with the requested data.
That was a general example of how things work.
Structure of Content URI
We can identify content providers under the <provider> tag in the android manifest. While constructing a query, we need to consider two parts –Selection & –Projection. Selection is a part where we need to specify which column or row we want and from which table, whereas in the selection part, we have to specify the condition.
How to approach the content provider?
In the above flow, we have to first look for a provider that is exported without mandatory permissions. Now sometimes the provider is exported, but there are permissions. Still, the developer forgets to protect paths such as sometimes content://provider/ this is protected, but content://provider/vulnpath is not protected so that we can take benefits of that, now when we have any two of the above condition, we can directly look for data retrieving the data via that provider. Other than this, we look into the provider class, and if we find some misconfiguration, such as Broken Query could be the entry point for SQL injection or if FileProvider is enabled, then either we look for Local File Access or Path Transversal.
Let’s have a look at how practically we can exploit content providers:
Open Diva Application and check Access Control Issue – Part 3
A feature allows you to establish a pin for private notes, and those notes can only be accessed after entering the pin. There is no other method to access such notes without first verifying the pin. Now where data operations come from, the content provider is involved.
Let’s go with the flow and see if we found something. Check AndroidManifest.xml
So as we can see, there is a provider which is exported now permissions we can check with the help of drozer. if you need help setting up a drozer, check here. Once the drozer is successfully set up, access the drozer console and check for the package name by the following command. With drozer, we can do a lot of things without going manually. But for now, we only look for the content provider. We can get all the provider URIs from apps using the following command.
So get back to flow and check permissions
as there are no permissions, we can check provider class.
After looking into class, we got to know that the notes could be accessible via
content://jakhar.aseem.diva.provider.notesprovider/notes URI, so now we can query whether it allows us to access the notes without verifying the pin. We can make the request using the
As we can see in the above image, we can access the notes without having any pin verification. Other than this, we can perform different CRUD operations. Some modules for further testing:
For example, If we want to delete the row where id = 1, we can use the
app.provider.delete the module.
In this way, we can perform different operations on the content provider.
This is different from web SQL injection. Here we only target local databases and need vulnerable content providers to submit our query. By manipulating –the selection & –projection part, we can dump data. Let’s see that when we submit something unexpected in query, how it will react? Such as special character /, *, ‘.
After submitting “@” as a projection, we get the error with the actual query in the background. Of course, this can also be done through source code, but while doing this, we understand how the provider reacts to our inputs.
If we want to request whole stuff from notes, our backend query will be
and input for query will be “*” let’s see if it works.
Yes, it works!
Now we want tables from the whole system, so we have to look for the SQLITE_MASTER table for that, we can query as follows.
This query will select everything from sqlite_master and “–” to end the query, and the remaining part will become a comment. Let’s try if it works:
And it works. In this way, we can approach SQL injection in android. We covered pretty much content providers, from basics to exploitation. let’s see some automated scanners provided by drozer for testing.
By using the dozer, we can also scan for automatic SQL injection.
Similar to data, we can access files from the system if we have a file provider.
Path Transversal: (Automatic Scanner)
Our next component is the broadcast receiver,
Android OS broadcasts to apps when any event happens in the app or system. Broadcast Receiver helps apps in communicating with android OS and other apps.
Static Broadcast Receivers: These types are declared in the manifest file and work even if the app is closed. E.g. Battery Warnings, Alarms.
This example is for static broadcast receivers doesn’t matter whether the app is open or not when it triggers the condition the broadcast will receive.
Dynamic Broadcast Receivers: These receivers work only if the app is active or minimized. Eg. OTP Reading
Here is a simple example of WhatsApp. It would only check whether files exist or not whenever the app runs and broadcasts.
How to exploit them?
Hope you have already configured the drozer, and for demo purposes, we need InsecurebankV2 application. You will get it from here
Let’s check with drozer which is the broadcast used by the application via the following command –
we can notice here that
MyBroadCastReceiver is exported, and the permissions are
null so any third-party app can start the broadcast, but that’s not enough. We need to check if any sensitive action can be performed. for that, we can just go through the source code of the particular class. Let’s check M
yBroadCastReceiver.class and see if we can do anything with it.
In the example above, we can observe two strings that can be used to pass extra data to the broadcast
To send extra strings to that particular broadcast, we can use
--extra string string-name value
then effectively, our command will be
As a broadcast trigger, we can see that we are getting notifications on the device, and it is almost ready to send the message.
In this way, we can check whether the broadcasts are vulnerable. It may vary case by case.
To secure Android components, two methods could be used –
There should be no need to export components unless it is necessary to do so. Otherwise, set android:exported=”false”
If the export is necessary, make sure the components are protected by configuring permissions
When You Need Us
Android apps are utilized nowadays for various purposes, including mobile banking, shopping, sharing personal information, social networking, and entertainment. Unfortunately, android devices are vulnerable to threats from multiple hacking techniques, including malware, code injection, buffer overflow, and reverse engineering. Security should always come first, no matter how big or small your business is. Connect with us for penetration testing to keep your apps safe and secure.
Find more about us here.