Understanding app sandboxing

In all our previous sections, we have discussed how apps are built and run in detail. Once the app is installed on the device, how does it look like on the file system? What are the security controls enforced by Google to make sure that our app's data is safe from other applications running on the device? This section will discuss all these concepts in detail.

Android is built on top of Linux Kernel and the user separation model of Linux is also applicable to Linux but slightly different from traditional Linux. First let's see how UID is assigned to processes running on traditional Linux machines.

I have logged into my Kali Linux machine as user root and running two processes:

UID per app

As you can notice, we are able to see both the processes under the same User ID.

Now, it's not true in the case of Android app. Every single app installed on your device will have a separate User ID (UID). This ensures that each application and its resources are being sand-boxed and will not be accessible to any other application.

The following excerpt shows how each application is given a separate UID:

C:\>adb shell ps |find "u0"

u0_a14    1366  968   642012 68560 sys_epoll_ b73ba1b5 S com.android.systemui
u0_a33    1494  968   606072 40104 sys_epoll_ b73ba1b5 S com.android.inputmethod
.latin
u0_a7     1518  968   721168 61816 sys_epoll_ b73ba1b5 S com.google.android.gms.
persistent
u0_a2     1666  968   601712 39908 sys_epoll_ b73ba1b5 S android.process.acore
u0_a5     1714  968   599604 37284 sys_epoll_ b73ba1b5 S android.process.media
u0_a7     1731  968   723464 67068 sys_epoll_ b73ba1b5 S com.google.process.gapps
u0_a7     1814  968   847820 70992 sys_epoll_ b73ba1b5 S com.google.android.gms
u0_a37    1843  968   664656 52688 sys_epoll_ b73ba1b5 S com.google.android.apps
.maps
u0_a7     1876  968   696996 40352 sys_epoll_ b73ba1b5 S com.google.android.gms.
wearable
u0_a24    1962  968   600340 33848 sys_epoll_ b73ba1b5 S com.android.deskclock
u0_a46    1976  968   594520 28616 sys_epoll_ b73ba1b5 S com.android.quicksearchbox
u0_a20    2011  968   602900 32724 sys_epoll_ b73ba1b5 S com.android.calendar
u0_a1     2034  968   596712 33300 sys_epoll_ b73ba1b5 S com.android.providers.calendar
u0_a4     2098  968   599872 29700 sys_epoll_ b73ba1b5 S com.android.dialer
u0_a9     2152  968   593236 27876 sys_epoll_ b73ba1b5 S com.android.managedprovisioning
u0_a28    2223  968   610040 37504 sys_epoll_ b73ba1b5 S com.android.email
u0_a7     2242  968   709932 55596 sys_epoll_ b73ba1b5 S com.google.android.gms.unstable
u0_a30    2265  968   601140 30540 sys_epoll_ b73ba1b5 S com.android.exchange
u0_a43    2289  968   620792 52824 sys_epoll_ b73ba1b5 S com.google.android.apps
.messaging
u0_a8     2441  968   621016 50200 sys_epoll_ b73ba1b5 S com.android.launcher3
C:\>

If you notice the first column of the preceding output, each installed app runs as a different user whose names start with u0_xx. For example, email application is the user u0_a28. Similarly, we can observe the user names of other apps.

Each of these users is actually mapped to their respective UIDs starting with 10000. For example, User u0_a28 is mapped with UID 10028. This can be verified on a rooted device by exploring the file packages.xml which is located under the /data/system/ directory.

As shown in the excerpt below, this file is owned by system:

To get a better understanding of this, let's have a look at some of the apps and their UID mapping at low level. I installed the heartrate application which has the package name si.modula.android.instantheartrate.

Start the application and run the ps command and observe the first column of the app process:

As we can see in the preceding excerpt, this app has got u0_a132 as its user. We can check its low level UID mapping using the packages.xml file as shown following:

<package name="si.modula.android.instantheartrate" codePath="/data/app/si.modula.android.instantheartrate-1.apk" nativeLibraryPath="/data/data/si.modula.android.instantheartrate/lib" flags="0" ft="151013a1f08" it="151013a2db1" ut="151013a2db1" version="2700" userId="10132">
<sigs count="1">
<cert index="10" key="308202153082017ea00302010202044bedb53a300d06092a864886f70d0101050500304f310b300906035504061302534931123010060355040713094c6a75626c6a616e6131163014060355040a130d4d6f64756c6120642e6f2e6f2e311430120603550403130b5065746572204b75686172301e170d3130303531343230343032365a170d3335303530383230343032365a304f310b300906035504061302534931123010060355040713094c6a75626c6a616e6131163014060355040a130d4d6f64756c6120642e6f2e6f2e311430120603550403130b5065746572204b7568617230819f300d06092a864886f70d010101050003818d003081890281810085bc0e5459c5d09bf94bddf5f599b3328d53fbdac876b7cf17288a44d9f8dfcf51d004c7dec353872940f101d83a53b1c050990a863db402249fe57349a2c1ba2ef49a11640755808e8b78593d81ab859aa3614eff02d4d38d2ea042101a8eccc166cd187d66be2075bf89d993c6e94080d1cb47d410b6f42931bc39fa4674f70203010001300d06092a864886f70d01010505000381810008a7be43861ebf10afc8918da2b9b63f5477a6ec4bcea8ab8b6b1d97bae4ee71969d692a3112f269b7ce2834984f6e30296bdc1be8beb1b5c369158240da1a915a324b6d69cea650e6754d95f3334fb9fab4e6c1715668560a3cf7faf159322a3b578e70579652b9b3f91a8e419d06e7e58bb16e4a2a77b6030c4b7a064a251c" />
</sigs>
<perms>
<item name="android.permission.CAMERA" />
<item name="android.permission.ACCESS_NETWORK_STATE" />
<item name="android.permission.FLASHLIGHT" />
<item name="android.permission.INTERNET" />
</perms>
</package>

