Chapter 9

Making Your Application Safe and Secure

In This Chapter

  • Understanding security and its relationship with trust
  • Knowing the basics of security and trust for mobile devices and apps
  • Appreciating the Android security model and making your application work within it
  • Recognizing where the insecurities lie in your Android app and protecting it

“Eternal vigilance!” is the watchword for developing mobile devices and applications. However, implementing random security techniques in your app as a result of blind panic is hardly a good development strategy. As you design your app, think systematically to see where the security principles described in this chapter apply, and then implement the necessary security using a combination of the techniques also described in this chapter.

In this chapter, we take a holistic look at developing secure Android apps — starting by describing why security is especially important for mobile apps, and then presenting security principles and general security techniques. We then get into Android security specifics.

Recognizing the Importance of Security

Security is an increasingly important consideration for mobile devices (and their applications), for three primary reasons:

  • Mobile devices store valuable personal information. Most people's mobile devices eventually become repositories for all types of personal information — their geographical location, contact names and addresses, financial transactions, and credit card information, for example. Theft of this information can result in significant financial loss to the user.
  • Mobile devices have a greater security footprint than applications on your desktop. Mobile devices have more areas of vulnerability than desktop, and even laptop, applications. Mobile devices are designed to interact with the outside world via the Internet and other networking capabilities, such as Wi-Fi and Bluetooth, so they're exposed to all the consequent dangers. For example, when a user accesses the Internet from the browser on a mobile device, all browser-based vulnerabilities certainly apply — such as phishing, spyware, and viruses (collectively known as malware). However, malware poses a greater risk to mobile devices than to desktop computers because websites built to support mobile users are notorious for being security risks themselves (because they have been hurriedly implemented, usually without thought given to making them secure) — which means, of course, that they present a risk to devices that access them.

    Because an app is now the primary means of using a device, it creates a security risk. Keep in mind that mobile apps have been authored by a range of organizations and developers and have been installed from diverse locations. Depending on the permissions granted to an app, it may be able to read and create user data on the device. In the Android Application Model, an app can be launched directly from the Home screen or invoked by another app. These two characteristics (it can read or create private data and it can be invoked by another app through an Intent — Chapter 3) make every app — including yours — a potential security risk. This is because your app, if it has access to private data and can be invoked by another (malicious) app, can be forced to reveal this data. Creating private data is a problem in itself. If your app creates private data and leaves it on the device in an insecure manner, a malicious piece of code (such as another app) can read it.

  • Mobile devices have less ability to protect themselves than desktop computers do. Even though mobile devices are exposed to a wider set of vulnerabilities than desktop computers are, mobile devices are less able to protect themselves because the techniques and best practices used to protect desktop computers often are not feasible on mobile devices. Even if you believe that an Android device is less powerful than a desktop computer because, obviously, it lacks features such as strong encryption, that's not the whole story. A lack of computing power is no longer the primary issue.

