Android Apps Security pdf - EBook Free Download

publicyardMobile - Wireless

Dec 10, 2013 (3 years and 9 months ago)

692 views

Android Apps
Security
Sheran A. Gunasekera
Create apps that are safe from hacking,
attacks, and security breaches
www.it-ebooks.info
For your convenience Apress has placed some of the front
matter material after the index. Please use the Bookmarks
and Contents at a Glance links to access them.
www.it-ebooks.info

v
Contents at a Glance
About the Author ��������������������������������������������������������������������������������������������������������� xiii
About the Technical Reviewer �������������������������������������������������������������������������������������� xv
Acknowledgments ������������������������������������������������������������������������������������������������������ xvii
Chapter 1: Android Architecture ■ ���������������������������������������������������������������������������������� 1
Chapter 2: Information: The Foundation of an App ■ ���������������������������������������������������� 13
Chapter 3: Android Security Architecture ■ ����������������������������������������������������������������� 31
Chapter 4: Concepts in Action – Part 1 ■ ���������������������������������������������������������������������� 47
Chapter 5: Data Storage and Cryptography ■ ��������������������������������������������������������������� 55
Chapter 6: Talking to Web Apps ■ ��������������������������������������������������������������������������������� 87
Chapter 7: Security in the Enterprise ■ ���������������������������������������������������������������������� 121
Chapter 8: Concepts in Action: Part 2 ■ ���������������������������������������������������������������������� 137
Chapter 9: Publishing and Selling Your Apps ■ ���������������������������������������������������������� 163
Chapter 10: Malware and Spyware ■ ������������������������������������������������������������������������� 203
Appendix A: Android Permission Constants ��������������������������������������������������������������� 213
Index ��������������������������������������������������������������������������������������������������������������������������� 223
www.it-ebooks.info
1

Chapter
1
Android Architecture
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).
www.it-ebooks.info

CHAPTER 1: Android Architecture2
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):
1. The kernel
2. The libraries and Dalvik virtual machine
3. The application framework
4. The applications
Figure 1-1. An HTC Dream (Courtesy Michael Oryl)
1
Bloomberg Businessweek, “Google Holds Honeycomb Tight,” Ashlee Vance and Brad Stone,
www.businessweek.com/technology/content/mar2011/tc20110324_269784.htm, March 24, 2011.
www.it-ebooks.info
CHAPTER 1: Android Architecture

3
The Kernel
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.
Application
Layer
Frameworks
Layer
Runtime
Layer
Kernel
Layer
App0
Activity
Manager
Window
Manager
Package
Manager
Surface
Manager
Media
Framework
SQLite
Core
Libraries
Dalvik Virtual
Machine (DVM)
OpenGL/ES FreeType WebKit
SGL SSL libc
Display
Driver
Mouse
Driver
Ethernet
Driver
USB
Driver
Keyboard
Driver
C, C++, Native Code Java
= Linux Kernel
= Libraries
= Android Runtime
= Android Frameworks
= Applications
WiFi
Driver
Hardware
Binder (IPC)
Driver
Power
Management
Flash Memory
Driver
Audio
Drivers
Resource
Manager
XMPP
Service
Content
Providers
View
System
Notification
Manager
App1 App2 App3 App4
Figure 1-2. The Android architecture
www.it-ebooks.info

CHAPTER 1: Android Architecture4
The Libraries
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:
 LibWebCore: Allows access to the web browser.
 Media libraries: Allows access to popular audio- and video-recording and
playback functions.
 Graphics libraries: Allows access to 2D and 3D graphics drawing engines.
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.
The Dalvik Virtual Machine
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.
www.it-ebooks.info
CHAPTER 1: Android Architecture

5
The Application Framework
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.
.jar file
.class file
.dex file
.class file
heterogeneous
constant pool
heterogeneous
constant pool
other data
string_ids
constant pool
type_ids
constant pool
proto_ids
constant pool
field_ids
constant pool
method_ids
constant pool
other data
.class file
heterogeneous
constant pool
other data
other data
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%
www.it-ebooks.info

CHAPTER 1: Android Architecture6
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 {
www.it-ebooks.info
CHAPTER 1: Android Architecture

7

/*
* Alternatively,for streaming media you can use
* mVideoView.setVideoURI(Uri.parse(URLstring));
*/
mVideoView.setVideoPath(path);
mVideoView.setMediaController(new MediaController(this));
mVideoView.requestFocus();

}
}
}
The Applications
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.
www.it-ebooks.info

CHAPTER 1: Android Architecture8
Security
Security isn’t a dirty word, Blackadder!
—General Melchett, Blackadder IV
Security is 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.
Protect Your User
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?
Security Risks
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
www.it-ebooks.info
CHAPTER 1: Android Architecture
9
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?
Android Security Architecture
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.
Privilege Separation
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.
www.it-ebooks.info

CHAPTER 1: Android Architecture10
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.
Permissions
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.
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.
WhAt is PriVilege sePArAtion?
www.it-ebooks.info
CHAPTER 1: Android Architecture

11
Application Code Signing
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.
Figure 1-4. The Android permissions request screen
www.it-ebooks.info

CHAPTER 1: Android Architecture12
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.
www.it-ebooks.info
13

Chapter
2
Information: The Foundation
of an App
The basis of all meaningful applications is information, and we design and build applications
to exchange, create, or store it. Mobile applications are no different. In today’s well-connected
mobile landscape, information exchange is the name of the game. To illustrate this point,
imagine an Android phone without mobile network or WiFi coverage. While there would still be
uses for such a phone, you would have lost access to some of the more important applications
on your device. For example, e-mail, instant messaging, web browsing, and any other
application that require the Internet would now be nonfunctional.
In later chapters, we will focus our efforts on examining information in transit and how to secure
it. In this chapter, we will focus mostly on what happens to information that is stored.
Securing Your Application from Attacks
When created or received, data needs to be stored somewhere. How this information is stored
will ultimately reflect on how secure your application really is. Releasing your application to the
public should be approached with the same caution and paranoia as launching a website on the
Internet. You should assume that your application will be either directly or indirectly attacked at
some time and that the only thing standing between your end user’s privacy and data protection
is your application.
Indirect Attacks
As dramatic as that last sentence sounds, it is not without basis. Before we go further, let’s take
a look at whether my fear mongering is justified. In the latter part of 2010 and early 2011, two
vulnerabilities were discovered in Android versions 2.2 and 2.3, respectively. The vulnerability is
essentially the same one, in which an attacker can copy any file that is stored on the device’s SD
www.it-ebooks.info

