Understanding app sandboxing

Understanding app sandboxing

September 02, 2023 15 min read 5 views 0 discussions
Table of Contents

    In all our previous sections, we have discussed how apps are built and run in detail. Hello everyone, welcome back again. Today, in this section, we will be going to understand Android app sandboxing. This mechanism ensures the security and isolation of each application within the Android ecosystem. 

    Let's delve into the intricate layers of app sandboxing to gain a comprehensive understanding.

    Understanding User IDs per Application

    You're probably aware that Android is based on the Linux Kernel. The way users are kept separate in Linux also applies to Android but with a slight twist. Let's break it down by understanding how User IDs (UIDs) are given to processes on regular Linux systems.

    As usual, we're on a Kali Linux Virtual Machine. To examine running processes owned by a specific user, we execute the command:

    ┌──(kali㉿kali)-[~]
    └─$ ps -U kali
        PID TTY          TIME CMD
       1052 ?        00:00:00 systemd
       1053 ?        00:00:00 (sd-pam)
            --------------more------------------
     156930 ?        00:00:02 qterminal
     156933 pts/0    00:00:05 zsh
     157149 ?        00:00:03 adb
     162552 ?        00:00:00 xfconfd
     164127 ?        00:00:00 tumblerd
     164336 ?        00:00:00 qterminal
     164339 pts/1    00:00:01 zsh
     164428 pts/1    00:00:00 ps
    ┌──(kali㉿kali)-[~]
    └─$

    This presents us with a list of currently active processes associated with the user "kali."

    To filter with specific processes associated with user “kali”, run the same command with grep “specify the process name”.

    ┌──(kali㉿kali)-[~]
    └─$ ps -U kali | grep "zsh\|mousepad"
     156933 pts/0    00:00:05 zsh
     164339 pts/1    00:00:04 zsh
     164670 ?        00:00:01 mousepad
    ┌──(kali㉿kali)-[~]
    └─$

    As you can notice, we can see both processes under the same User ID. But, it's different for Android apps

    Every app on your device has its own unique User ID (UID). This makes sure that each app and its stuff are kept separate from others, like being in their own little sandbox. They can't reach each other's things.

    To verify this, open a new terminal and run the command:

    ┌──(kali㉿kali)-[~]
    └─$ adb devices
    List of devices attached
    192.168.95.118:5555     device                                                                                                                                 
    ┌──(kali㉿kali)-[~]
    └─$ adb shell ps | grep "u0"
    u0_a61        1266  1022 3796852  86464 0                   0 S com.android.inputmethod.latin
    u0_a31        1276  1022 3922980 192168 0                   0 S com.android.systemui
    u0_a51        1578  1022 3786204  72968 0                   0 S com.android.deskclock
    u0_a22        1615  1022 3900064 176616 0                   0 S com.android.launcher3
    u0_a66        1638  1022 3781820  65288 0                   0 S com.android.printspooler
    u0_a10        1674  1022 3785688  84832 0                   0 S android.process.media
    u0_a14        1723  1022 3794748  76028 0                   0 S com.android.dialer
    u0_a5         1825  1022 3779492  74156 0                   0 S com.android.providers.calendar
    u0_a9         1843  1022 3785280  67652 0                   0 S com.android.contacts
    u0_a23        1885  1022 3779068  62576 0                   0 S com.android.managedprovisioning
    u0_a30        1902  1022 3781976  64380 0                   0 S com.farmerbb.taskbar.androidx86
    u0_a20        1919  1022 3787104  77240 0                   0 S com.google.android.packageinstaller
    ┌──(kali㉿kali)-[~]
    └─$

    This will show you that each app gets a distinct UID. If you look at the first part of the output, you'll see that every installed app runs as its own user with names like u0_xx

    For instance, the dialer app goes by the user u0_a14. You'll notice similar user names for other apps.

    u0_a14        1723  1022 3794748  76028 0                   0 S com.android.dialer
    Remember, if two apps have the same developer key, it means, they can share data with each other.

    The User IDs (UIDs) assigned to users are distinct and individual. For instance, the user u0_a14 corresponds to the UID 1723. 

    To verify the correlation between users and UIDs on a rooted device, you can inspect the `packages.xml` file found in the `/data/system/` directory. 

    ┌──(kali㉿kali)-[~]
    └─$ adb shell
    x86_64:/ $ ls -l /data/system/packages.xml
    -rw-rw---- 1 system system 365653 2023-08-24 16:54 /data/system/packages.xml
    x86_64:/ $
    It's important to note that the internal configurations of Android can differ, and therefore, this approach may not always yield precise results.

    To grasp this concept better, let's take a closer look at the UID mapping for some apps. But before that, let me run a user-installed app to observe. 

    After running the app, use the ps command and check the first column of the process.

    ┌──(kali㉿kali)-[~]
    └─$ adb shell ps | grep "u0"
    u0_a61        1266  1022 3796852  86464 0                   0 S com.android.inputmethod.latin
    u0_a31        1276  1022 3923236 193012 0                   0 S com.android.systemui
    u0_a51        1578  1022 3786204  72968 0                   0 S com.android.deskclock
    u0_a22        1615  1022 3891080 170316 0                   0 S com.android.launcher3
    u0_a66        1638  1022 3781820  65288 0                   0 S com.android.printspooler
    u0_a10        1674  1022 3785688  84832 0                   0 S android.process.media
    u0_a14        1723  1022 3794748  76028 0                   0 S com.android.dialer
    u0_a5         1825  1022 3779492  74156 0                   0 S com.android.providers.calendar
    u0_a9         1843  1022 3785280  67652 0                   0 S com.android.contacts
    u0_a23        1885  1022 3779068  62576 0                   0 S com.android.managedprovisioning
    u0_a30        1902  1022 3781976  64380 0                   0 S com.farmerbb.taskbar.androidx86
    u0_a20        1919  1022 3787104  77240 0                   0 S com.google.android.packageinstaller
    u0_a73        3245  1022 3846616 152620 0                   0 S com.jetstartgames.chess
    ┌──(kali㉿kali)-[~]
    └─$ 

    In the provided example, the application resides within the user u0_a73. 

    To delve further, we can investigate the underlying User ID (UID) mapping. Open the terminal and enter the command "cat," followed by the path to the `packages.xml` file.

    x86_64:/ # cat /data/system/packages.xml

    However, the output might be overwhelming, so I'll paste it into a text editor for clarity.

    From there, search for the app by its package name. Copy and paste the package name in the search.

    <package name="com.jetstartgames.chess" codePath="/data/app/com.jetstartgames.chess-AWAN-L4GToOwbH3oP1MY5A==" nativeLibraryPath="/data/app/com.jetstartgames.chess-AWAN-L4GToOwbH3oP1MY5A==/lib" publicFlags="973651524" privateFlags="0" ft="18a1de3bd38" it="18a1de3c0cc" ut="18a1de3c0cc" version="75" userId="10073">
            <sigs count="1">
                <cert index="14" key="308202b9308202220209008f2b5f0605259e76300d06092a864886f70d01010505003081a0310b300906035504061302646d310d300b06035504081304646a646a311330110603550407130a6a6b686b73646a66686a31153013060355040a130c6f696d6e66636b6a61736466311a3018060355040b13116a6b68676b6a6863796864626173646c66311430120603550403130b6862636c7a6b64797566673124302206092a864886f70d01090116156a6b6273646b666a6268406b666a7662682e636f6d301e170d3135303632363031333431385a170d3432313131303031333431385a3081a0310b300906035504061302646d310d300b06035504081304646a646a311330110603550407130a6a6b686b73646a66686a31153013060355040a130c6f696d6e66636b6a61736466311a3018060355040b13116a6b68676b6a6863796864626173646c66311430120603550403130b6862636c7a6b64797566673124302206092a864886f70d01090116156a6b6273646b666a6268406b666a7662682e636f6d30819f300d06092a864886f70d010101050003818d0030818902818100cde847c7c90c9453063c1849ad45095b13c354672d255e7891d5b85c998f99e3b8f4613a6c007fde1b645ead98ad2ca1ee31cefa10a6944d6805204d39a3abba836fda50c79c50f2f73f1290b2f6be3402cf1134e3c3270ac15a3b6b49a3eed3eef60101b4572c0c0e3db4aa3c98e6daa00dcbcace73181cbe3bd6a7959641bd0203010001300d06092a864886f70d010105050003818100c482ea8d6575dcb49a2e98a1ea7674addb253d85698d840cb585ffe924450933058cb98ade9100c941a6c7e496f82c2ea169fa9a950eda1237e0b5411b1566a60961774f9e774e5f04b2fbc3cccc75361671a870a8ed134bf7cc6d4746319e5098ff798964a9513c5302ad4d5b16fbe5dfe4e146022e8055a92d8642f5594f99" />
            </sigs>
            <perms>
                <item name="android.permission.RECEIVE_BOOT_COMPLETED" granted="true" flags="0" />
                <item name="android.permission.INTERNET" granted="true" flags="0" />
                <item name="android.permission.ACCESS_NETWORK_STATE" granted="true" flags="0" />
                <item name="android.permission.WAKE_LOCK" granted="true" flags="0" />
            </perms>
            <proper-signing-keyset identifier="28" />
        </package>

     If you see the field userId="10073," it means that the app with the user u0_a73 is tied to the userid 10073.

    Now, let's consider a pre-installed app such as "com.android.deskclock," which comes preloaded in the Android VM under the user u0_a14. 

        <package name="com.android.deskclock" codePath="/system/app/DeskClock" nativeLibraryPath="/system/app/DeskClock/lib" publicFlags="944258629" privateFlags="0" ft="1685113a320" it="1685113a320" ut="1685113a320" version="27" userId="10051" isOrphaned="true">
            <sigs count="1">
                <cert index="2" />
            </sigs>
            <perms>
                <item name="android.permission.RECEIVE_BOOT_COMPLETED" granted="true" flags="0" />
                <item name="android.permission.DISABLE_KEYGUARD" granted="true" flags="0" />
                <item name="android.permission.VIBRATE" granted="true" flags="0" />
                <item name="android.permission.WAKE_LOCK" granted="true" flags="0" />
            </perms>
            <proper-signing-keyset identifier="3" />
        </package>

    Upon inspecting the `packages.xml` file, you will notice that it is associated with the userId 10051.

    App sandboxing

    Previously, we differentiated Sandbox on Android and Linux and then understood the UID per app on the Android app. Next, move forward to app sandboxing.

    App sandboxing is like giving each app its own private room in the /data/data/ directory to keep its stuff. As we saw before, each app has its own rightful ownership of this space.

    This setup is like separating each app's belongings into its own little box, or sandbox, within the /data/data/ directory. To see this in action, you'd need a rooted device or emulator since the /data/data/ directory isn't available to regular users.

    To take a look, first get into your device's shell using adb. Then, head over to the /data/data/ directory by typing: cd data slash data/. Once you're in, run the command ls -l.

    ┌──(kali㉿kali)-[~]
    └─$ adb shell
    x86_64:/ $ su
    x86_64:/ # cd /data/data
    x86_64:/data/data # ls -l
    total 720
    drwx------  4 system    system    4096 2020-02-25 01:04 android
    drwx------  4 u0_a1     u0_a1     4096 2020-02-27 08:10 com.android.backupconfirm
    drwx------  5 u0_a43    u0_a43    4096 2020-02-15 10:12 com.android.camera2
    drwx------  4 u0_a41    u0_a41    4096 2020-02-12 04:42 com.android.captiveportallogin
                ------------------------more---------------------------
    drwx------  4 u0_a17    u0_a17    4096 2020-02-10 11:03 com.android.emergency
    drwx------  4 u0_a13    u0_a13    4096 2020-02-18 05:56 com.android.externalstorage
    drwx------  5 u0_a56    u0_a56    4096 2020-02-06 08:17 com.android.gallery3d
    drwxr-x--x  4 u0_a58    u0_a58    4096 2020-03-05 06:43 com.android.htmlviewer
    drwx------ 10 u0_a71    u0_a71    4096 2023-08-24 16:39 heartratemonitor.heartrate.pulse.pulseapp
    drwxr-x--x  6 u0_a40    u0_a40    4096 2023-08-24 16:55 jackpal.androidterm
    drwx------  4 u0_a11    u0_a11    4096 2020-03-05 06:00 org.lineageos.eleven
    drwx------  4 system    system    4096 2020-02-11 04:30 org.zeroxlab.util.tscal
    x86_64:/data/data # 

    If you check out the file permissions, you'll see that each app's directory is owned by itself. And they're not open for reading or writing by other users. It's like each app's room is locked and only they have the key.

    Can we break out of this protective sandbox? 

    Well, according to Google, even though the app sandbox is strong, it's not completely unbeatable. If someone really wants to break out of it on a properly set-up device, they'd need to compromise the security of the Linux kernel – which is a big deal.

    Here's, where we get into Android rooting. Rooting gives someone what's like a master key for an Android system. It's similar to having the highest authority or being the ultimate boss in a game.

    In the world of computers, we call this "root" level the supreme user level. It's like being the king or queen of the system with the power to do anything. Normally, only the Android system's essential parts, like the kernel, run as this "root." But when you root your device, you're kind of opening the doors for all apps to have that same power.

    So, imagine if everyone in your town suddenly became the mayor. They could change everything, including the roads, the buildings, and even the rules. In the Android world, when apps get this power, they can tinker with the system's core parts – the kernel and other apps. They can even mess with an app's personal space, the sandbox, by breaking out of it.

    Just like in real life, having great power means great responsibility. But with great rooting comes great risk. It's a trade-off between freedom and security in the Android universe.

    This compilation of insights provides us with a profound comprehension of the internal mechanisms of Android apps. Throughout this playlist, we've focused on grasping these internal workings, which serve as a foundational step toward delving into Android security. The objective of this playlist has been to furnish you with these pivotal concepts. 

    In our forthcoming playlist, we'll explore the overarching strategies for targeting Android applications.

    If you have any questions related to this article, feel free to write them in the comments section.

    Community Q&A