Every application in android system is generally being sandboxed, which means applications application one can’t simply access application two and applications three. That’s actually a good feature. Imagine that another applications cloud access to your banking application data.
But how the sandboxing work in Android?
It’s easier than you think. We are in Linux system, therefore android create a new user and assign in to each application have been installed. So every application gets its own User ID. Now you can find out the Linux system simply didn’t let to User A access to User B data.
There are a file located on
/etc/permissions/platform.xml
. In this file there are some permissions which assigned to groups.Example:
<?xml version="1.0" encoding="utf-8"?>
<permissions>
<!-- The following tags are associating low-level group IDs with specific permissions -->
<permission name="android.permission.INTERNET" group gid="inet" />
<permission name="com.sec.android.permission.CAMERA" group gid="camera" />
<permission name="android.permission.READ_LOGS" group gid="log" />
<permission name="android.permission.WRITE_MEDIA_STORAGE" group gid="sdcard_rw" group gid="media_rw" />
<permission name="android.permission.ACCESS_MTP" group gid="mtp" />
<permission name="android.permission.NET_ADMIN" group gid="net_admin" />
<!-- ... -->
</permissions>
In this example, the
android.permission.INTERNET
permission is associated with the inet
group, the com.sec.android.permission.CAMERA
permission is associated with the camera
group, and so on. This file is crucial for maintaining the security of the Android system, as it ensures that only authorized applications and users can access certain system resources.If any third-party application want to access
internet
, it should join to the inet
group.Another important path is
/data/system/packages.xml
which contains information about installed applications, their granted permissions, their code path and etc.The
/data/system/packages.xml
file is an important file in the Android operating system that contains information about installed applications and their permissions. It is a well-formed XML file that lists the package names, code paths, native library paths, user IDs, and other metadata for each installed application on the device.Example:
<package codepath="/data/app/com.project.t2i-2.apk" flags="0" ft="13a837c2068" it="13a83704ea3" name="com.project.t2i" nativelibrarypath="/data/data/com.project.t2i/lib" userid="10040" ut="13a837c2ecb" version="1">
<sigs count="1">
<cert index="3" key="308201e53082014ea0030201020204506825ae300d06092a86" /> <!-- This is signing key -->
</sigs>
<perms>
<!-- List of permissions for the app -->
</perms>
</package>
This example shows a part of the
packages.xml
file for an application named com.project.t2i
. The file contains information about the application's code path, native library path, user ID, and version, as well as the permissions(with granted or not granted state) to the application. Modifying this file can have security implications, so it should be done with caution.Custom permission define here too.
Permission Flag:
0 → Normal Permission. No alert to user.
1 → Dangerous Permission. Showing pop up and asking user to grant the permission.
Custom Permissions
All the android application cloud define their own permissions which if the user grant, the other application access to feature or data on it.
<permission android:label="Allows reading user infroatmion" android:name="com.apphacking.privacy.USER_INFO" android:protectionLevel="dangerous"/>
android:label
—> This attribute is a description for users about this permission.android:name
—> Other applications should use this name to request for grant.android:protectionLevel
—> Define how much the permission cloud be dangerous if granted to the unknown applications.This custom permissions are very important because maybe the app share a critical data like PII of user or a password. Therefore we want to make sure the third-party apps have granted permission to access these data.
To understand this subject better lets using a Lab
.
First download this app:
Sieve is app which is kind of password manager. This app developed to be vulnerable.
Then we go to analysis this tool via
apktool
or JadX
. Analysis the manifest. You these custom permissions:apktool d sieve.apk
The we go to analysis manifest:
This app have a content provider which share stored passwords. To accessing this content provider third-party app needs to define this permission in their manifest and user must grant theme. For example if create a app which want to access to sieve content provider, I need to define this permission in my app:
<uses-permission ns0:name=com.mwr.example.sieve.READ_KEYS"/>
But you can’t protect user important data with custom permission unless you choose the correct protection level.
Let’s speak about permission protection level. We have four protection level:
Normal
These permission granted automatically by the system. Like internet permission. These permissions usually will now show when installing or running the app.
Dangerous
Simply means the user needs to informed about this and choose to grant or not. Just it. So it’s not a good way to defend against secrets.
Example of dangerous level permission which require runtime permission to inform user and let he/she choose to grant or not.
Signature
Its means simply all application which signed with same key can access to these data. For example WhatsApp and Instagram are both for meta. If they sign with the same key they and WhatsApp define a custom permission to access some information with same signature, just Instagram can do it.
Signature Or System
A permission that the system grants only to applications that are in a dedicated folder on the Android system image or that are signed with the same certificate as the application that declared the permission. Avoid using this option, as the
"signature"
protection level is sufficient for most needs and works regardless of where apps are installed.Getting installed apps user ID
To getting apps packages ID you should use this command:
adb shell pm list packages -U
The user ID of applications start from 10,000 as defined in
android_filesystem_config.h
file. This file contains some important configs like default user Ids and group Ids. As an example user ID of ADB defined here as hardcoded.The android_filesystem_config
.h
file is a header file that contains definitions for the Android filesystem configuration. It is used by the Android operating system to define the permissions and access control for files and directories in the Android filesystem.The
android_filesystem_config.h
file contains a set of macros that define the user and group IDs, permissions, and capabilities for specific system processes and files. These definitions are used by the Android system to determine the access control for various system resources.Some examples of the definitions in this file include:
AID_ROOT
: The user ID for the root user.AID_SYSTEM
: The user ID for the system user.AID_SHELL
: The user ID for the shell user.AID_RADIO
: The user ID for the radio user.AID_WIFI
: The user ID for the Wi-Fi user.CAP_NET_ADMIN
: The capability to perform network administration tasks.Overall, the
android_filesystem_config.h
file plays an important role in defining the security and access control policies for the Android operating systemFirst app user mean the first application which is installed by user have user ID of 10000. The other should be grater than this.
How To Get Runtime Permission
Here's an example code snippet that shows how to request for camera permission in Android using Kotlin:
import android.Manifest
import android.content.pm.PackageManager
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
class MainActivity : AppCompatActivity() {
private val MY_PERMISSIONS_REQUEST_CAMERA = 1
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
!= PackageManager.PERMISSION_GRANTED) {
// Permission is not granted, request it
ActivityCompat.requestPermissions(this,
arrayOf(Manifest.permission.CAMERA),
MY_PERMISSIONS_REQUEST_CAMERA)
} else {
// Permission is already granted
// You can start using the camera here
}
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>,
grantResults: IntArray) {
when (requestCode) {
MY_PERMISSIONS_REQUEST_CAMERA -> {
// If request is cancelled, the result arrays are empty.
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permission was granted, start using the camera
} else {
// permission denied, disable the functionality that depends on this permission.
}
return
}
}
}
}