Book Image

Learning Android Forensics - Second Edition

By : Oleg Skulkin, Donnie Tindall, Rohit Tamma
Book Image

Learning Android Forensics - Second Edition

By: Oleg Skulkin, Donnie Tindall, Rohit Tamma

Overview of this book

Many forensic examiners rely on commercial, push-button tools to retrieve and analyze data, even though there is no tool that does either of these jobs perfectly. Learning Android Forensics will introduce you to the most up-to-date Android platform and its architecture, and provide a high-level overview of what Android forensics entails. You will understand how data is stored on Android devices and how to set up a digital forensic examination environment. As you make your way through the chapters, you will work through various physical and logical techniques to extract data from devices in order to obtain forensic evidence. You will also learn how to recover deleted data and forensically analyze application data with the help of various open source and commercial tools. In the concluding chapters, you will explore malware analysis so that you’ll be able to investigate cybersecurity incidents involving Android malware. By the end of this book, you will have a complete understanding of the Android forensic process, you will have explored open source and commercial forensic tools, and will have basic skills of Android malware identification and analysis.
Table of Contents (12 chapters)

Android security

Android as a platform has certain features built into the architecture that ensure the security of users, applications, and data. Although they help in protecting the data, these security features sometimes prevent investigators from getting access to necessary data. From a forensic perspective, it is first important to understand the inherent security features so that a clear idea is established about what can be or cannot be accessed under normal circumstances. The security features and offerings that are incorporated aim to achieve three things:

  • To protect user data
  • To protect system resources
  • To make sure that one application cannot access the data of another application

The next sections provide an overview of the key security features in the Android operating system.

Security at OS level through the Linux kernel

The Android operating system is built on top of the Linux kernel. Over the past few decades, Linux has evolved as a secure operating system trusted by many corporations across the world for its security. By having the Linux kernel at the heart of its platform, Android tries to ensure security at the OS level. Also, Android has built a lot of specific code into Linux to include certain features related to the mobile environment. With each Android release the kernel version also has changed. The following table shows Android versions and the corresponding Linux kernel version:

Android version

Linux kernel version

1.0

2.6.25

1.5

2.6.27

1.6

2.6.29

2.2

2.6.32

2.3

2.6.35

3.0

2.6.36

4.0

3.0.1

4.1

3.0.31

4.2

3.4.0

4.3

3.4.39

4.4

3.8

5.0

3.16.1

6.0

3.18.10

7.0

4.4.1

7.1

4.4.1

8.0

4.10

9.0

4.4.107, 4.9.84, and 4.14.42


The Linux kernel provides Android with the following key security features:

  • A user-based permissions model
  • Process isolation
  • Extensible mechanism for secure IPC

Permission model

Android implements a permission model for individual apps. Applications must declare which permissions (in the manifest file) they require. In older versions of Android, the user was presented with a full list of permissions requested by the application prior to installation.

Newer versions of Android prompt the user the first time each permission is required while the app is in use. This model allows a user to use an app without granting all permissions requested by the application, though functionality may be decreased.

Sample permission model in Android

Unlike a desktop environment, this provides an opportunity for the user to know in advance what resources the application is seeking access to. In other words, user permission is a must to access any kind of critical resource on the device. By looking at the requested permission, the user is more aware of the risks involved in installing the application.

As mentioned before, developers have to identify the permissions in a file named AndroidManifest.xml. For example, if the application needs to access the internet, the permission INTERNET is specified using the following code in the AndroidManifest.xml file:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.rohit">

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

</manifest>

Android permissions are categorized into four levels:

Permission type

Description

Normal

This is the default value. These are low risk permissions and do not pose a risk to other applications, system, or user. This permission is automatically granted to the user without asking for user approval during installation.

Dangerous

These are the permissions that can cause harm to the system and other applications. Hence, user approval is necessary during installation.

Signature

These are automatically granted to a requesting app if that app is signed by the same certificate as the one that declared/created the permission. This level is designed to allow apps that are part of a suite, or otherwise related, to share data.

Signature/System

A permission that the system grants only to applications that are in the Android system image or that are signed with the same certificate as the application that declared the permission.

Application sandboxing

In order to isolate applications from each other, Android takes advantage of the Linux user-based protection model. In Linux systems, each user is assigned a unique User ID (UID) and users are segregated so that one user does not have access to the data of another. All resources under a particular user are run with the same privileges. Similarly, each Android application is assigned a UID and is run as a separate process. What this means is that, even if an installed application tries to do something malicious, it can do it only within its context and with the permissions it has. This application sandboxing is done at the kernel level. The security between applications and the system at the process level is ensured through standard Linux facilities, such as user and group IDs that are assigned to applications. For example, the following screenshot referenced from http://www.ibm.com/developerworks/library/x-androidsecurity/ shows the sandbox mechanism:

By default, applications can't read or access the data of other applications and have limited access to the operating system. If Application A tries to read Application B's data, for example, the operating system protects against this because Application A does not have the appropriate user privileges. Since the application sandbox mechanism is implemented at the kernel level, it applies to both native applications and OS applications. Hence, the operating system libraries, application framework, application runtime, and all applications run within the Application Sandbox. Bypassing this sandbox mechanism would require compromising the security of the Linux kernel.

SELinux in Android

Starting with Android 4.3, Security-Enhanced Linux (SELinux) is supported by the Android security model. Android security is based on discretionary access control, which means applications can ask for permissions, and users can grant or deny those permissions. Hence, malware can create havoc on the phones by gaining permissions. Android uses SELinux to enforce mandatory access control that ensures applications work in isolated environments; this includes applications running as root or superuser. Hence, even if a user installs a malicious app, the malware cannot easily access the OS and corrupt the device. SELinux is used to enforce Mandatory Access Control (MAC) over all of the processes, including the ones running with root privileges. SELinux operates on the principle of default denial. Anything that isn't explicitly allowed is denied. SELinux can operate in one of two global modes: permissive mode, in which permission denials are logged but not enforced, and enforcing mode, in which denials are both logged and enforced. As per Google's documentation, in the Android 5.0 Lollipop release, Android moves to full enforcement of SELinux. This builds upon the permissive release of 4.3 and the partial enforcement of 4.4. In short, Android is shifting from enforcement on a limited set of crucial domains (installd, netd, vold, and zygote) to everything (more than 60 domains).

Application signing

All Android apps need to be digitally signed with a certificate before they can be installed on a device. The main purpose of using certificates is to identify the author of an app. These certificates do not need to be signed by a certificate authority, and Android apps often use self-signed certificates. The app developer holds the certificate's private key. Using the same private key, the developer can provide updates to their applications and share data between applications. In debug mode, developers can sign the app with a debug certificate generated by the Android SDK tools. You can run and debug an app signed in debug mode but the app cannot be distributed. To distribute an app, the app needs to be signed with your own certificate. The key store and the private key that are used during this process need to be secured by the developer as they are essential to push updates. The following screenshot shows the key store selection option that is displayed while exporting the application:

Secure inter-process communication

As discussed in the previous sections, sandboxing of the apps is achieved by running apps in different processes with different Linux identities. System services run in separate processes and have more privileges. Hence, in order to organize data and signals between these processes, an Inter-Process Communication (IPC) framework is needed. In Android, this is achieved with the use of the Binder mechanism.

The Binder framework in Android provides the capabilities required to organize all types of communication between various processes. Android application components such as Intents and content providers are also built on top of this Binder framework. Using this framework, it is possible to perform a variety of actions such as invoking methods on remote objects as if they were local, synchronous and asynchronous method invocation, and sending file descriptors across processes. Let's suppose the application in Process A wants to use certain behavior exposed by a Service that runs in Process B. In this case, Process A is the client and Process B is the service. The communication model using Binder is shown in the following screenshot:

Binder communication model

All communications between the processes using the Binder framework occur through the Linux kernel driver, /dev/binder. The permissions to this device driver are set to world readable and writable, meaning any application may write to and read from this device driver. All communications between client and server happen through proxies on the client side and stubs on the server side. The proxies and the stubs are responsible for sending and receiving the data and the commands sent over the Binder driver.

Each service (also called a Binder service) exposed using the Binder mechanism is assigned a token. This token is a 32-bit value and is unique across all processes in the system. A client can start interacting with the service after discovering this value, which can be done with the help of Binder's context manager. Basically, the context manager acts as a name service providing the handle of a service using the name of this service. In order to get this process working, each service must be registered with the context manager. Hence, a client needs to know only the name of a service to communicate.

The name is resolved by the context manager and the client receives the token that is later used for communicating with the service. The Binder driver adds the UID and the PID value of the sender process to each transaction. As discussed earlier, each application in the system has its own UID and hence this value is used to identify the calling party. The receiver of the call may check the obtained values and decide if the transaction should be completed. Hence, the security is enforced and the Binder token acts as a security token as it is unique across all of the processes.