If you notice the field userId="10132", it makes it clear that the app with the user u0_a132 is mapped to the userid 10132.

Let's also check one such preinstalled app. The following app com.sonyericsson.notes comes preinstalled with Sony devices. The ps command shows that it is assigned with u0_a77:

Now, let's explore the packages.xml file:

As you can see, it has got the userId 10077.

Each application has its own entry inside the /data/data/ directory for storing its data. As shown in the previous section, each app has specific ownership of it.

The following excerpt shows how each app's data is isolated in a separate sandboxed environment under the /data/data/ directory. To observe this, we need a rooted device or emulator as the /data/data/ directory is not accessible to limited users:

The following excerpt is the output taken from the ls –l command inside the /data/data/ directory:

drwxr-x--x u0_a2    u0_a2             1981-07-11 12:36 com.android.backupconfirm
drwxr-x--x u0_a3    u0_a3             1981-07-11 12:36 com.android.bluetooth
drwxr-x--x u0_a5    u0_a5             2015-11-13 15:42 com.android.browser
drwxr-x--x u0_a6    u0_a6             2015-10-28 13:27 com.android.calculator2
drwxr-x--x u0_a72   u0_a72            1981-07-11 12:39 com.android.calendar
drwxr-x--x u0_a9    u0_a9             2015-11-14 02:14 com.android.certinstaller
drwxr-x--x u0_a11   u0_a11            2015-11-13 15:38 com.android.chrome
drwxr-x--x u0_a17   u0_a17            2015-10-29 04:33 com.android.defcontainer
drwxr-x--x u0_a75   u0_a75            1981-07-11 12:39 com.android.email
drwxr-x--x u0_a24   u0_a24            1981-07-11 12:38 com.android.exchange
drwxr-x--x u0_a31   u0_a31            1981-07-11 12:36 com.android.galaxy4
drwxr-x--x u0_a40   u0_a40            1981-07-11 12:36 com.android.htmlviewer
drwxr-x--x u0_a47   u0_a47            1981-07-11 12:36 com.android.magicsmoke
drwxr-x--x u0_a49   u0_a49            1981-07-11 12:39 com.android.musicfx
drwxr-x--x u0_a106  u0_a106           1981-07-11 12:36 com.android.musicvis
drwxr-x--x u0_a50   u0_a50            1981-07-11 12:36 com.android.noisefield
drwxr-x--x u0_a57   u0_a57            2015-10-31 03:40 com.android.packageinstaller
drwxr-x--x u0_a59   u0_a59            1981-07-11 12:36 com.android.phasebeam
drwxr-x--x radio    radio             1981-07-11 12:39 com.android.phone
drwxr-x--x u0_a63   u0_a63            1981-07-11 12:36 com.android.protips
drwxr-x--x u0_a1    u0_a1             1981-07-11 12:36 com.android.providers.applications
drwxr-x--x u0_a7    u0_a7             1981-07-11 12:38 com.android.providers.calendar
drwxr-x--x u0_a1    u0_a1             1981-07-11 12:39 com.android.providers.contacts
drwxr-x--x u0_a37   u0_a37            1981-07-11 12:37 com.sonyericsson.music.youtubeplugin
drwxr-x--x u0_a77   u0_a77            2015-10-28 13:22 com.sonyericsson.notes
drwxr-x--x u0_a125  u0_a125           1981-07-11 12:37 com.sonyericsson.orangetheme
drwxr-x--x u0_a78   u0_a78            1981-07-11 12:36 com.sonyericsson.photoeditor
drwxr-x--x u0_a126  u0_a126           1981-07-11 12:37 com.sonyericsson.pinktheme

If you notice the file permissions in the preceding output, each application's directory is owned by itself and they are not readable/writeable by other users.

Google says, "Like all security features, the application sandbox is not unbreakable. However, to break out of the Application Sandbox in a properly configured device, one must compromise the security of the Linux kernel".

This is where we can comfortably discuss Android rooting which enables someone to have root privileges to do most of the things they want to do on the android system.

In Linux (and UNIX) based machines, 'root' is the supreme user level with the highest privileges to perform any task. By default, only the Linux kernel and a small number of core utilities run as 'root' on android. But if you root your device, the root user level is available to all apps running on the device. Now any user or app with root permission can modify any other part of the Android OS including the kernel, and other apps as well as the application data by breaking out of the sandboxed environment.

Android rooting concepts have been discussed in detail in Chapter 2, Android Rooting.