This chapter, Android Rooting, gives an introduction to the techniques typically used to root Android devices. We will begin with the basics of rooting and its pros and cons. Then, we shall move on to topics such as various Android partition layouts, boot loaders, boot loader unlocking techniques, and so on. This chapter acts as a guide for those who want to root their devices and want to know the ins and outs of rooting concepts before they proceed.
The following are some of the major topics that we will discuss in this chapter:
Android is built on top of Linux Kernel. In Unix based machines such as Linux, we see two types of user accounts – normal user accounts and root accounts. Normal user accounts usually have low privileges and they need permission from root to perform privileged operations such as installing tools, making changes to the Operating System, and so on. Whereas root accounts have all the privileges such as applying updates, installing software tools, ability to run any command, and so on. Essentially, this account has granular control over the whole system. This privilege separation model is one of the core Linux security features.
As mentioned earlier, Android is an operating system built on top of Linux Kernel. So many features that we see in traditional Linux systems will also be present in Android devices. Privilege separation is one among them. When you buy a brand new Android device, technically you are not the owner of your device, meaning you will have limited control over the device in terms of performing privileged operations that are possible for root accounts. So gaining full control over the device by gaining root access is termed as rooting.
One simple way to check if you have root access on the device is by running the su
command on an adb shell. su
is Unix's way of executing commands with the privileges of another user:
shell@android:/ $ su /system/bin/sh: su: not found 127|shell@android:/ $
As we can see in the preceding excerpt, we have no root access on the device.
On a rooted device, we usually have UID value 0
with a root shell having #
rather than $
representing root account. This looks as shown following:
shell@android:/ $ su root@android:/ # id uid=0(root) gid=0(root) root@android:/ #
As mentioned earlier, we do not have complete control over the Android devices due to the limitations imposed by hardware manufacturers and carriers. So, rooting a device gives us additional privileges to overcome these limitations.
However, the goal of rooting a device could vary from person to person. For example, some people root their devices to get more beautiful themes, a better look and feel, and so on by installing custom ROMs. Some may want to install additional apps known as root apps that cannot be installed without root access. Similarly, others may have some other reasons. In our case, we are going to root our device for penetration testing purposes as a rooted device gives us complete control over the file system and additional apps such as Cydia Substrate which can be installed to audit the apps.
Whatever the reason may be, rooting has its own advantages and disadvantages. Some of them are described following.
This section describes some of the advantages of rooting an Android device.
By default we cannot fully access the device as a normal user. After rooting an Android device we get full control over the device. Let's see the following example. The following excerpt shows that a normal user without root access cannot see the listing of installed app packages inside the /data/data
directory:
shell@android:/ $ ls /data/data opendir failed, Permission denied 1|shell@android:/ $
As a root user, we can explore the complete file system, modify the system files, and so on.
The following excerpt shows that a root user can see the listing of installed app packages inside the /data/data
directory:
shell@android:/ $ su root@android:/ # ls /data/data com.android.backupconfirm com.android.bluetooth com.android.browser com.android.calculator2 com.android.calendar com.android.certinstaller com.android.chrome com.android.defcontainer com.android.email com.android.exchange
This section describes various disadvantages of rooting an Android device and why it is dangerous for end users to root their devices.
Once a device is rooted, it compromises the security of your device.
By default each application runs inside its own sandbox with a separate user ID assigned to it. This user id segregation ensures that one application with its UID running on the device cannot access the resources or data of other apps with different UID running on the same device. On a rooted device, a malicious application with root access will not have this limitation and so it can read data from any other application running on the device. A few other examples would be bypassing lock screens, extracting all the data such as SMS, call logs, contacts, and other app specific data from a stolen/lost device.
Let's see a practical example of how it looks like. content://sms/draft
is a content provider URI in Android to access the draft SMS from the device. For any application on your device to access the data through this URI, it requires READ_SMS
permission from the user. When an application tries to access this without appropriate permission, it results in an exception.
Open up a shell over USB using adb and type in the following command with a limited user shell (without root access):
shell@android:/ $ content query --uri content://sms/draft Error while accessing provider:sms java.lang.SecurityException: Permission Denial: opening provider com.android.providers.telephony.SemcSmsProvider from (null) (pid=4956, uid=2000) requires android.permission.READ_SMS or android.permission.WRITE_SMS at android.os.Parcel.readException(Parcel.java:1425) at android.os.Parcel.readException(Parcel.java:1379) at android.app.ActivityManagerProxy.getContentProviderExternal(ActivityManagerNative.java:2373) at com.android.commands.content.Content$Command.execute(Content.java:313) at com.android.commands.content.Content.main(Content.java:444) at com.android.internal.os.RuntimeInit.nativeFinishInit(Native Method) at com.android.internal.os.RuntimeInit.main(RuntimeInit.java:293) at dalvik.system.NativeStart.main(Native Method) shell@android:/ $
As we can see in the preceding excerpt, it is throwing an exception saying permission denied.
Now, let's see how it looks like when we query the same URI using a root shell:
shell@android:/ $ su root@android:/ # content query --uri content://sms/draft Row: 0 _id=1, thread_id=1, address=, person=NULL, date=-1141447516, date_sent=0, protocol=NULL, read=1, status=-1, type=3, reply_path_present=NULL, subject=NULL, body=Android Rooting Test, service_center=NULL, locked=0, sub_id=0, error_code=0, seen=0, semc_message_priority=NULL, parent_id=NULL, delivery_status=NULL, star_status=NULL, delivery_date=0 root@android:/ #
As we can see in the preceding output, we do not require seeking any permission from the user to be able to read SMS with root privileges and thus compromising the data of the application sitting on the device. It is quite common to see root apps executing shell commands on devices to steal sensitive files such as mmssms.db
.