CHAPTER 2: Information: The Foundation of an App14
Card without permission or even without a visible cue that this is happening. The vulnerability
works as shown in Figure 2-1.
The following are the most noteworthy points:
1. A user visits a malicious website hosting a file, such as evil.html.
2. Due to one part of the vulnerability, the evil.html file is downloaded and
saved to the device SD Card without prompting the user.
3. Due to another part of the vulnerability, the saved file can be made to
execute JavaScript code as soon as it is saved. Once again, there is no
prompt to the end user.
4. Due to the final part of this vulnerability, the executed JavaScript from
the preceding point, because it is running under the “local” context of the
device, will have full access to upload files stored on the SD Card to a
website of the attacker’s choosing.
For the sake of argument, assume that your application writes all saved information to the SD
Card for storage under its own directory. Because of the vulnerability just discussed, the data
used by your application is at risk of being stolen. Any Android device that runs your application
and the vulnerable firmware versions poses a risk of data theft to its end user. This is an example
of an indirect attack on your application.
How vulnerable your application is to an indirect attack depends largely on how much effort you
put into architecting and considering security aspects before you begin writing a single line of
code. You may ask the question, “I’m just a small app developer planning to sell my app for a
low price online, so do I really need to waste time doing so much planning beforehand?” And I
would answer you with a resounding, “Yes!” Whether you are part of a team of thirty developers
or an individual working from home, a well-architected application is something you should
always strive to create. I hope that this is what you will learn from this book.
Malicious
Page
evil.html
auto saved
to SDCard.
.js
javascript
executed.
Full access
to SDCard.
No
prompt
SD
Figure 2-1. Data theft vulnerabilities
www.it-ebooks.info
CHAPTER 2: Information: The Foundation of an App

15
Direct Attacks
Direct attacks are significantly different and can take many different forms. A direct attack can
be classified as one that is targeted directly at your application. Thus, the attacker is looking to
leverage weaknesses in your application design to either collect sensitive information on your
application’s users or to attack the server that your application talks to. Take, for instance, a
mobile-banking application. An attacker may go after the mobile applications belonging to a
specific bank. If the application design is weak

for example, if that sensitive user data is stored
in clear text, or the communication between application and server is not secured by SSL

then
an attacker can craft special attacks that only target these weaknesses. This is a direct attack on
a specific application. I will cover direct attacks in more detail in
Chapter 9
of this book.
Project 1:“Proxim” and Data Storage
Let’s get started with a simple example called Proxim. I’ve been contracted to write an
application that can send an SMS to specific, defined contacts when a user is within certain
proximity to a set of GPS coordinates. For instance, with this application, a user can add his
wife as a contact and have the application SMS her every time he is within three miles of his
workplace and house. This way, she knows when he is close to home and the office.
You can download and examine the entire source code for the Proxim application from the
Source Code/Download area of the Apress website (
www.apress.com
). For the sake of clarity, let’s
take a look at the most important areas.
The data-storage routine is shown in Listing 2-1.
Listing 2-1.

The Save Routine, SaveController. java
package net.zenconsult.android.controller;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

import net.zenconsult.android.model.Contact;
import net.zenconsult.android.model.Location;
import android.content.Context;
import android.os.Environment;
import android.util.Log;

public class SaveController {
private static final String
TAG
= "SaveController";

public static void saveContact(Context context, Contact contact) {
if (
isReadWrite
()) {
try {
File outputFile = new File(context.getExternalFilesDir(null),contact.getFirstName());
FileOutputStream outputStream = new FileOutputStream(outputFile);
outputStream.write(contact.getBytes());
outputStream.close();
www.it-ebooks.info

CHAPTER 2: Information: The Foundation of an App16

} catch (FileNotFoundException e) {
Log.e(TAG,"File not found");
} catch (IOException e) {
Log.e(TAG,"IO Exception");
}

} else {
Log.e(TAG,"Error opening media card in read/write mode!");
}
}

public static void saveLocation(Context context, Location location) {
if (isReadWrite()) {
try {
File outputFile = new File(context.getExternalFilesDir(null),location.getIdentifier());
FileOutputStream outputStream = new FileOutputStream(outputFile);
outputStream.write(location.getBytes());
outputStream.close();

} catch (FileNotFoundException e) {
Log.e(TAG,"File not found");
} catch (IOException e) {
Log.e(TAG,"IO Exception");
}

} else {
Log.e(TAG,"Error opening media card in read/write mode!");
}
}

private static boolean isReadOnly() {
Log.e(TAG,Environment
.getExternalStorageState());
return Environment.MEDIA_MOUNTED_READ_ONLY.equals(Environment
.getExternalStorageState());
}

private static boolean isReadWrite() {
Log.e(TAG,Environment
.getExternalStorageState());

return Environment.MEDIA_MOUNTED.equals(Environment
.getExternalStorageState());
}
}
Each time a user selects the Save Location button or the Save Contact button, it triggers the
preceding code. Let’s take a look at the Location (see Listing 2-2) and Contact (see Listing
2-3) classes in more detail. While we could implement one main save routine, I am keeping it
separate in case there is a need to act on different objects in a different manner.
www.it-ebooks.info
CHAPTER 2: Information: The Foundation of an App

17
Listing 2-2. The Location Class, Location.java
package net.zenconsult.android.model;