Here are some other reasons that mobile devices are more vulnerable than desktop computers:

  • Small physical form factor: Mobile devices are often easily mislaid or stolen because they're small. Someone with bad intentions can easily disassemble them to reach their internal components, such as memory cards, that contain private information.
  • No user login required: A mobile device typically requires no login or other type of authentication in order to use it. A person who steals a user's device has immediate access to all the information on it and to other systems it's allowed to connect to, such as e-mail. In a related issue, whenever a user accesses a secure site, such as a bank or an employer's internal system, the device — not the user — is often the only entity that has been verified as the trusted party. If the device is stolen, the thief might have full access to the user's secured sites — at least from the time the theft occurs to the time the user discovers and reports it.
  • Weak password protection: If a login is required on a device, the pass word itself can be a security threat. Because of the difficulty to use keyboards on mobile devices, it is a real inconvenience for users to type all the characters needed for long, strong passwords. For this reason, users tend to use shorter, simpler passwords, which makes the device easier to break into. Building complex layers of security into mobile devices and applications is also difficult because mobile users are especially sensitive to the user experience of the devices. Mobile users have been known to reject devices whose user interface is inconvenient to use; worse, users might be inclined to circumvent security features and thereby leave themselves completely vulnerable.
  • Limited screen size that impedes readability: Because of the small screen sizes of mobile devices, URLs that a device might access often aren't completely visible. If a “dangerous” URL is a small variation of a “safe” URL (as commonly happens in phishing attacks), the user is likely not to notice the variation and may provide private information to the malicious site.
  • Environmental distractions: Because users often use mobile devices in crowded spaces, such as buses, or while engaged in other activities, such as walking or driving (a bad idea), they become distracted and give less than optimum attention to security warnings.

    For example, some financial portals show users special, personalized images to verify that they're on legitimate websites. Someone using a desktop in an office setting is likely to notice that this image is missing after being directed to a site that's spoofing the legitimate site. A user on a mobile device, on the other hand, is likely to be distracted and not notice the missing image because of simultaneously having to navigate the interior of a shopping mall or attempt to maintain balance on a speeding train.

image When your application is demonstrably safe, secure, and useful, it becomes an application that people trust and hence want to buy, download, and install. While the reliable, high-performing usefulness of an application is certainly a significant factor in establishing trust (trust happens as a side-effect of the app demonstrating it can “get the job done well”), security plays the largest role in establishing trust.

Looking at Security Holistically

An application developer wondering how to provide application security typically starts by considering specific (but random) topics such as types of encryption and password-based login.

However, as an app developer, you must first define the app's threat model, which defines the kinds of attacks the app must expect to handle, the assets that must be protected, and the likely degree of loss if those assets are violated or stolen. (See the later section “Defining the Threat Model for an Android Application.”)

After you have defined the threat model, you need to identify the specific techniques to handle threats. Security techniques can be grouped in the following functional categories:

  • Authentication: This includes techniques for validating and identifying who or what is using the system. Authentication may be done through a username/password scheme (like in Tic-Tac-Toe), or you can get very sophisticated and even use biometrics — such as fingerprint or retinal scans! Authentication is a key need in secure systems. If you can't validate and identify the user, then access control, audit trail, and non-repudiation become impossible.
  • Access control: Manage who has access to which capabilities or data. Now that you know (through authentication) who the user is, you should only allow him to do what he is permitted to do.
  • Audit trail: This is the concept of keeping track of who did what in the system. This is typically achieved by logging.
  • Data integrity: This is ensuring that data doesn't become corrupted or harmed. An audit trail will help here, and so will access control. Also in this category are techniques that use checksums that can be used to test whether a piece of data has been inconsistently modified.
  • Non-repudiation: This is ensuring that no user or agent can deny doing something after he (or it) has done it.

Another (related) classification of security techniques is defined by the roles that the above security techniques can play in implementing a secure system. There are four roles, as follows:

  • Resistance: This is making the loss more difficult to occur. Authentication, access control, and data integrity certainly help make the system resistant to attack.
  • Detection: This is determining that a loss or breach has taken place, so that the system can start to protect itself against further breaches or limit the extent of the breach.
  • Mitigation: This is limiting the degree of loss or breach that takes place.
  • Recovery: This is helping the user to recover from a loss, such as by recovering the data from a backup.

Use both the lists to guide you in finding out how to address the attacks the system is likely to face. This systematic approach can lead to much better protection of your app than does simply adding a few ad hoc security techniques. Incidentally, the set of threats the system is likely to face, the probabilities of the threats succeeding, and the losses that are likely to happen if the threats succeed are collectively known as the “threat model” for a system. We explain the threat model, and how to define it, in the next section.

Defining the Threat Model for an Android Application

