Why attackers can't resist Android apps

Why attackers can’t resist Android applications

In their quest for new attack surfaces, threat actors find easy targets among the ~2.7 million Android applications, ad infinitum.

What makes Android applications irresistible targets? 

  1. The ease with which an attacker can acquire the entire source code of an Android application.
  2. The source codes often contain API keys, secret tokens, sensitive credentials, and endpoints, which developers forget to remove after staging.

Developers often lack awareness about attack vectors on a mobile app. Owing to a false sense of security, provided by the sandboxed and permission-oriented operating systems. However, mobile apps have the same attack vectors as web apps, albeit with different exploitation techniques. 

When an attacker meets an Android app

After getting their hands on an Android app’s source code, attackers first decompile it, analyse it for weaknesses, and then exploit it.

Decompiling the source code

The attacker first extracts files and folders from the apk file of an Android app, which is similar to unzipping a zip file. However, the files are compiled. To read the source code, the files are decompiled using:     

  • Apktool: To read the AndroidManifest.xml file. It also disassembles to small code and allows to repack the apk after modifications.
  • Dex2jar: To convert the Dex file into a Jar file.
  • Jadx/Jd-gui: To read the code in GUI format.

Analysing the source code

The attacker analyses the source code using 2 methods: 

  • Static Analysis
  • Dynamic Analysis

Static Analysis

In this approach, the attacker examines the source code for secret tokens, API keys, credentials, and secret paths. They also understand the source code, check for activities, content providers, broadcast receivers, vulnerable permissions, local storage, sensitive files, etc.

Here are some examples of what attackers look for during static analysis:

Sensitive Information 

As we can see, the strings.xml file below exposes sensitive information such as API keys, bucket name, Firebase database URL, etc.

strings.xml file exposes sensitive information about the Android app
strings.xml file exposes sensitive information
Working Credentials

Often, usernames and passwords are hidden in the source code, because developers forget to remove them. 

Exposed passwords make the Android app vulnerable
Exposed passwords
Content Providers

Content Providers allow applications to access data from other applications. And in order to access a Content Provider, you need its URI. 

Attackers check if the Content Provider attribute is ‘exported=true,’ which implies that it can be accessed by third-party applications.

The Content Provider attribute is ‘exported=true'
The Content Provider attribute is ‘exported=true’
Content Provider URI
Content Provider URI

Below we are accessing the content provider declared by the vulnerable application through the tool i.e. content, which acts as a third-party application.

Using the Content Provider to access data without a PIN
Using the Content Provider to access data without a PIN
Activities

An activity implements a screen/window in an app. So, an app usually invokes only an activity i.e. a particular screen in another app, and not the app as a whole.  

Attackers check for weaknesses in activities in the AndroindManifest.xml file. Where, if an activity is marked as ‘exported=true,’ a third-party app can initiate that activity.

Activity marked as 'exported=true'
Activity marked as ‘exported=true’

For example, the screen below has a functionality to submit a password. And only on submitting the password, we can see the dashboard. 

Password required to view dashboard
Password required to view dashboard

However, if the activity responsible for showing the dashboard is marked ‘exported= true,’ an attacker can use an Activity Manager (AM) tool to run it. 

Using an Activity Manager to run the activity
Using an Activity Manager to run the activity

And by doing this the attacker can access the dashboard without a password. 

Accessing the dashboard without a password
Accessing the dashboard without a password
Broadcast Receivers

Broadcast receivers listen for system-generated or custom generated events from other applications or from the system itself. 

Attackers check for weaknesses in Broadcast Receivers in the AndroindManifest.xml file. And if the intent-filter tag is declared ‘exported=true,’ a third-party application can easily access it. To prevent this, we need to explicitly declare ‘exported=false.’

Intent-filter tag declared ‘exported=true’
Intent-filter tag declared ‘exported=true’

After checking for the parameters that the receiver can accept, attackers can write a command that will trigger the receiver on behalf of the application.  

For example: The following command triggers the receiver to send a message to a phone number. 

Command to trigger the receiver
Command to trigger the receiver

Following which, the message is delivered to the phone number:

Message sent as per command
Message sent as per command

Dynamic analysis

In this approach, the attacker uses a binary toolkit such a Frida to hook to a targeted application and change its implementation. It also allows the attacker to bypass root detection and SSLs. 

Since Frida has the capability to access classes and functions of a targeted process/ application, the attacker injects their own JavaScript (JS) payload at runtime, to analyze the behavior of the code. 

Bypassing root detection

The following application has root detection. Hence, to access all the capabilities of the application, the attackers need to bypass root detection. 

A device that has root detection
A device that has root detection

First, the attacker needs to identify the function that is responsible for root detection. Which they can get from the source code:

Root detection function in the source code
Root detection function in the source code

If one of the functions i.e. ‘doesSuperuserApkExist(‘’) and doesSuExist(‘’)’ returns True, it will be identified as a Rooted Device.

So, the attacker needs to change the implementation of these two functions to False, in order to bypass the rooting. And this is where Frida comes to use. 

By injecting the following JS payload, the attacker changes the implementation of the functions responsible for root detection. 

JS payload to change the root detection function
JS payload to change the root detection function

With the help of use(), the attacker accesses the PostLogin class. Here, they mention the function i.e. ‘doesSUexist or doesSuperuserApkExist,’ that they need to hook. After which, the function will start returning False instead of True

Frida Client then sends the server this JS payload. And the server makes it a thread and sends it to the JS Engine. So, whenever the application calls this function, Frida will call the thread instead of the actual function declared in source code.

"<yoastmark

Conclusion

Given the increasing sophistication of cyber-attacks, it is important that Android apps undergo proper vulnerability assessments before publishing. Also, developers should not leave sensitive information such as API keys and credentials exposed in the source code. 

Written by :

Cyber Security Analyst, who also plays a significant role in the POC team, at CloudSEK.

Deepanjli is CloudSEK's Lead Technical Content Writer and Editor. She is a pen wielding pedant with an insatiable appetite for books, Sudoku, and epistemology. She works on any and all content at CloudSEK, which includes blogs, reports, product documentation, and everything in between.