Google entered the mobile phone market in a style that only multibillion-dollar companies can afford: it bought a company. In 2005, Google, Inc. purchased Android, Inc. At the time, Android was relatively unknown, despite having four very successful people as its creators. Founded by Andy Rubin, Rich Miner, Chris White, and Nick Sears in 2003, Android flew under the radar, developing an operating system for mobile phones. With a quest to develop a smarter mobile phone that was more aware of its owner’s preferences, the team behind the Android operating system toiled away in secrecy. Admitting only that they were developing software for mobile phones, the team remained quiet about the true nature of the Android operating system until the acquisition in 2005.
With the full might of Google’s resources behind it, Android development increased at a rapid pace. By the second quarter of 2011, Android had already captured nearly a 50% market share in mobile phone operating systems shipped to end users. The four founders stayed on after the acquisition, with Rubin taking the lead as Senior Vice President of Mobile. The official launch of version 1.0 of Android took place on September 23, 2008, and the first device to run it was the HTC Dream (see Figure 1-1).
Figure 1-1. An HTC Dream (Courtesy Michael Oryl)
One of the unique features of the Android operating system that has allowed it to grow rapidly has been that the binaries and source code are released as open source software. You can download the entire source code of the Android operating system, and it takes up approximately 2.6 GB of disk space. In theory, this allows anyone to design and build a phone that runs Android. The idea of keeping the software open source was followed until version 3.0. Versions of Android including and higher than 3.0 are still closed source. In an interview given to Bloomberg Businessweek, Rubin said that the version 3.x code base took many shortcuts to ensure it was released to market quickly and worked with very specific hardware. If other hardware vendors adopted this version of Android, then the chances for a negative user experience would be a possibility, and Google wished to avoid this.1
Components of the Android Architecture
The Android architecture is divided into the following four main components (see Figure 1-2):
Figure 1-2. The Android architecture
Android runs on top of a Linux 2.6 kernel. The kernel is the first layer of software that interacts with the device hardware. Similar to a desktop computer running Linux, the Android kernel will take care of power and memory management, device drivers, process management, networking, and security. The Android kernel is available at http://android.git.kernel.org/.
Modifying and building a new kernel is not something you will want to consider as an application developer. Generally, only hardware or device manufacturers will want to modify the kernel to ensure that the operating system works with their particular type of hardware.
The libraries component also shares its space with the runtime component. The libraries component acts as a translation layer between the kernel and the application framework. The libraries are written in C/C++ but are exposed to developers through a Java API. Developers can use the Java application framework to access the underlying core C/C++ libraries. Some of the core libraries include the following:
The runtime component consists of the Dalvik virtual machine that will interact with and run applications. The virtual machine is an important part of the Android operating system and executes system and third-party applications.
Dan Bornstein originally wrote the Dalvik virtual machine. He named it after a small fishing village in Iceland where he believed one of his ancestors once originated. The Dalvik VM was written primarily to allow application execution on devices with very limited resources. Typically, mobile phones will fall into this category because they are limited by processing power, the amount of memory available, and a short battery life.
What is a Virtual Machine?
A virtual machine is an isolated, guest operating system running within another host operating system. A virtual machine will execute applications as if they were running on a physical machine. One of the main advantages of a virtual machine is portability. Regardless of the underlying hardware, the code that you write will work on the VM. To you as a developer, this means that you write your code only once and can execute it on any hardware platform that runs a compatible VM.
The Dalvik VM executes .dex files. A .dex file is made by taking the compiled Java .class or .jar files and consolidating all the constants and data within each .class file into a shared constant pool (see Figure 1-3). The dx tool, included in the Android SDK, performs this conversion. After conversion, .dex files have a significantly smaller file size, as shown in Table 1-1.
Figure 1-3. Conversion of a .jar file to a .dex file
Table 1-1. A File Size Comparison (in Bytes) of .jar and .dex Files
Application | Uncompressed .jar | Compressed .jar | Uncompressed .dex |
---|---|---|---|
Common system libraries | 21445320 = 100% | 10662048 = 50% | 10311972 = 48% |
Web browser app | 470312 = 100% | 232065 = 49% | 209248 = 44% |
Alarm clock app | 119200 = 100% | 61658 = 52% | 53020 = 44% |
The application framework is one of the building blocks for the final system or end-user applications. The framework provides a suite of services or systems that a developer will find useful when writing applications. Commonly referred to as the API (application programming interface) component, this framework will provide a developer with access to user interface components such as buttons and text boxes, common content providers so that apps may share data between them, a notification manager so that device owners can be alerted of events, and an activity manager for managing the lifecycle of applications.
As a developer, you will write code and use the APIs in the Java programming language. Listing 1-1, taken from Google’s sample API demos ( http://developer.android.com/resources/samples/ApiDemos/index.html ), demonstrates how to use the application framework to play a video file. The import statements in bold allow access to the core C/C++ libraries through a Java API.
Listing 1-1. A Video Player Demo (Courtesy Google, Inc.)
/*
* Copyright (C) 2009 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.android.apis.media;
import com.example.android.apis.R;
import android.app.Activity;
import android.os.Bundle;
import android.widget.MediaController;
import android.widget.Toast;
import android.widget.VideoView;
public class VideoViewDemo extends Activity {
/**
* TODO: Set the path variable to a streaming video URL or a local media
* file path.
*/
private String path = "";
private VideoView mVideoView;
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.videoview);
mVideoView = (VideoView) findViewById(R.id.surface_view);
if (path == "") {
// Tell the user to provide a media file URL/path.
Toast.makeText(
VideoViewDemo.this,
"Please edit VideoViewDemo Activity, and set path"
+ " variable to your media file URL/path",
Toast.LENGTH_LONG).show();
} else {
/*
* Alternatively,for streaming media you can use
* mVideoView.setVideoURI(Uri.parse(URLstring));
*/
mVideoView.setVideoPath(path);
mVideoView.setMediaController(new MediaController(this));
mVideoView.requestFocus();
}
}
}
The application component of the Android operating system is the closest to the end user. This is where the Contacts, Phone, Messaging, and Angry Birds apps live. As a developer, your finished product will execute in this space by using the API libraries and the Dalvik VM. In this book, we will extensively look at this component of the Android operating system.
Even though every component of the Android operating system can be modified, you will only have direct control over your own application’s security. This does not, however, give you free rein to ignore what happens if the device is compromised with a kernel or VM exploit. Ensuring your application does not fall victim to an attack because of an unrelated exploit is also your responsibility.
What This Book Is About
Now that you’ve got an overall understanding of the Android architecture, let’s turn to what you will not learn in this book. First, you are not going to learn how to develop Android apps from scratch in this book. You will see many examples and source code listings; and while I will explain each section of code, you might have additional questions that you might not find answered in this book. You are required to have a certain degree of experience and skill at writing Java applications for the Android platform. I also assume that you have already setup your Android development environment using the Eclipse IDE. In this book, I will focus on how you can develop more secure applications for the Android operating system.
Android has had its fair share of security setbacks and a burgeoning list of malware that is worth examining and learning from. Armed with where to look and how to tackle security aspects of developing for Android will not necessarily make you a better coder, but it will start you on your way to becoming more responsible with your end users’ privacy and security.
I’ve tried to write this book in a manner that will help you understand the concepts of security in relation to the applications you develop. In most cases, the best way I find I can achieve this is by teaching through example. Therefore, you will usually find me asking you to write and execute source code listings first. I will then follow up with an explanation of the specific concept that we are covering. With this in mind, let’s take a look at some of the security controls available on the Android operating system.
Security
Security isn’t a dirty word, Blackadder!
Securityis a vast subject and is applicable to many areas depending on what context it is taken in. I wrote this book to cover a small component of a small component of security. It is written to give you a good understanding of Android application security. However, what does that really mean? What are we trying to secure? Who will benefit from this? Why is it important? Let’s try to answer those questions and possibly come up with a few new ones.
First, let’s identify who you really are. Are you a developer? Maybe you’re a security practitioner conducting research. Alternatively, maybe you’re an end user interested in safeguarding yourself from an attack. I’d like to think that I fit into each of these categories. No doubt, you will fit into one or more of them. The vast majority, however, will fit into one category: an end user who wants to use the features of a well-written application in a manner that does not compromise her privacy and security. If you’re a developer, and I’m guessing you are if you’ve picked this book up, this is your target audience: the end user. You write applications to distribute to your users. You may choose to sell them or give them away for free. Either way, you are writing applications that will end up installed on someone else’s device, possibly thousands of miles away.
Your application should strive to provide the best functionality possible while taking care to protect your users’ data. This means thinking about security before you begin development.
Your user might not always know about the security practices you employ “under the hood” of your application, but one breach in your application is all it will take to ensure that all his Twitter and Facebook followers find out. Planning and thinking about security prior to the development phase of your application can save you the embarrassment of bad reviews and the loss of paying customers. The end user is almost never quick to forgive or forget.
As we go along, you will learn principles and techniques to identify sensitive user data and create a plan to protect this data. The goal is to eliminate or vastly reduce any unintentional harm your application could cause. So, what are you really protecting the end user from?
Mobile device users face some unique risks when compared with desktop computer users. Aside from the higher possibility of losing or having their device stolen, mobile device users risk losing sensitive data or having their privacy compromised. Why would this be different from desktop users? First, the quality of data stored on a user’s mobile device tends to be more personal. Apart from e-mail, there are instant messages, SMS/MMS, contacts, photos, and voicemail. “So what?” you say. “Some of these things exist on a desktop computer.” True, but consider this: The data on your mobile device is most likely going to be of higher value than that on your desktop because you carry it around with you all the time. It is a converged platform of both your computer and mobile phone that contains a richer collection of personal data. Because the level of user interaction is higher on the smartphone, the data is always newer than on your desktop computer. Even if you have configured real-time sync to a remote location, that still only protects you from a loss of data and not a loss of privacy.
Consider also that the format of data stored on mobile devices is fixed. Every phone will have SMS/MMS, contacts, and voicemail. Phones that are more powerful will have photos, videos, GPS locations, and e-mail, but all of it is common regardless of the operating system. Now consider how important all of this information is to an end user. To a user who has no backups, losing data of this nature can be unthinkable. Losing important phone numbers, precious moments of her daughter’s first steps caught on video, or important SMS messages can be catastrophic to the everyday phone user.
What about the user who combines both business and personal activities on his phone? What would you do if someone copied an entire file of passwords for your office server farm from your phone? Or if an e-mail containing trade secrets and confidential pricing for proposals leaked out onto the Internet? What if you lost the address of your child’s school? Consider a stalker gaining access to this information and more, such as your home address and phone number.
It is clear when you think about it that the data stored on the phone is, in most cases, far more valuable than that of the device itself. The most dangerous type of attack is the one that takes place silently and remotely; an attacker does not need physical access to your phone. These types of attacks can happen at any time and can often happen because of weak security elsewhere on the device. These lapses in security might not be because your application is insecure. They could be due to a bug in the kernel or web browser. The question is this: can your application protect its data from attackers even when they gain access to the device through different routes?
As we discussed previously, Android runs on top of the Linux 2.6 kernel. We also learned that the Android Linux kernel handles security management for the operating system. Let’s take a look at the Android Security Architecture.
The Android kernel implements a privilege separation model when it comes to executing applications. This means that, like on a UNIX system, the Android operating system requires every application to run with its own user identifier (uid) and group identifier (gid).
Parts of the system architecture themselves are separated in this fashion. This ensures that applications or processes have no permissions to access other applications or processes.
What is Privilege Separation?
Privilege separation is an important security feature because it denies one of the more common types of attacks. In many cases, the first attack that is performed is not the most effective one. It is usually the stepping-stone or gateway to a bigger attack. Often, attackers will exploit one component of a system first; and once there, they will try to attack a more important component in the system. If both these components are running with the same privileges, then it is a very trivial task for the attacker to hop from one component to the next. By separating privileges, the attacker’s task becomes more difficult. He has to be able to escalate or change his privileges to that of the component he wishes to attack. In this manner, the attack is stopped, if not slowed.
Because the kernel implements privilege separation, it is one of the core design features of Android. The philosophy behind this design is to ensure that no application can read or write to code or data of other applications, the device user, or the operating system itself. Thus, an application might not be able to arbitrarily use the device’s networking stack to connect to remote servers. One application might not read directly from the device’s contact list or calendar. This feature is also known as sandboxing. After two processes have run in their own sandboxes, the only way they have to communicate with each other is to explicitly request permission to access data.
Let’s take a simple example. We have an application that records audio from the built-in microphone of the device. For this application to work correctly, the developer has to make sure to add a request for the RECORD_AUDIO permission in the application’s AndroidManifest.xml file. This allows our application to request permission to use the system component that handles audio recording. But who decides whether to grant or deny access? Android allows the end user to perform this final approval process. When the user installs our application, he is prompted with the screen shown in Figure 1-4. It is worthwhile to note that no prompt for permissions will take place when the application is executing. Instead, the permission will need to be granted at install time.
Figure 1-4. The Android permissions request screen
If we do not explicitly set our need for the RECORD_AUDIO permission, or if the device owner does not grant us the permission after we request it, then an exception will be thrown by the VM and the application will fail. It is up to the developer to know to request the permission and handle the scenario where permission is not granted by catching the relevant exception. To request this permission, the following tag must be included in the AndroidManifest.xml file of the project:
<uses-permission android:name="android.permission.RECORD_AUDIO" />
The full list of permissions is given in this book’s appendix.
Any application that is to run on the Android operating system must be signed. Android uses the certificate of individual developers in order to identify them and establish trust relationships among the various applications running in the operating system. The operating system will not allow an unsigned application to execute. The use of a certification authority to sign the certificate is not required, and Android will happily run any application that has been signed with a self-signed certificate.
Like permissions checks, the certificate check is done only during installation of the application. Therefore, if your developer certificate expires after your application is installed on the device, then the application will continue to execute. The only difference at this point would be that you would need to generate a new certificate before you could sign any new applications. Android requires two separate certificates for debug versions of your application and release versions of your application. Generally, the Eclipse environment running the Android Development Tools (ADT) is already setup to help you generate your keys and install your certificate, so that your applications can be automatically packaged and signed. The Android emulator behaves identically to the physical device. Like the physical device, it will only execute signed applications. We will cover application code signing in detail, as well as publishing and selling your applications online.
Summary
As we’ve seen so far, Android received a tremendous boost in resources and attention thanks to Google’s takeover of Android. This same care and attention has helped propel Android to one of the most rapidly growing smartphone operating systems in the world today. Android’s open source model has helped its numbers grow, mainly because many different hardware manufacturers can use the operating system on their phones.
We’ve also seen that the core of Android is based on the Linux kernel. The kernel’s two main tasks are (1) to serve as a bridge between hardware and operating system, and (2) to handle security, memory management, process management, and networking. The kernel is usually one of the main components that will be modified when different hardware manufacturers start adopting Android to work with their hardware.
The next layer that goes around the Android kernel is the runtime layer that comprises the core libraries and the Dalvik virtual machine. The Dalvik VM is a fundamental part of executing your applications on the Android platform. As you will see in the following chapters, the Dalvik VM has some unique features when it comes to executing applications securely and efficiently in a resource-constrained environment.
The next upper layers to be added are the frameworks and applications, respectively. You can think of the framework layer as yet another bridge between the Java API and the native code and system processes running below. This is where all the Android Java APIs live. Any libraries that you wish to import in your program are imported from here. The applications layer is where your applications will finally live and work. You will share this space with other developer applications and Android’s bundled applications such as the Phone, Calendar, E-mail, and Messaging applications.
We then looked briefly at the security risks, how you have the responsibility to protect your end user, and some of the ways in which Android facilitates this. The three areas we looked at were privilege separation, permissions, and application code signing. In the next chapters, we will explore what you can do to not only make use of these features, but also add in your own levels of security and end-user protection.
1 Bloomberg Businessweek, “Google Holds Honeycomb Tight,” Ashlee Vance and Brad Stone, www.businessweek.com/technology/content/mar2011/tc20110324_269784.htm , March 24, 2011.
3.12.36.65