To define the threat model, this section describes what types of Android vulnerabilities you have to (and don't have to) deal with.

On the good side, because Android is a privilege-separated operating system. This means that — because it runs on Linux — every application runs under its own user ID and group ID. In other words, applications run separately from each other and the system. Finally, whenever an application is uninstalled, all its private data (including preferences and SQLite databases) is removed. Many risks are therefore eliminated and do not need to be included in the threat model.

On the bad side (it's not the fault of Android, however), after your app has been downloaded to a device, virtually every one of its characteristics can be looked up by an attacker, because the .apk file can be parsed and all its separate components extracted, including the manifest file, executable code, resources, and images. The source code can then be decompiled (reconstructed) from the executable code and examined for useful information such as which algorithms are used and which strings represent user IDs and passwords. As you might imagine, implementing “security by obscurity” — that is, relying on the system being safe because no one knows anything about it — simply isn't possible. You have to assume that an attacker knows every detail about your app and then try to protect it.

Your application can become a security risk in six ways, for example, if you

  • Leave private data in files on the device and its SD card: Other, unauthorized and malicious, software may be able to read the files.
  • Use SQLite databases in a manner vulnerable to database hacking techniques: An example is a SQL injection — which we explain later.
  • Allow other, unauthorized, apps to gain access to private data by using your app: Remember that your app can be launched from another app. If your app is a security risk, it can be exploited by other malicious apps. Even built-in Android apps — such as the browser — can be a security risk. A malicious app may access a malicious website via either the built-in browser or the underlying WebView class (Chapter 10) and download a virus or other malware without the user realizing it.
  • Leave private information in a human-readable form in your source code: Examples are hard-wired or “special” user IDs (that provide a system-level, or higher, degree of access to certain data) and passwords or encryption keys.
  • Rely on security by obscurity, such as using simple algorithms for generating keys or encrypting data: You must assume that your app code isn't private and that, after your code is read, any security measure you've applied can be broken.

The following sections look systematically at how to address these threats.

Understanding the Android Security Model

image The security threat in your app lies in malicious code — or a malicious user — taking advantage of the capabilities granted to your application.

Let's start by looking at how your app gains those capabilities. Android's privilege model (the rules by which capabilities are granted to applications) is designed so that no application can, by default, give permission to do anything that can adversely affect other apps or the operating system. Essentially, every app runs in its own sandbox (for example, its own address space in memory, or its own processes, threads, and space on the file system). If your app needs to operate outside this sandbox, such as by launching another app, by using some system functionality, or by sharing resources with another app, it must explicitly ask for permission from the Android framework.

All Android applications (specifically the .apk files that are installed on the device) must be signed using a certificate that identifies the author of the application. Self-signing certificates are perfectly legal — certificates don't have to be signed by a signing authority that verifies your identity. Android just wants to be able to uniquely differentiate you from everyone else.

For this reason, you can ask for a couple different kinds of permissions:

  • First, you can request that two applications share the same user ID, thereby sharing access to each other's files and SQLite databases. Note that only two applications requesting to share user IDs have to be signed with the same signature in order for their request to be granted. To see how it's done, visit http://developer.android.com/guide/topics/manifest/manifest-element.html#uid.
  • Second, your Android app must (in its manifest file) explicitly ask for permission for every protected service it needs on the device. These protected services range from straightforward, such as accessing locations, to esoteric, such as “using SurfaceFlinger low-level features” (which gives your app fine-grained control of how objects are placed on the frame buffer — a data structure that mirrors the device display). At the time the application is installed, the installer presents the list of permissions that the app is requesting and asks the user to approve or reject them, as shown in Figure 9-1. If the user rejects any permission, the installer on the device will not install the app. Also, if the app does not request these permissions it will not be able to use these services (although the parts of the app that do not use these services will still work).

A particular permission can be enforced at a number of places during your app's operation:

  • When a call is made to a system function: To prevent an unauthorized invocation
  • When starting an activity: To prevent an unauthorized application from launching the activity of other applications
  • When sending or receiving broadcasts: To determine who can receive a broadcast or send one to you
  • When accessing, and operating on, a content provider: To prevent an unauthorized app from accessing the data in the content provider
  • When binding to, or starting, a service: To prevent an unauthorized application from using the service

Figure 9-1: Approving requested permissions for the popular game Angry Birds.

images

The following XML snippet shows examples (from the Tic-Tac-Toe application) of requesting permission to use the Internet, access the network state, find both coarse and fine locations, and read contacts from the built-in Contacts application. You can see the complete list of permissions at http://developer.android.com/reference/android/Manifest.permission.html. Note that this list isn't static but, rather, grows in each Android release. Neither does it contain the list of custom permissions defined by you (see the entry containing LAUNCHACTIVITY shown in the XML block below).

<uses-permission android:name=“android.permission.READ_CONTACTS” /> 
<uses-permission android:name=“android.permission.INTERNET” />
<uses-permission android:name=“android.permission.ACCESS_NETWORK_STATE” />
<uses-permission android:name=“android.permission.ACCESS_COARSE_LOCATION” />
<uses-permission android:name=“android.permission.ACCESS_FINE_LOCATION” />
<uses-permission
       android:name=“com.wiley.fordummies.androidsdk.tictactoe.LAUNCHACTIVITY” />

image Note carefully where the <uses-permission> … </usespermission> element is placed in the AndroidManifest.xml file (it must be outside the application block and inside the manifest block)!

In the preceding chunk of code, you can see that the last permission appears to be specific to the Tic-Tac-Toe application — and it is. In addition to requesting predefined system permissions, apps can define their own permissions. To define and use custom permissions, these three steps must take place:

  1. These permissions must be defined by the app developer by using <permissions> … </permissions> elements in the manifest file. Here's an example from the Tic-Tac-Toe activity:
    <permission
       android:name=“com.wiley.fordummies.androidsdk.tictactoe.LAUNCHACTIVITY”
       android:label=“Launch Tic-Tac-Toe Activity”
       android:description=“@string/permission_launch_activity”
       android:protectionLevel=“normal”
    />

    image Note carefully where this element is also placed in the AndroidManifest.xml file (outside the application block and inside the manifest block). Also, the complete list of attributes in the permission element is shown at http://developer.android.com/guide/topics/manifest/permission-element.html.

  2. The component (an activity or a service) that wants to declare the need for the permission must do so in its android:permission attribute. Here's an example from the Login activity in Tic-Tac-Toe:
    <activity
        android:name=“.Login”
        android:label=“@string/app_name”
        android:launchMode=“standard”
        android:screenOrientation=“portrait”
        android:permission=
            “com.wiley.fordummies.androidsdk.tictactoe.LAUNCHACTIVITY”
    >
  3. The using package must request this permission (we showed you how to request permissions a few paragraphs earlier):
    <uses-permission
     android:name=“com.wiley.fordummies.androidsdk.tictactoe.LAUNCHACTIVITY”/>

    image This request is needed by the package in which the activity itself is located. Any separate package that has applications that will invoke the Login activity must (obviously) also request this permission.

The Android framework also uses a permissions-based scheme to protect content providers. Note that the Tic-Tac-Toe application must declare the need for the following permission to be able to read information about your contacts (and send them your scores):

<uses-permission android:name=“android.permission.READ_CONTACTS”/>

Finally, we give you some techniques in the remainder of this section to help you debug permission errors.

If an application fails because of a permission error, you see an entry like the following in the logcat window (it's one long line, but we indented it here to improve readability):

02-28 12:48:00.864: ERROR/AndroidRuntime(378):
    java.lang.SecurityException: Permission Denial: starting Intent {
        act=com.wiley.fordummies.androidsdk.tictactoe.Login 
        cmp=com.wiley.fordummies.androidsdk.tictactoe/.Login }
    from ProcessRecord{407740c0
        378:com.wiley.fordummies.androidsdk.tictactoe/10033} (pid=378,
            uid=10033)
    requires
        com.wiley.fordummies.androidsdk.tictactoe.permission.LAUNCHACTIVITY

The key string in this example is, of course, java.lang.Security Exception. The following lines (also from logcat) indicate that the exception is being thrown from the SplashScreen activity when it is trying to start the Login activity:

02-28 21:04:39.758: ERROR/AndroidRuntime(914):at
    com.wiley.fordummies.androidsdk.tictactoe.SplashScreen$1.run
        (SplashScreen.java:36)

You use the next technique to install the .apk on either an emulator or a device, find the directory by using the adb executable supplied with your Android distribution, and open a shell, cmd, or terminal window in that directory. Type this line:

./adb shell pm list permissions

You will see the text shown below, with your custom permission (LAUNCHACTIVITY) nestling in it:

permission:android.permission.INTERNAL_SYSTEM_WINDOW
permission:android.permission.MOVE_PACKAGE
permission:android.permission.READ_INPUT_STATE
permission:com.google.android.providers.settings.permission.READ_GSETTINGS
permission:android.permission.REBOOT
permission:android.permission.STATUS_BAR
permission:android.permission.ACCESS_DOWNLOAD_MANAGER_ADVANCED
permission:android.permission.STOP_APP_SWITCHES

permission:android.permission.MANAGE_APP_TOKENS
…
permission:com.wiley.fordummies.androidsdk.tictactoe.LAUNCHACTIVITY
…
permission:android.permission.SET_ACTIVITY_WATCHER
permission:android.permission.BACKUP
permission:android.permission.SET_TIME
permission:android.permission.STATUS_BAR_SERVICE
permission:android.permission.PERFORM_CDMA_PROVISIONING
permission:android.permission.INSTALL_PACKAGES
permission:com.google.android.apps.maps.permission.C2D_MESSAGE
permission:android.permission.CALL_PRIVILEGED
permission:android.permission.CHANGE_COMPONENT_ENABLED_STATE
permission:android.permission.WRITE_GSERVICES
permission:android.permission.BIND_WALLPAPER

Finally, we show you what happens if you put your permission entry in the wrong place. The following lines are shown in logcat if the LAUNCHACTIVITY permission declaration is at the wrong level (for example, inside the activity element):

02-28 16:53:09.838: DEBUG/PackageManager(77):   Permissions: com.wiley.
               fordummies.androidsdk.tictactoe.LAUNCHACTIVITY

02-28 17:04:18.888: WARN/PackageParser(77): Unknown element under <application>:
               permission at /data/app/vmdl1654102309.tmp Binary XML file line
               #11

02-28 17:04:20.438: WARN/PackageManager(77): Unknown permission com.wiley.
               fordummies.androidsdk.tictactoe.LAUNCHACTIVITY inpackage
               com.wiley.fordummies.androidsdk.tictactoe

Protecting SQLite Databases

The primary security concern created by using SQLite databases is the SQL injection attack, in which the attacker is able to force the system to execute his own query and return data that he does not have authorization to access. Suppose that in response to aprompt for a person's name, you enter Bob on the form and the application returns Bob's e-mail address by looking up a table using this query:

Select e-mail from user_information where name = Bob

Before software developers understood SQL injection attacks, they (the software developers) would use string concatenation to create queries. Thus, for the example shown above, a string was programmatically created that looked exactly like the query shown in the preceding example. This string was then sent to the database to execute.

But note what happens if you enter Bob; select table_names from user_tables in the entry field of the user interface: The query string becomes

Select e-mail from user_information where name = Bob;
           select table_names from user_tables

Most SQL databases would execute both queries, returning not only Bob's e-mail but also the names of the programmer-defined tables in the system. (The user_tables view is standard in most databases that contain the names of all user-defined tables.) Armed with this information, an attacker can inject all kinds of queries into a database to read all the other tables — even the system tables.

Defending against this type of attack is a straightforward process. The trick is to use what are known as “bind” variables. We do this in the Tic-Tac-Toe application. Look at the following lines that were extracted from the file DatabaseHelper.java:

private static final String TABLE_NAME = “Accounts”;
…
private static final String INSERT = “insert into ” +
    TABLE_NAME + “(name,password) values (?, ?)” ;
…
public DatabaseHelper(Context context) {
…
    this.insertStmt = this.db.compileStatement(INSERT);
…
}
…
public long insert(String name, Stringpassword) {
    this.insertStmt.bindString(1, name);
    this.insertStmt.bindString(2,password);
    return this.insertStmt.executeInsert();
}

The constant INSERT defines a template for the database query, where the two question marks (?) define locations where data can be inserted. The this.insertStmt = this.db.compileStatement(INSERT) statement is compiling the query into an internal data structure, and the insert(…) method assembles the query from the parameters that are sent to it. If someone attempted the SQL injection attack from the preceding example (and added a query to the Password field), the query would look like the following line, which creates an odd password but does nothing harmful:

insert into Accounts (name,password) values (‘Bob’, ‘<password>; select table_
               names from user_tables’)

Minimizing the Security Footprint of Your App

After you know how the Android security model works, we have to tell how to leverage it for security purposes. To begin with, follow the principle of least privilege and give your app the least possible level of capability so that if someone uses it in an unauthorized manner, the least amount of damage will be done. If your app needs only a coarse location (at the city level), for example, don't give it fine location capability. If your app doesn't need to save external files, don't write it so that it can save them. If your app doesn't need complete access to a content provider, give it access only to the Universal Resource Identifiers (URI) it needs.

You should also limit your app's accessibility with respect to other applications (those not developed by you). If certain activities in your app are security risks and are not to be started by other activities, declare custom permissions for these activities. Then if a malicious app wants to use your app, it must declare its true intentions by requesting these custom permissions. The user then has a chance to realize this malicious intent and refuse to accept the request.

Before we end this section, and so as to connect it with the security categories we covered in the earlier section, note that the above are mitigation tactics — they help you minimize the damage caused by a breach.

Going Beyond Permissions

The appropriate use of permissions can go a long way toward helping to make your apps secure. The following list describes some additional steps you can take to make your applications more secure (the categories the strategy belongs to are shown in parentheses):

  • Do not hard-wire secrets (such as special passwords) into your code. Java code can be easily decompiled to reveal this type of constant in your code. (Resist)
  • Encrypt any files that hold sensitive information. This advice isn't specific to Android — a good book on Java security (such as Java Security Solutions, by Rich Helton and Johennie Helton (John Wiley & Sons, Inc.)) should show you how. Note that you must keep hidden (from anyone who might hack your app's source code) the key you use to encrypt the file itself. (Resist, Data Integrity)
  • Back up your data so that you can restore it if your device ever gets hacked and its data corrupted. The Android SDK provides an API to a service that can back up your app's data on Google's servers. We don't include a description of this service in this book because of certain Google limitations (no guarantee that the service will remain free and no guarantee of future support, for example). (Recover)
  • Log what your app does (such as the methods it calls) to a log file (and don'tput sensitive, user-supplied information in the file or forget to encrypt it). In particular, be sure to log all permission exceptions. The log file can also be used to determine whether an attack was made, and by whom. (Audit Trail, Non-Repudiation, Detect)
  • For especially sensitive operations or requests for data, don't rely only on permissions. Add code that alerts the user to the sensitive access being requested and asks for user confirmation. (Resist, Access Control)
  • Keep intent filters to sensitive activities specific so that attackers cannot launch this type of activity by sending out high-level intents. Validate intent parameters when they're received by activities, and don'tput sensitive data (such as passwords) into an intent that's being used to start an activity. Malware can register higher-priority intent filters and have a user's sensitive data sent to it instead. (Resist, Access Control)
  • Of course, set up your user interface so that when sensitive data (such as a password) is entered, it's masked. You probably can tell where in the Tic-Tac-Toe application we didn't do this (for a hint, look at the Login activity) and where we did mask the data entry (look at the Account activity). (Resist, Authentication)
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.12.136.186