publicclass Location {
private String identifier;
privatedouble latitude;
privatedouble longitude;

public Location() {

}

publicdouble getLatitude() {
return latitude;
}

publicvoid setLatitude(double latitude) {
this.latitude = latitude;
}

publicdouble getLongitude() {
return longitude;
}

publicvoid setLongitude(double longitude) {
this.longitude = longitude;
}

publicvoid setIdentifier(String identifier) {
this.identifier = identifier;
}

public String getIdentifier() {
return identifier;
}

public String toString() {
StringBuilder ret = new StringBuilder();
ret.append(getIdentifier());
ret.append(String.valueOf(getLatitude()));
ret.append(String.valueOf(getLongitude()));
return ret.toString();
}

publicbyte[] getBytes() {
return toString().getBytes();
}

}
www.it-ebooks.info

CHAPTER 2: Information: The Foundation of an App18
Listing 2-3. The Contact Class, Contact.java
package net.zenconsult.android.model;

publicclass Contact {
private String firstName;
private String lastName;
private String address1;
private String address2;
private String email;
private String phone;

public Contact() {

}

public String getFirstName() {
return firstName;
}

publicvoid setFirstName(String firstName) {
this.firstName = firstName;
}

public String getLastName() {
return lastName;
}

publicvoid setLastName(String lastName) {
this.lastName = lastName;
}

public String getAddress1() {
return address1;
}

publicvoid setAddress1(String address1) {
this.address1 = address1;
}

public String getAddress2() {
return address2;
}

publicvoid setAddress2(String address2) {
this.address2 = address2;
}

public String getEmail() {
return email;
}

www.it-ebooks.info
CHAPTER 2: Information: The Foundation of an App
19

publicvoid
setEmail(String email) {

this
.email = email;
}


public
String getPhone() {

return
phone;
}


publicvoid
setPhone(String phone) {

this
.phone = phone;
}


public
String toString() {
StringBuilder ret =
new
StringBuilder();
ret.append(getFirstName() + "|");
ret.append(getLastName() + "|");
ret.append(getAddress1() + "|");
ret.append(getAddress2() + "|");
ret.append(getEmail() + "|");
ret.append(getPhone() + "|");

return
ret.toString();
}


publicbyte
[] getBytes() {

return
toString().getBytes();
}
}
The
Location
and
Contact
classes are standard classes designed to hold data specific to each
type. Each of them contains
toString()
and
getBytes()
methods that return the entire contents
of the class as either a
String
or an array of
bytes
.
If we were to manually add a
Contact
object, then we would most likely use code similar to what
is shown in Listing 2-4.
Listing 2-4. Code that Adds a New Contact Object
final
Contact contact =
new
Contact();
contact.setFirstName("Sheran");
contact.setLastName("Gunasekera");
contact.setAddress1("");
contact.setAddress2("");
contact.setEmail("sheran@zenconsult.net");
contact.setPhone("12120031337");
Assume for the moment that the code in Listing 2-4 is called when a user fills in the screen to
add a new contact to the application. Rather than seeing hardcoded values, you will use the
getText()
methods from each of the
EditText
objects that are displayed on your main
View
.
If you execute the code
SaveController.saveContact(getApplicationContext(), contact)

)
in
your Android simulator, the
SaveController
will take the newly created
Contact
and store it in the
external media source (refer back to Listing 2-1).
www.it-ebooks.info

