Android Securities
Android Securities
Android Securities
Security guidelines
Android has built-in security features that significantly reduce the frequency and impact
of application security issues. The system is designed so that you can typically build
your apps with the default system and file permissions and avoid difficult decisions
about security.
The following core security features help you build secure apps:
● The Android application sandbox, which isolates your app data and code
execution from other apps.
● An application framework with robust implementations of common security
functionality such as cryptography, permissions, and secure interprocess
communication (IPC).
● Technologies like address space layout randomization (ASLR), no-execute (NX),
ProPolice, safe_iop, OpenBSD dlmalloc and calloc, and Linux mmap_min_addr
to mitigate risks associated with common memory management errors.
● User-granted permissions to restrict access to system features and user data.
● Application-defined permissions to control application data on a per-app basis.
It's important to be familiar with the Android security best practices on this page.
Following these practices as general coding habits help you avoid inadvertently
introducing security issues that adversely affect your users.
Data storage
The most common security concern for an application on Android is whether the data
that you save on the device is accessible to other apps. There are three fundamental
ways to save data on the device:
● Internal storage
● External storage
● Content providers
The following sections describe the security issues associated with each approach.
Internal storage
By default, files that you create on internal storage are accessible only to your app.
Android implements this protection, and it's sufficient for most applications.
Avoid the deprecated MODE_WORLD_WRITEABLE and MODE_WORLD_READABLE
modes for IPC files. They don't provide the ability to limit data access to particular
applications, and they don't provide any control of data format. If you want to share your
data with other app processes, consider using a content provider instead, which offers
read and write permissions to other apps and can make dynamic permission grants on
a case-by-case basis.
External storage
Files created on external storage, such as SD cards, are globally readable and writable.
Because external storage can be removed by the user and also modified by any
application, only store non-sensitive information using external storage.
Perform input validation when handling data from external storage as you would with
data from any untrusted source. Don't store executables or class files on external
storage prior to dynamic loading. If your app does retrieve executable files from external
storage, make sure the files are signed and cryptographically verified prior to dynamic
loading.
Content providers
Content providers offer a structured storage mechanism that can be limited to your own
application or exported to allow access by other applications. If you don't intend to
provide other applications with access to your ContentProvider, mark it as
android:exported=false in the application manifest. Otherwise, set the android:exported
attribute to true to let other apps access the stored data.
When creating a ContentProvider that is exported for use by other applications, you can
specify a single permission for reading and writing, or you can specify distinct
permissions for reading and writing. Limit your permissions to those required to
accomplish the task at hand. Keep in mind that it’s usually easier to add permissions
later to expose new functionality than it is to take them away and impact existing users.
If you are using a content provider for sharing data between only your own apps, we
recommend using the android:protectionLevel attribute set to signature protection.
Signature permissions don't require user confirmation, so they provide a better user
experience and more controlled access to the content provider data when the apps
accessing the data are signed with the same key.
Content providers can also provide more granular access by declaring the
android:grantUriPermissions attribute and using the
FLAG_GRANT_READ_URI_PERMISSION and
FLAG_GRANT_WRITE_URI_PERMISSION flags in the Intent object that activates the
component. The scope of these permissions can be further limited by the
<grant-uri-permission> element.
When accessing a content provider, use parameterized query methods such as query(),
update(), and delete() to avoid potential SQL injection from untrusted sources. Note that
using parameterized methods is not sufficient if the selection argument is built by
concatenating user data prior to submitting it to the method.
Don't have a false sense of security about the write permission. The write permission
allows SQL statements that make it possible for some data to be confirmed using
creative WHERE clauses and parsing the results. For example, an attacker might probe
for the presence of a specific phone number in a call log by modifying a row only if that
phone number already exists. If the content provider data has predictable structure, the
write permission might be equivalent to providing both reading and writing.
Permissions
Because Android sandboxes applications from each other, applications must explicitly
share resources and data. They do this by declaring the permissions they need for
additional capabilities not provided by the basic sandbox, including access to device
features such as the camera.
Permission requests
Minimize the number of permissions that your app requests. Restricting access to
sensitive permissions reduces the risk of inadvertently misusing those permissions,
improves user adoption, and makes your app less vulnerable for attackers. Generally, if
a permission isn't required for your app to function, don't request it. See the guide to
evaluating whether your app needs to declare permissions.
If possible, design your application in a way that doesn't require any permissions. For
example, rather than requesting access to device information to create a unique
identifier, create a UUID for your application (see the section about user data). Or,
rather than using external storage (which requires permission), store data on internal
storage.
In addition to requesting permissions, your application can use the <permission>
element to protect IPC that is security sensitive and is exposed to other applications,
such as a ContentProvider. In general, we recommend using access controls other than
user-confirmed permissions where possible, because permissions can be confusing for
users. For example, consider using the signature protection level on permissions for
IPC communication between applications provided by a single developer.
Don't leak permission-protected data. This occurs when your app exposes data over
IPC that is available only because your app has permission to access that data. The
clients of your app's IPC interface might not have that same data-access permission.
More details on the frequency and potential effects of this issue appear in the research
paper Permission Re-Delegation: Attacks and Defenses , published at USENIX.
Permission definitions
Define the smallest set of permissions that satisfy your security requirements. Creating
a new permission is relatively uncommon for most applications, because the
system-defined permissions cover many situations. Where appropriate, perform access
checks using existing permissions.
If you need a new permission, consider whether you can accomplish your task with a
signature protection level. Signature permissions are transparent to the user and allow
access only by applications signed by the same developer as the application performing
the permission check.
If creating a new permission is still required, declare it in the app manifest using the
<permission> element. Apps using the new permission can reference it by adding a
<uses-permission> element in their manifest files. You can also add permissions
dynamically by using the addPermission() method.
If you create a permission with the dangerous protection level, there are a number of
complexities that you need to consider:
● The permission must have a string that concisely expresses to the user the
security decision they are required to make.
● The permission string must be localized to many different languages.
● Users might choose not to install an application because a permission is
confusing or perceived as risky.
● Applications might request the permission when the creator of the permission
hasn't been installed.
Each of these poses a significant nontechnical challenge for you as the developer while
also confusing your users, which is why we discourage the use of the dangerous
permission level.
Networking
Network transactions are inherently risky for security, because they involve transmitting
data that is potentially private to the user. People are increasingly aware of the privacy
concerns of a mobile device, especially when the device performs network transactions,
so it's very important that your app implement all best practices toward keeping the
user's data secure at all times.
IP networking
Networking on Android is not significantly different from other Linux environments. The
key consideration is making sure that appropriate protocols are used for sensitive data,
such as HttpsURLConnection for secure web traffic. Use HTTPS over HTTP anywhere
that HTTPS is supported on the server, because mobile devices frequently connect on
networks that aren't secured, such as public Wi-Fi hotspots.
Authenticated, encrypted socket-level communication can be easily implemented using
the SSLSocket class. Given the frequency with which Android devices connect to
unsecured wireless networks using Wi-Fi, the use of secure networking is strongly
encouraged for all applications that communicate over the network.
Some applications use localhost network ports for handling sensitive IPC. Don't use this
approach, because these interfaces are accessible by other applications on the device.
Instead, use an Android IPC mechanism where authentication is possible, such as with
a Service. Binding to the non-specific IP address INADDR_ANY is worse than using
loopback, because it allows your application to receive requests from any IP address.
Make sure that you don't trust data downloaded from HTTP or other insecure protocols.
This includes validation of input in WebView and any responses to intents issued
against HTTP.
Telephony networking
The Short Message Service (SMS) protocol was primarily designed for user-to-user
communication and isn't well suited for apps that want to transfer data. Due to the
limitations of SMS, we recommend using Firebase Cloud Messaging (FCM) and IP
networking for sending data messages from a web server to your app on a user device.
Be aware that SMS is neither encrypted nor strongly authenticated on either the
network or the device. In particular, any SMS receiver should expect that a malicious
user might have sent the SMS to your application. Don't rely on unauthenticated SMS
data to perform sensitive commands. Also, be aware that SMS can be subject to
spoofing and/or interception on the network. On the Android-powered device itself, SMS
messages are transmitted as broadcast intents, so they can be read or captured by
other applications that have the READ_SMS permission.
Input validation
Insufficient input validation is one of the most common security problems affecting
applications, regardless of what platform they run on. Android has platform-level
countermeasures that reduce the exposure of applications to input validation issues,
and we recommend that you use those features where possible. Also, we recommend
using type-safe languages to reduce the likelihood of input validation issues.
If you are using native code, any data read from files, received over the network, or
received from an IPC has the potential to introduce a security issue. The most common
problems are buffer overflows, use after free, and off-by-one errors. Android provides a
number of technologies, like ASLR and Data Execution Prevention (DEP), that reduce
the exploitability of these errors, but they don't solve the underlying problem. You can
prevent these vulnerabilities by carefully handling pointers and managing buffers.
Dynamic, string-based languages such as JavaScript and SQL are also subject to input
validation problems due to escape characters and script injection.
If you are using data within queries that are submitted to an SQL database or a content
provider, SQL injection can be an issue. The best defense is to use parameterized
queries, as discussed in the section about content providers. Limiting permissions to
read-only or write-only can also reduce the potential for harm related to SQL injection.
If you can't use the security features discussed in this section, make sure to use
well-structured data formats and verify that the data conforms to the expected format.
While blocking specific characters or performing character replacement can be an
effective strategy, these techniques are error prone in practice, and we recommend
avoiding them when possible.
User data
In general, the best approach for user data security is to minimize the use of APIs that
access sensitive or personal user data. If you have access to user data, avoid storing or
transmitting it if you can. Consider whether your application logic can be implemented
using a hash or non-reversible form of the data. For example, your application might
use the hash of an email address as a primary key to avoid transmitting or storing the
email address. This reduces the chances of inadvertently exposing data, and it also
reduces the chance of attackers attempting to exploit your application.
If your application accesses personal information such as passwords or usernames,
keep in mind that some jurisdictions might require you to provide a privacy policy
explaining your use and storage of that data. Following the security best practice of
minimizing access to user data can also simplify compliance.
Also, consider whether your application could inadvertently expose personal information
to other parties, such as third-party components for advertising or third-party services
used by your application. If you don't know why a component or service requires
personal information, don’t provide it. In general, reducing the access to personal
information by your application reduces the potential for problems in this area.
If your app requires access to sensitive data, evaluate whether you need to transmit it to
a server or if you can run the operation on the client. Consider running any code using
sensitive data on the client to avoid transmitting user data. Also, make sure that you
don't inadvertently expose user data to other applications on the device through overly
permissive IPC, world-writable files, or network sockets. Overly permissive IPC is a
special case of leaking permission-protected data, discussed in the Permission requests
section.
If a Globally Unique Identifier (GUID) is required, create a large, unique number and
store it. Don't use phone identifiers such as the phone number or IMEI, which might be
associated with personal information. This topic is discussed in more detail in the page
about best practices for unique identifiers.
Be careful when writing to on-device logs. On Android, logs are a shared resource and
are available to an application with the READ_LOGS permission. Even though the
phone log data is temporary and erased on reboot, inappropriate logging of user
information could inadvertently leak user data to other applications. In addition to not
logging PII, limit log usage in production apps. To easily implement this, use debug flags
and custom Log classes with easily configurable logging levels.
WebView
Because WebView consumes web content that can include HTML and JavaScript,
improper use can introduce common web security issues such as cross-site scripting
(JavaScript injection). Android includes a number of mechanisms to reduce the scope of
these potential issues by limiting the capability of WebView to the minimum functionality
required by your application.
If your application doesn't directly use JavaScript within a WebView, do not call
setJavaScriptEnabled(). Some sample code uses this method; if you repurpose sample
code that uses it in a production application, remove that method call if it's not required.
By default, WebView doesn't execute JavaScript, so cross-site scripting is not possible.
Use addJavaScriptInterface() with particular care, because it lets JavaScript invoke
operations that are normally reserved for Android applications. If you use it, expose
addJavaScriptInterface() only to web pages from which all input is trustworthy. If
untrusted input is allowed, untrusted JavaScript might be able to invoke Android
methods within your app. In general, we recommend exposing addJavaScriptInterface()
only to JavaScript that is contained within your application APK.
If your application accesses sensitive data with a WebView, consider using the
clearCache() method to delete any files stored locally. You can also use server-side
headers, such as no-store, to indicate that an application should not cache particular
content.
Devices running platforms older than Android 4.4 (API level 19) use a version of webkit
that has a number of security issues. As a workaround, if your app is running on these
devices, it must confirm that WebView objects display only trusted content. To make
sure your app isn’t exposed to potential vulnerabilities in SSL, use the updatable
security Provider object as described in Update your security provider to protect against
SSL exploits. If your application must render content from the open web, consider
providing your own renderer so you can keep it up to date with the latest security
patches.
Credentials requests
To make phishing attacks more conspicuous and less likely to be successful, minimize
the frequency of asking for user credentials. Instead, use an authorization token and
refresh it.
Where possible, don't store usernames and passwords on the device. Instead, perform
initial authentication using the username and password supplied by the user, and then
use a short-lived, service-specific authorization token.
We recommend connecting to services that are accessible to multiple applications using
AccountManager. If possible, use the AccountManager class to invoke a cloud-based
service and don't store passwords on the device.
After using AccountManager to retrieve an Account, use CREATOR before passing in
any credentials so that you don't inadvertently pass credentials to the wrong application.
If credentials are used only by applications that you create, you can verify the
application that accesses the AccountManager using checkSignatures(). Alternatively, if
only one application uses the credential, you might use a KeyStore for storage.
SSL Pinning
It is a security technique used to enhance the security of network communication by
establishing a trusted connection between a mobile app and a server. It involves
associating a specific SSL/TLS certificate or public key with a server and ensuring that
subsequent connections to that server only accept that specific certificate or key.
By default, when making HTTPS connections, Android devices rely on the built-in trust
store that contains a list of trusted root certificate authorities (CAs). This trust store is
used to validate the server's certificate during the SSL handshake process. However,
SSL pinning goes a step further by explicitly specifying the certificate or public key that
the client expects to receive from the server.
It's important to note that SSL pinning requires careful management and maintenance. If
the server's certificate or public key changes, the app's pinned value needs to be
updated accordingly. Failure to update the pinned value may result in connection
failures or prevent the app from accessing the server.
CertificatePinner certificatePinner
= new CertificatePinner.Builder()
.add("api.github.com",
"sha256/6wJsqVDF8K19zxfLxV5DGRneLyzso9
adVdUN/exDacw=")
.build();
.baseUrl(END_POINT)
.addConverterFactory(GsonConverterFactory.cr
eate())
.client(client)
.build();
SSL (Secure Sockets Layer) pinning involves hard-coding or “pinning” a specific SSL
certificate or its public key within the app. This means that the app will only trust
connections to the server if the presented certificate matches the pinned certificate. This
helps protect against attacks that involve using fraudulent certificates to intercept or
manipulate the communication between the app and the server.