CHAPTER 2: Information: The Foundation of an App20
Let’s take it a line at a time, beginning with the constructor for the saveContact() method:
public static void saveContact(Context context, Contact contact) {
if (isReadWrite()) {
try {
The preceding snippet expects a Context object and a Contact object. Each application on
Android has its own Context. A Context object holds application-specific classes, methods,
and resources that can be shared among all the classes within an application. For example, a
Context object will contain information about the location of the SD Card directory. To access it,
you have to invoke the Context.getExternalFilesDir() method. After the method accepts the
parameters, it will check to see if the SD Card on the device is mounted and if it is writeable. The
isReadWrite() method will execute and return a true or false value to indicate this:
File outputFile = new File(context.getExternalFilesDir(null),contact.getFirstName());
This code creates a File object that points to the location of the SD Card directory. We use the
first name of the Contact object as the file name:
FileOutputStream outputStream = new FileOutputStream(outputFile);
outputStream.write(contact.getBytes());
outputStream.close();
Using this code, we create a FileOutputStream that points to the location of our File object.
Next, we write the contents of our Contact object to the output stream using the getBytes()
method to return an array of bytes. Finally, we close the FileOutputStream.
When execution completes, we should have a file with the name “Sheran” written to the SD Card
directory on the device. I’m using the Android simulator on Mac OS X Snow Leopard. Therefore,
when I navigate to the location of the simulator, I can see the screen shown in Figure 2-2.
Note It is always good practice to use the getExternalFilesDir() method to find the
location of the SD Card on an Android device. Because Android can run on a large number of
devices with different specifications, the location of the SD Card directory may not always be in
/sdcard. The getExternalFilesDir() method will query the operating system for the correct
location of the SD Card and return the location to you.
www.it-ebooks.info
CHAPTER 2: Information: The Foundation of an App

21
When this image is mounted by navigating to Android/data/net.zenconsult.android/files, the
newly created contact file name is visible (see Figure 2-3).
If we open the file up in a text editor, we can see the plain text data that was saved from the
application (see Figure 2-4).
Figure 2-2. The SD Card image file on Max OS X
Figure 2-3. The Contact object that was written to a file
www.it-ebooks.info

CHAPTER 2: Information: The Foundation of an App22
Classification of Information
One of the things I struggled with when starting out in mobile-application development was the
fact that I’d get into code writing from the get go. I’d make up the features in my head and code
them as I went along. All too often, I would later spend time revising my code and going back to
write a plan midstream. This had devastating effects on my deadlines and deliverables. It also
had a detrimental effect on the security of my applications.
I have since learned that writing up a brief outline of the project that I am about to embark on
will help me think of things ahead of time. While this seems like an obvious thing, there are many
developers that I have spoken with who fail to follow this simple step. One other thing that I have
also begun doing religiously is finding time to look at the information or data that my application
will be handling. For instance, I use a table like the one shown in Table 2-1 to classify the data
that my application handles. The table is very basic; however, by putting it down on paper, I am
able to visualize the types of data my application will handle—moreover, I’m able to formulate a
plan to secure that information.
If you look at the data classification table in Table 2-1 closely, you will realize that some of the
headings are very subjective. Different people will have different opinions on what constitutes
sensitive or personal information. Nevertheless, it is usually best to try and zero in on a common
frame of reference as to what constitutes sensitive and personal information. In this section,
you will try to do that by taking a look at the table header first, and then going over each of the
columns:
Data Type: You will be handling this data within your application. It is self-
explanatory.
Personal?: This column indicates whether the data type is classified as personal
information.
Figure 2-4. The contents of the Contact object
Table 2-1. Data Classification Table
Data Type Personal?Sensitive?Create Store Send Receive
Name Yes No X X x
E-mail Address Yes Yes X X x
Phone No.Yes Yes X X
Address Yes Yes X X
www.it-ebooks.info
CHAPTER 2: Information: The Foundation of an App

23
Sensitive?: This column indicates whether the data type is classified as sensitive
information.
Create: Does your application allow this user to create this data type?
Store: Does your application store this data type either on the device or remotely
on a server?
Sent: Is this data type sent across the network to another party or server?
Receive: Is this data type received over the network from another party?
What Is Personal Information?
Personal information can be classified as data that is known to you and a limited number of
people within your social circle. Personal information is usually something that is private to
you, but that you would be willing to share with close friends and family members. Examples of
personal information can be your phone number, address, and e-mail address. The effects of
having this information compromised and leaked will usually not cause significant physical or
emotional harm to yourself or your family members. Instead, it may give rise to situations that
will greatly inconvenience you.
What Is Sensitive Information?
Sensitive information is worth much more than personal information. Sensitive information is
usually information that you will not share with anyone under most circumstances. Data of this
type includes your passwords, Internet banking credentials (such as PIN codes), mobile phone
number, Social Security number, or address. If sensitive information is compromised, then the
effects may cause you either physical or emotional harm. This information should be protected
all the time, regardless of whether it is in transit or in storage.
Caution How can the loss of sensitive information cause you physical or emotional harm?
Consider losing your online banking credentials. An attacker can cause you immense financial
(physical and emotional) harm by stealing all your money. A stalker that gets hold of your
phone number or address can pose a grave threat to you or your family’s physical well being.
Analysis of Code
If we go back to the indirect attack that we discussed earlier in this chapter, it is evident that
data kept in clear view on an SD Card is a significant risk and should be avoided at all costs.
Data theft or exposure has been one of the leading causes of financial and reputational loss for
corporations. But just because you’re writing an application for a single user of a smartphone
does not mean you should treat data theft lightly. In the case of Proxim, this weakness of clear
www.it-ebooks.info

CHAPTER 2: Information: The Foundation of an App
24
text data storage exists. Anyone who has access to the device’s SD Card will be able to copy
personal information, such as names, addresses, phone numbers, and e-mail addresses.
We can trace the flaw in the original code to the point where we save the data. The data itself
is not obscured or encrypted in any way. If we were to encrypt the data, then the personal
information would still be safe. Let’s take a look at how we can implement encryption in our
original Proxim code.
Chapter 5
will cover public key infrastructure and encryption in depth; so
for the purposes of this exercise, we will cover a very basic example of Advanced Encryption
Standard (AES) encryption. Public Key encryption or Asymmetric encryption is a method of
encrypting or obfuscating data by using two different types of keys. Each user has two keys, a
public and a private one. His private key can only decrypt data that is encrypted by the public
key. The key is called public because it is freely given away to other users. It is this key that other
users will use to encrypt data.
Where to Implement Encryption
We will encrypt our data just before we save it to the SD Card. In this way, we never write the
data to the SD Card in a format that can be read by anyone. An attacker that collects your
encrypted data has to first use a password to decrypt the data before having access to it.
We will use AES to encrypt our data using a password or key. One key is required to both
encrypt and decrypt the data. This is also known s symmetric key encryption. Unlike public key
encryption, this key is the sole one used to both encrypt and decrypt data. This key will need
to be stored securely because, if it is lost or compromised, an attacker can use it to decrypt the
data. Listing 2-5 shows the encryption routine.
Listing 2-5.

An Encryption Routine
privatestaticbyte
[] encrypt(
byte
[] key,
byte
[] data){
SecretKeySpec sKeySpec =
new
SecretKeySpec(key,"AES");
Cipher cipher;
byte[] ciphertext =
null
;

try
{
cipher = Cipher.
getInstance
("AES");
cipher.init(Cipher.
ENCRYPT_MODE
, sKeySpec);
ciphertext = cipher.doFinal(data);
}
catch
(NoSuchAlgorithmException e) {
Log.
e
(
TAG
,"NoSuchAlgorithmException");
}
catch
(NoSuchPaddingException e) {
Log.
e
(
TAG
,"NoSuchPaddingException");
}
catch
(IllegalBlockSizeException e) {
Log.
e
(
TAG
,"IllegalBlockSizeException");
}
catch
(BadPaddingException e) {
Log.
e
(
TAG
,"BadPaddingException");
}
catch
(InvalidKeyException e) {
Log.
e
(
TAG
,"InvalidKeyException");
}

return
ciphertext;

}
www.it-ebooks.info
CHAPTER 2: Information: The Foundation of an App

25
Let’s go through the code, section by section. The first bit of code initializes the SecretKeySpec class
and creates a new instance of the Cipher class in preparation of generating an AES secret key:
SecretKeySpec sKeySpec = new SecretKeySpec(key,"AES");
Cipher cipher;
byte[] ciphertext = null;
The preceding code also initializes a byte array to store the ciphertext. The next bit of code
prepares the Cipher class to use the AES algorithm:
cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, sKeySpec);
The cipher.init() function initializes the Cipher object, so it can perform encryption using the
generated secret key. The next line of code encrypts the plain text data and stores the encrypted
contents in the ciphertext byte array:
ciphertext = cipher.doFinal(data);
In order for the preceding routine to work, it should always have an encryption key. It is
important that we use the same key for the decryption routine, as well. Otherwise, it will fail. It
is generally better to write your own key generator that will generate a random number–based
key. This will make it harder for an attacker to guess than a normal password. For this exercise, I
used the key-generation algorithm shown in Listing 2-6.
Listing 2-6. A Key-Generation Algorithm
publicstaticbyte[] generateKey(byte[] randomNumberSeed) {
SecretKey sKey = null;
try {
KeyGenerator keyGen = KeyGenerator.getInstance("AES");
SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
random.setSeed(randomNumberSeed);
keyGen.init(256,random);
sKey = keyGen.generateKey();
} catch (NoSuchAlgorithmException e) {
Log.e(TAG,"No such algorithm exception");
}
return sKey.getEncoded();
}
Now, let’s analyze the code. This pair of lines initializes the KeyGenerator class so it can generate
AES-specific keys, and then initializes the device’s random-number generator so it can generate
random numbers:
KeyGenerator keyGen = KeyGenerator.getInstance("AES");
SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
These random numbers are encoded using SHA1. SHA1, or Secure Hash Algorithm 1, is a
cryptographic hashing function. The algorithm will operate on a piece of data that has an
arbitrary length and will produce a short string that is of fixed size. If any piece of the data being
hashed is changed, then the resulting hash will vary. This is an indication that a piece of data has
been tampered with.
www.it-ebooks.info

CHAPTER 2: Information: The Foundation of an App26
The next snippet of code uses the random-number seed provided to generate a 256-bit key
using this random number:
random.setSeed(randomNumberSeed);
keyGen.init(256,random);
sKey = keyGen.generateKey();
Simply run the key-generation algorithm once and save the resulting key to use with the
decryption routine.
Results of Encryption
When we examine the same Contact object in the SD Card, the contents appear garbled (see
Figure 2-5) and unreadable by any casual snoopers or deliberate attackers.
Reworked Project 1
Our changes to the Proxim project mostly affect the saveController() method (see Listing 2-7).
Listing 2-7. The Reworked SaveController.java method
package net.zenconsult.android.controller;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;

import net.zenconsult.android.crypto.Crypto;
import net.zenconsult.android.model.Contact;
import net.zenconsult.android.model.Location;
import android.content.Context;
import android.os.Environment;
import android.util.Log;

Figure 2-5. The encrypted contents of the Contact object
www.it-ebooks.info
CHAPTER 2: Information: The Foundation of an App

27
public class SaveController {
private static final String TAG = "SaveController";

public static void saveContact(Context context, Contact contact) {
if (isReadWrite()) {
try {
File outputFile = new File(context.getExternalFilesDir
(null),contact.getFirstName());
FileOutputStream outputStream = new FileOutputStream
(outputFile);
byte[] key = Crypto.generateKey
("randomtext".getBytes());
outputStream.write(encrypt(key,contact.getBytes()));
outputStream.close();

} catch (FileNotFoundException e) {
Log.e(TAG,"File not found");
} catch (IOException e) {
Log.e(TAG,"IO Exception");
}

} else {
Log.e(TAG,"Error opening media card in read/write mode!");
}
}

public static void saveLocation(Context context, Location location) {
if (isReadWrite()) {
try {
File outputFile = new File(context.getExternalFilesDir
(null),location.getIdentifier());
FileOutputStream outputStream = new FileOutputStream
(outputFile);
byte[] key = Crypto.generateKey
("randomtext".getBytes());
outputStream.write(encrypt(key,location.getBytes()));
outputStream.close();

} catch (FileNotFoundException e) {
Log.e(TAG,"File not found");
} catch (IOException e) {
Log.e(TAG,"IO Exception");
}

} else {
Log.e(TAG,"Error opening media card in read/write mode!");
}
}

www.it-ebooks.info

CHAPTER 2: Information: The Foundation of an App28
private static boolean isReadOnly() {
Log.e(TAG,Environment
.getExternalStorageState());
return Environment.MEDIA_MOUNTED_READ_ONLY.equals(Environment
.getExternalStorageState());
}

private static boolean isReadWrite() {
Log.e(TAG,Environment
.getExternalStorageState());

return Environment.MEDIA_MOUNTED.equals(Environment
.getExternalStorageState());
}

private static byte[] encrypt(byte[] key, byte[] data){
SecretKeySpec sKeySpec = new SecretKeySpec(key,"AES");
Cipher cipher;
byte[] ciphertext = null;
try {
cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, sKeySpec);
ciphertext = cipher.doFinal(data);
} catch (NoSuchAlgorithmException e) {
Log.e(TAG,"NoSuchAlgorithmException");
} catch (NoSuchPaddingException e) {
Log.e(TAG,"NoSuchPaddingException");
} catch (IllegalBlockSizeException e) {
Log.e(TAG,"IllegalBlockSizeException");
} catch (BadPaddingException e) {
Log.e(TAG,"BadPaddingException");
} catch (InvalidKeyException e) {
Log.e(TAG,"InvalidKeyException");
}
return ciphertext;

}
}
Exercise
Add EncrypTIon AT objEcT crEATIon TImE
There are many ways to encrypt the data in our Proxim application. What I have done is to encrypt it at storage time.
Your exercise is to rewrite the Proxim application so that the data is encrypted as soon as it is created.
Tip Do not modify the SaveController.java file. Look elsewhere.
www.it-ebooks.info
CHAPTER 2: Information: The Foundation of an App
29
Wr
ITE

A

dE
cryp
TI
on
r
ou
TI
n
E

F
or
T
h
E

p
rox
I
m Appl
I
c
ATI
on
Use the Android API reference and write a simple decryption routine based on the same principle as the encryption
routine. Create a new class called
LoadController
that will handle the loading of information from the SD Card.
Summary
Storing plain text or other easily read data on mobile devices is something you should avoid
doing at all costs. Even though your application itself might be written securely, an indirect
attack that originates from a completely different area on the device can still collect and read
sensitive or personal information written by your application. Follow the following basic steps
during application design:
1.
First, determine what data types are stored, created, or exchanged by
your application. Next, classify them into personal or sensitive data,
so that you will be aware of how to treat the data during application
execution.
2.
Have a collection of encryption routines that you can reuse in your
applications. It is best to keep this collection as a separate library that
you can include in your project.
3.
Generate a different key for each application that you write. Write a good
key-generator algorithm that creates lengthy and unpredictable secret
keys.
4.
Encrypt data either at creation or storage time.
www.it-ebooks.info
31

Chapter
3
Android Security Architecture
In
Chapter 2
, we looked at a simple example of how we can protect information using
encryption. However, that example did not make use of Android’s built-in security and
permissions architecture. In this chapter, we will take a look at what Android is able to offer the
developer and end user with regard to security. We will also look at some direct attacks that can
take place on applications and how to take the necessary safeguards to minimize the loss of
private data.
The Android platform has several mechanisms that control the security of the system and
applications, and it attempts to ensure application isolation and compartmentalization at every
stage. Each process within Android runs with its own set of privileges, and no other application
is able to access this application or its data without explicit permissions provided by the end
user. Even though Android exposes a large number of APIs to the developer, we cannot use all
of these APIs without requiring the end user to grant access.
Revisiting the System Architecture
Let’s start by looking at the Android architecture once more. We covered the Android system
architecture in
Chapter 1
, where you will recall that each process runs in its own isolated
environment. There is no interaction possible between applications unless otherwise explicitly
permitted. One of the mechanisms where such interaction is possible is by using permissions.
Again in
Chapter 1
, we looked at a simple example of how we needed to have the
RECORD_AUDIO

permission set, so that our application can make use of the device’s microphone. In this chapter,
we will look at the permissions architecture in a little bit more detail (see Figure

3-1
).
www.it-ebooks.info

CHAPTER 3: Android Security Architecture
32
Figure

3-1
depicts a simpler version of the Android architecture than the one presented in
Chapter 2
; specifically, this figure focuses more on the applications themselves.
As we saw previously, Android applications will execute on the Dalvik virtual machine (DVM).
The DVM is where the
bytecode
, or the most fundamental blocks of code, will execute. It is
analogous to the Java Virtual Machine (JVM) that exists on personal computers and servers
today. As depicted in Figure

3-1
, each application—even a built-in system application—will
execute in its own instance of the Dalvik VM. In other words, it operates inside a walled garden
of sorts, with no outside interaction among other applications, unless explicitly permitted. Since
starting up individual virtual machines can be time consuming and could increase the latency
between application launch and startup, Android relies on a preloading mechanism to speed up
the process. The process, known as Zygote, serves two functions: it acts first as a launch pad
for new applications; and second, as a repository of live core libraries to which all applications
can refer during their life cycles.
The Zygote process takes care of starting up a virtual machine instance and preloading and
pre-initializing any core library classes that the virtual machine requires. Then, it waits to receive
a signal for an application startup. The Zygote process is started up at boot time and works
in a manner similar to a queue. Any Android device will always have one main Zygote process
running. When the Android Activity Manager receives a command to start an application, it calls
up the virtual machine instance that is part of the Zygote process. Once this instance is used to
launch the application, a new one is forked to take its place. The next application that is started
up will use this new Zygote process, and so on.
The repository part of the Zygote process will always make the set of core libraries available to
applications throughout their life cycles. Figure

3-2
shows how multiple applications make use of
the main Zygote process’s repository of core libraries.
Installed Applications
System
Applications
Binder
Embedded Linux
Display
Bluetooth
GPS
Receiver
Cellular
Radio
Application
Application
Application
Application
Application
Application
Application
DVM
DVM
DVM
DVM
DVM
DVM
DVM
Figure 3-1.

The Android system architecture
www.it-ebooks.info
CHAPTER 3: Android Security Architecture

33
Understanding the Permissions Architecture
As we discussed in
Chapter 1
, applications running on the Android operating system all run with
their own set of user and group identifiers (UID and GID, respectively). The constrained manner
in which applications execute make it impossible for one application to read or write data from
another. To facilitate information sharing and interprocess communication among applications,
Android uses a system of permissions.
By default, an application has no permissions to perform any types of activities that would cause
damage or drastically impact other applications on the device. It also has no ability to interact
with the Android operating system, nor can it call any of the protected APIs to use the camera,
GPS, or networking stacks. Finally, a default application does not have the ability to read or write
to any of the end user’s data. The Linux kernel handles this task.
In order for an application to access high-privileged APIs or even gain access to user data,
it has to obtain permission from the end user. You, as the developer, have to understand
what permissions your application will require before you release it to the public. Once you
make a list of all your required permissions, you will need to add each one of them to your
AndroidManifest.xml
file. Then, when installing an application for the first time, the end user is
prompted by the device to grant or deny specific permissions as required by the application.
Therefore, a good practice is to develop your application in a manner that will fail modularly if a
user does not provide a specific permission. For example, let’s say you’ve written an application
that uses GPS Location inquiries, accesses user data, and sends SMS messages. The end user
grants your application two of the three permissions, but leaves out SMS message sending. You
should be able to write your application such that the functionality requiring SMS sending will
disable itself (unless omitting this permission breaks your entire application). This way, the end
user can still use your application with reduced functionality.
Zygote
Maps
Zygote heap
(shared dirty,
copy-on-write;
rarely written)
core library dex
files
(mmap()ed)
Maps live code
and heap
shared from
Zygote
Maps dex file
(mmap()ed)
(private dirty)
Browser
Browser live
code and heap
shared from
Zygote
Browser dex file
(mmap()ed)
(private dirty)
Home
Home live code
and heap
shared from
Zygote
Home dex file
(mmap()ed)
(private dirty)
“live” core
libraries
(shared dirty;
read-only)
Figure 3-2.

How applications use Zygote’s repository of core libraries
www.it-ebooks.info

CHAPTER 3: Android Security Architecture34
Before exploring permissions further, you need to familiarize yourself with a couple of topics that
are used in the context of Android software development and security: content providers and
intents. Although you most likely have heard these terms mentioned before, let’s go over them
here to make sure your understanding is complete.
Content Providers
Content providers are synonymous with data stores. They act as repositories of information
from which applications can read and write. Since the Android architecture does not allow for a
common storage area, content providers are the only way that applications can exchange data.
As a developer, you might be interested in creating your own content providers, so that other
applications can gain access to your data. This is as easy as subclassing the ContentProvider
object in the android.content package. We will cover the creation of a custom ContentProvider
objects in more detail in subsequent chapters of this book.
In addition to allowing the creation of your own content providers, Android provides several
content providers that allow you to access the most common types of data on the device,
including images, videos, audio files, and contact information. The Android provider package,
android.provider, contains many convenience classes that allow you to access these content
providers; Table 3-1 lists these.
Table 3-1. Content Provider Classes
Class Name Description
AlarmClock Contains an intent action and extras that can be
used to start an activity to set a new alarm in an
alarm clock application.
Browser
Browser.BookmarkColumns Column definitions for the mixed bookmark and
history items available at BOOKMARKS_URI.
Browser.SearchColumns Column definitions for the search history table,
available at SEARCHES_URI.
CallLog Contains information about placed and received
calls.
CallLog.Calls Contains the recent calls.
ContactsContract The contract between the contacts provider and
applications.
ContactsContract.AggregationExceptions Constants for the contact aggregation exceptions
table, which contains aggregation rules overriding
those used by automatic aggregation.
ContactsContract.CommonDataKinds Container for definitions of common data types
stored in the ContactsContract.Data table.
ContactsContract.CommonDataKinds.Email A data kind representing an e-mail address.
ContactsContract.CommonDataKinds.Event A data kind representing an event.
(continued )
www.it-ebooks.info
CHAPTER 3: Android Security Architecture

35
Class Name Description
ContactsContract.CommonDataKinds.
GroupMembership
Group membership.
ContactsContract.CommonDataKinds.Im A data kind representing an IM address. You can use
all columns defined for ContactsContract.Data, as
well as the following aliases.
ContactsContract.CommonDataKinds.Nickname A data kind representing the contact’s nickname.
ContactsContract.CommonDataKinds.Note Notes about the contact.
ContactsContract.CommonDataKinds.Organization A data kind representing an organization.
ContactsContract.CommonDataKinds.Phone A data kind representing a telephone number.
ContactsContract.CommonDataKinds.Photo A data kind representing a photo for the contact.
ContactsContract.CommonDataKinds.Relation A data kind representing a relation.
ContactsContract.CommonDataKinds.SipAddress A data kind representing an SIP address for the
contact.
ContactsContract.CommonDataKinds.
StructuredName
A data kind representing the contact’s proper name.
ContactsContract.CommonDataKinds.
StructuredPostal
A data kind representing a postal address.
ContactsContract.CommonDataKinds.Website A data kind representing a web site related to the
contact.
ContactsContract.Contacts Constants for the Contacts table, which contains a
record per aggregate of raw contacts representing
the same person.
ContactsContract.Contacts.AggregationSuggestions A read-only subdirectory of a single contact
aggregate that contains all aggregation suggestions
(other contacts).
ContactsContract.Contacts.Data A subdirectory of a single contact that contains all of
the constituent raw contactContactsContract.Data
rows
ContactsContract.Contacts.Entity A subdirectory of a contact that contains all of
its ContactsContract.RawContacts, as well as
ContactsContract.Data rows.
ContactsContract.Contacts.Photo A read-only subdirectory of a single contact that
contains the contact’s primary photo.
ContactsContract.Data Constants for the data table that contains data
points tied to a raw contact.
ContactsContract.Directory Represents a group of contacts.
ContactsContract.Groups Constants for the Groups table.
(continued )
Table 3.1 (continued )
www.it-ebooks.info

CHAPTER 3: Android Security Architecture36
Class Name Description
ContactsContract.Intents Contains helper classes used to create or manage
intents that involve contacts.
ContactsContract.Intents.Insert Convenience class that contains string constants
used to create contact intents.
ContactsContract.PhoneLookup Table that represents the result of looking up a
phone number (e.g., for caller ID).
ContactsContract.QuickContact Helper methods to display QuickContact dialogs that
allow users to pivot on a specific Contacts entry.
ContactsContract.RawContacts Constants for the raw contacts table, which contains
one row of contact information for each person in
each synced account.
ContactsContract.RawContacts.Data A subdirectory of a single raw contact that contains
all of its ContactsContract.Data rows.
ContactsContract.RawContacts.Entity A subdirectory of a single raw contact that contains
all of its ContactsContract.Data rows.
ContactsContract.RawContactsEntity Constants for the raw contacts entities table, which
can be thought of as an outer join of the raw_
contacts table with the data table.
ContactsContract.Settings Contact-specific settings for various Accounts.
ContactsContract.StatusUpdates A status update is linked to a ContactsContract.Data
row and captures the user’s latest status update via
the corresponding source.
ContactsContract.SyncState A table provided for sync adapters to use for storing
private sync state data.
LiveFolders A LiveFolder is a special folder whose content is
provided by a ContentProvider.
MediaStore The Media provider contains meta data for all
available media on both internal and external
storage devices.
MediaStore.Audio Container for all audio content.
MediaStore.Audio.Albums Contains artists for audio files.
MediaStore.Audio.Artists Contains artists for audio files.
MediaStore.Audio.Artists.Albums Subdirectory of each artist containing all albums on
which a song by the artist appears.
MediaStore.Audio.Genres Contains all genres for audio files.
MediaStore.Audio.Genres.Members Subdirectory of each genre containing all members.
MediaStore.Audio.Media
MediaStore.Audio.Playlists Contains playlists for audio files.
Table 3.1 (continued )
(continued )
www.it-ebooks.info
CHAPTER 3: Android Security Architecture

37
Class Name Description
MediaStore.Audio.Playlists.Members Subdirectory of each playlist containing all members.
MediaStore.Files Media provider table containing an index of all files
in the media storage, including nonmedia files.
MediaStore.Images Contains metadata for all available images.
MediaStore.Images.Media
MediaStore.Images.Thumbnails Allows developers to query and get two kinds of
thumbnails: MINI_KIND (512 × 384 pixels) and
MICRO_KIND (96 × 96 pixels).
MediaStore.Video
MediaStore.Video.Media
MediaStore.Video.Thumbnails Allows developers to query and get two kinds of
thumbnails: MINI_KIND (512 × 384 pixels) and
MICRO_KIND (96 × 96 pixels).
SearchRecentSuggestions A utility class providing access to
SearchRecentSuggestionsProvider.
Settings Contains global system-level device preferences.
Settings.NameValueTable Common base for tables of name/value settings.
Settings.Secure Secure system settings containing system
preferences that applications can read, but are not
allowed to write.
Settings.System System settings containing miscellaneous system
preferences.
SyncStateContract The ContentProvider contract for associating data
with any data array account.
SyncStateContract.Constants
SyncStateContract.Helpers
UserDictionary A provider of user-defined words for input methods
to use for predictive text input.
UserDictionary.Words Contains the user-defined words.
Accessing a content provider requires prior knowledge of the following information:
The content provider object ( Contacts, Photos, Videos, etc.)
The columns required from this content provider
The query to fetch this information
As stated previously, content providers act in a similar manner to a Relational Database, such as
Oracle, Microsoft SQL Server, or MySQL. This becomes evident when you first try to query one.
For example, you access the MediaStore.Images.Media content provider to query for images.
Table 3.1 (continued )
www.it-ebooks.info

CHAPTER 3: Android Security Architecture
38
Let’s assume that we want to access each of the image names stored on the device. We first
need to create a content provider URI to access the external store on the device:
Uri images = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
Next, we need to create a receiver object for the data we will be fetching. Simply declaring an
array does this:
String[] details = new String[] {MediaStore.MediaColumns.DISPLAY_NAME};
To traverse the resulting dataset, we need to create and use a
managedQuery
and then use the
resulting
Cursor
object to move through rows and columns:
Cursor cur = managedQuery(details,details, null, null null);
We can then iterate over the results using the
Cursor
object we created. We use the
cur.moveToFirst()
method to move to the first row and then read off the image name, like so:
String name = cur.getString(cur.getColumnIndex(MediaStore.MediaColumns.DISPLAY_NAME));
After that, we advance the cursor to the next record by calling the
cur.moveToNext()
method.
To

query multiple records, this process can be wrapped in either a
for
loop or
do
/
while
block.
Note that some content providers are controlled, and your application will need to request
specific permissions before attempting to access them.
Intents
Intents are types of messages that one application sends to another to control tasks or transport
data. Intents work with three specific types of application components: activity, service, and
broadcast receiver. Let’s take a simple example where your application requires the Android
device browser to start up and load the contents of a URL. Some of the main components of an
Intent
object include the intent action and the intent data. For our example, we want our user to
view the browser, so we will use the
Intent.ACTION_VIEW
constant to work with some data that is
at the URL,
http://www.apress.com
. Our
Intent
object will be created like this:
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(http://www.apress.com);
To invoke this intent, we call this code:
startActivity(intent);
To control which applications can receive intents, a permission can be added to the intent prior
to dispatching it.
Checking Permissions
We’ve very briefly covered content providers and intents, including how the Android operating
system controls access to these objects through the use of permissions. In
Chapter 1
, we
looked at how an application can request the end user for specific permissions to interact with
the system. Let’s look at how permission checks really take place and where.
A validation mechanism will handle permission checks within the Android operating system.
When your application makes any API call, the permission validation mechanism will check if
www.it-ebooks.info
CHAPTER 3: Android Security Architecture

39
your application has the required permissions to complete the call. If a user grants permission,
the API call is processed; otherwise, a SecurityException is thrown.
API calls are handled in three separate steps. First, the API library is invoked. Second, the library
will invoke a private proxy interface that is part of the API library itself. Finally, this private proxy
interface will use interprocess communication to query the service running in the system process
to perform the required API call operation. This process is depicted in Figure 3-3.
In some instances, an application may also use native code to conduct API calls. These native
API calls are also protected in a similar manner because they are not allowed to proceed unless
they are called through Java wrapper methods. In other words, before a native API call can
be invoked, it has to go through a wrapped Java API call that is then subject to the standard
permission-validation mechanism. All validation of permissions is handled by the system process.
Additionally, applications that require access to the BLUETOOTH, WRITE_EXTERNAL_STORAGE,
and INTERNET permissions will be assigned to a Linux group that has access to the network
sockets and files associated with those permissions. This small subset of permissions has its
validation performed at the Linux kernel.
Using Self-Defined Permissions
Android allows developers to create and enforce their own permissions. As with system
permissions, you need to declare specific tags and attributes within the AndroidManifest.xml
file. If you write an application that provides a specific type of functionality accessible by other
developers, you can choose to protect certain functions with your own custom permissions.
In your application’s AndroidManifest.xml file, you have to define your permissions as follows:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="net.zenconsult.mobile.testapp" >
<permission android:name="net.zenconsult.mobile.testapp.permission.PURGE_DATABASE"
android:label="@string/label_purgeDatabase"
android:description="@string/description_purgeDatabase"
android:protectionLevel="dangerous" />
. . .
</manifest>
Figure 3-3. The API call process
www.it-ebooks.info
CHAPTER 3: Android Security Architecture
40
You define the name of your permission in the
android:name
attribute. The
android:label
and
android:description
attributes are required. They are pointers to strings that you define in your
AndroidManifest.xml
file. The strings will identify what the permission is and describe what this
permission does to end users that browse the list of permissions present on the device. You will
want to set these strings with something descriptive, as in this example:
<string name=" label_purgeDatabase ">purge the application database </string>
<string name="permdesc_callPhone">Allows the application to purge the core database of
the information store. Malicious applications may be able to wipe your entire application
information store.</string>
The
android:protectionLevel
attribute is required. It categorizes the permission into one of the
four levels of protection discussed earlier.