Security in Android apps Falco Peijnenburg (3749002) August 16, 2013 Abstract Apps can be released on the Google Play store through the Google Developer Console. The Google Play store only allows apps that are signed by a private key owned by the developer. The developer is responsible for creating and maintaining their own certificate. Keys can be generated with the Keytool program. The generated keys are stored in a keystore file, which should be kept secret. A leak is, however, not immediately disastrous since the keystore is encrypted. The security of an Android installation package cannot be assured when there are two files in it with duplicate file names. Apps are restricted in their access and have to ask for explicit consent to access personal data. The permissions system that takes care of this system can, however, be worked around in many ways. 1 Introduction Android apps are written in Java. They are compiled to a Android Application Package File (APK). APK files contain compiled code and various other files, compressed in zip format. These APK files can be published over the Google Play store. After publishing an app, people can download and install it. Releasing apps on the Play store cannot be done without the necessary security measures, and once an app has been released it could pose a risk to the end user s privacy. The next section describes how apps are released on the market. The third section details the application signing process. The fourth section describes how keys and certificates are managed. The fifth section takes a closer look at the privacy in apps and the last section concludes this paper. 2 Releasing apps on Google Play To publish an app on the Google Play store, the developer needs access to the Developer Console. The developer console is a web based set of tools that allows the developer to publish and monitor their apps. Once an app has been published the developer console provides insight in the usage, reviews and crash reports. To publish one or more apps on the Play store, the developer is required to pay a one time fee of $25 U.S. dollars (as of June 13th 2013) [8]. 1
An app does not have to be released on the Play store. Besides the play store there are various other (unofficial) markets from which an end user can install apps. The end user can even choose to install an app directly from a website or e-mail. Apps distributed by means other than the Google Play store have a higher risk of containing malicious code that could, for instance, send private data to advertisement companies. This is why Android does not allow the installation of apps from unknown sources by default. A simple toggle in the settings menu disables this restriction. 3 Application signing Every published app needs to be signed. This is done with an asymmetric encryption algorithm. When building a debug version of the app, the signing is done automatically with a debug key. The public/private keypair of the debug key is stored in the Integrated Developer Environments (IDE) that allow the developer to create and build the application. This implies that the private debug key is publicly available. The debug key does not provide any security of verification. The only reason for it to exist is to facilitate the development process. After all, it can be cumbersome to have to sign every test build. The developer could also choose to create their own debug key. Since debug keys prove no authenticity, the Developer Console does not allow developers to upload apps that are signed with them. Instead, the developer is required to create their own key pair and certificate. The certificate has to meet strict requirements [7]: 1. it has to be encrypted with either RSA or the ElGamal based Digital Signature Algorithm (DSA) [10] 2. the certificate has to be valid until at least 22 October 2033 3. it has to represent the person or company that created it A certificate that is valid for twenty years poses some risks. The chance of leaking the private key increases as it is used for a longer period of time. When it does get leaked, it could potentially be abused for a long time. From a security point of view it might be better to decrease the validity period of the certificate. However, each app has its release certificate permanently associated with it; it cannot be changed. The same certificate is used when an app is updated. The reason why the certificates are permanently associated to apps is to prevent a man in the middle from replacing the genuine app with a malicious one that is signed with a different private key. This way, end users will have to uninstall the app and install the version with the different certificate to get the malicious version, as the app cannot be installed as an update. Expired certificates are also not accepted, which means that apps cannot be updated after the expiry date of the certificate. This means there has to be a balance between the security of a certificate and its usability. Google advise a validity period of more than 25 years [7]. 2
The certificate does not have to be verified by a certificate authority. This has several reasons. Registering a key with a certificate authority is a huge step can significantly slow down the release progress and thus be a deterrent for less experienced developers. A second reason is that the owner of a certificate is the developer s Google account that uploads the app to the Developer Console. The developer is trusted to be the only person or company that has access to the Google account. Consequently, each used certificate is trusted to be held by the developer. The third reason is each released app having its certificate permanently linked to it. This means that apps cannot be updated even if someone were to get unauthorized access to a developer s Google account, since they would have to sign it with a key they do not possess. 4 Key management The Google Play store uses the certificate of an app for its identification. The Play store will know when a new version of a previously published app is uploaded when the certificates (and package names) match. This means that the developer is in possession of one key pair for each app they publish. The Google Play store accepts any signed non-debug certificate. This implies that the developer has full responsibility over the security and validity of their certificates. 4.1 Generating keys The developer of an app is responsible for generating the key pair and certificate. They can be generated with a program called keytool [13]. This is a command line based application that can be downloaded by the developer. The keytool provides a variety of features for generating keys and certificates. A public/private keypair can be generated by running the keytool with the -genkey parameter. To generate a key, the keytool needs the following information: 1. The asymmetric encryption algorithm (either RSA or DSA) 2. A human readable alias for the key pair (so it can be recognized) 3. The key length in bits 4. The signature algorithm. The signature is created by encrypting the hash of the certificate with the private key. The signature algorithm is a combination of a hash function (commonly MD5 or SHA1) with the chosen asymmetric encryption algorithm 5. The validity of the certificate in days. 6. The file in which the certificate and keys will be stored 7. The password to (symmetrically) encrypt the file in which the keys and certificate are stored 3
The keytool creates a keystore file which stores the keys. A keystore is a database that can hold more one or more key pairs and references of trusted certificates. The private key of each key pair is encrypted with a password. The password is human readable, with usually a very low entropy. Since it cannot be directly used as an encryption key, the password is hashed (with MD5 by default [12]). This hash is then used by the encryption algorithm (3DES by default), which encrypts the private key. 4.2 Attacks Since the private keys in the keystore file are encrypted, leaking the keystore file will not have an immediate disastrous effect. However, an attacker could try to brute force the private keys. This can be done in two ways: 1. Hash generated passwords and try to decrypt the private key with the hash 2. Skip the passwords and enumerate all possible hashes Both brute force methods have up- and downsides. Generating passwords and hashing them can be slow. Besides, it will take longer to iterate over the hash space, since several passwords can hash to the same digest. However, this method could get very quick results if the password is weak. After all, an intelligent brute force program tries the most common passwords first. The other brute force method skips the hashing of passwords and attempts to crack the encryption immediately. This method can attempt more keys per second, since it requires less work. It is also complete: it can iterate over the entire key space without the chance of hitting duplicates. Assuming 3DES with a key length of 168 bits. With a meet in the middle attack, the amount of required encryptions can be reduced to 2 112 [11]. A brute force attack would have to try 2 112 keys. A computer that can try one hundred billion keys per second would take 2 112 5.19 1022 100, 000, 000, 000 seconds, which is about 1.64 10 15 years. By that time the certificate will most likely have become invalid. When the keystore has been cracked, the attacker will gain access to one or more private keys. These private keys can be used to sign a malicious version of the app. When installed, this app will replace the app from the original author, making it look like an update. The malicious version of the app can be only be released to the Play store when the attacker also has the login credentials of the developer on the Developer Console. In this situation the developer is still not completely powerless. Once the developer finds out their private key was compromised, they can remove the app from the Play Store and upload a new version of the app that is signed with a different key. 4
5 The Bluebox attack The certificate of an application contains a hash of the APK file. This hash is calculated with a function H. This hash is encrypted with the private key x of the developer. This is called the signature. Signature = Encr x (H(AP K)) During the installation this signature is verified with the public key y as follows: Decr y (Signature) = H(AP K) The installation is aborted when this assertion fails. The verification of the signature is required to assure the integrity of the package. A man in the middle is unable modify the APK file since the hash of its content would differ from the one in the signature. Modifying an app in such a way that the hash fingerprints match is considered infeasible. Yet researches at the Bluebox company have found a way to circumvent this security. [3] 5.1 The exploit The problem lies with the function that verifies the signature of an APK file (V ) and the function that actually unpacks its contents (U). V is calculated by iterating over the files in the APK and running their contents through a hash algorithm H. V Decr y (Signature) =? H(file1 + file2 + file3 +...) Someone with malicious intent could insert a malicious file in the APK package by using Google s APK tool and other zip tools. This malicious file has the exact same name as some other file in the APK. The signature of the APK file is left in, but will have become invalid as the APK was modified. However, due to a bug in V [2], only one of the two files are iterated over when calculating the hash. This means that the malicious file is skipped when calculating the hash. This (false) hash matches the one in the signature, causing the app to be considered valid. U on the other hand, is implemented in C [4]. Whereas V (implemented in Java) skips the malicious file and iterates over the genuine file, U finds the malicious file and skips the genuine file when unpacking. As a result, the malicious file is installed on the device while the original is discarded. 5.2 Consequences With this exploit, a man in the middle can put malicious code in any APK file while tricking the Android device into thinking the signature is still valid. The malicious version of the app can be installed as an update to the genuine app, allowing malicious code to be run without being noticed by the end user. This exploit can also be used to create a rootkit. The press release from Bluebox [3] shows a screenshot of a maliciously updated system app. The malicious version of the app inherits the root privileges that the original system app used to perform its tasks. Removal of this malicious software is easy now the exploit is known, but it would not have been if it remained unknown. 5
The most important lesson here is that certificates and signatures, even when considered cryptographically secure, can be rendered useless by an exploit in the code that uses them. The part of the APK file that Android checks against the certificate is indeed valid and signed by the owner of the certificate. The failure of verifying the entire APK file and the difference between U and V compromise the security that the certificates and signatures would otherwise provide. 6 Privacy in apps Android devices often contain personal information, such as the phone number, contacts and other personal files. Android apps should not be able to retrieve any personal information without explicit consent of the end user. On the other hand, apps might need this personal information to perform the tasks they were designed for. For instance, a contacts manager app needs access to the contacts. For this purpose, Android has implemented a permissions system [5]. At the time of writing, there are 130 permissions [6]. They range from connecting to the internet to accessing the exact location through GPS. 6.1 Using functions that require permissions Android provides an Application Programming Interface (API) that allows developers to make their app interact with the Android operating system. Many classes and methods in this API can be called without requiring any permissions. Some methods, however, do require one or more permissions before they can be called. One clear example is the TelephonyManager.getLine1Number() method which returns a string that contains the phone number of the device running the app. To run this method, the app requires the READ PHONE STATE permission. When this method is called without this permission, a Java exception is thrown: Figure 1: The exception that is thrown when trying to retrieve the phone number without permission Leaving this exception uncaught will crash the app with just the error Unfortunately, app name has stopped. 6.2 Getting permissions Each app defines its permissions in an XML file called the Android Manifest. When using the Eclipse developer environment, privileges can be added through the user interface. Figure 6.2 on the next page shows how permissions are requested in the Android manifest file. 6
Figure 2: Requesting permissions for GPS location, reading phone information and enabling the flashlight Before installing an app, the user is warned about the permissions it requests. The user has to explicitly grant these permissions. Once the app has been installed, it does not ask for the permissions again unless an update of the app requires new permissions. 6.3 Problems with permissions There are several major problems with the permissions system. Many of problems hurt usability, other problems allow apps to bypass the permissions system altogether. Here follows an incomplete, yet revealing list of problems the permissions system has: Not clear It is not unusual for an app to request a dozen permissions. In many cases, apps ask for permissions that look suspicious, but are, in the end, used for genuine purposes. One example is the Guardian live news app [9], which requires the permission to find social network accounts on the device. This information could be sent to a server to be stored or even sold to governments or advertisement companies. However, it actually uses this permission to allow users to share articles to their friends and family on social networks. Some developers explain their use of permissions in the description of the app. Some (like the Guardian) explain it on their website. Nevertheless, even with an explanation the end user has to trust the developer not to abuse these permissions. Often ignored The average end user cares about privacy as long as it is not their responsibility to maintain it. Permissions are often granted without scrutiny. Partially because of the first problem, but also because it takes effort to take a closer look at the permissions an app uses. The Google Play store is designed to be able to install an app within seconds. This is why accepting the permissions is but one extra click. End users are not encouraged to mind their privacy when installing apps. New permissions in an update Popular app developers can afford to release an update that asks for more permissions. Sometimes these permissions are needed for newly implemented features, but these new permissions can also be abused. The latter situation confronts the end users (who notice) with a dilemma. They could either continue using their app with a risk or uninstall the app and lose the functionality it provided. Since losing the functionality is immediately noticeable, taking the risk is often the preferred choice. There is however a third choice: there are apps on the market that can restrict individual permissions of other apps. The problem with these apps is that they require administrator access (root) to the device, which, depending on the device, can be difficult to obtain. 7
Privilege escalation attack There are ways for apps to get personal information without requiring the permissions. This is called a privilege escalation attack. One way to do this is to send a malicious message to an app that does have permissions to pry out a response from it that contains personal information (as described in [1]). Another way is to find an exploit in the Android operating system to gain access to the root user, One example is the bluebox attack. The root user is the user account that has full access to the device. An app that gains access to this root account is called a rootkit. Rootkits can not only gather any information from the device without the user noticing, it could also hide itself from the user and make it nearly impossible to be removed. 7 Conclusion Android apps can be published over the Google Play Store or through other means. When publishing through the Play store, the app needs to be signed. The certificate is to be created by the developer, but has to meet specific demands about encryption, validity and ownership. Certificates do not need to be verified by a certificate authority. The key pair and certificate can be generated with the Keytool program, which stores them in a Keystore file on the developer s computer. The responsibility lies with the developer to keep this Keystore file secret and secure. An attacker could pose as the developer and update the app once they are in possession of the private key. When not in possession of the private key, the attacker could perform a Bluebox attack to modify an APK file without needing to change the signature. Ideally, apps cannot access personal information from the owner of the device on which it is installed. When such access is needed to provide functionality, the app will ask for permission before installation. These permission requests are, however, often ignored. On top of that there are exploits that bypass the permissions system altogether. End users are encouraged to always be alert for suspicious apps. References [1] K. Casteel, O. Derby, and D. Wilson. Exploiting common intent vulnerabilities in android applications. http://css.csail.mit.edu/6.858/2012/projects/ocderby-denniswkcasteel.pdf, December 2012. [2] G. Condra. Remove support for duplicate file entries. http://review.cyanogenmod.org/#/c/45251/, February 2013. [3] J. Forristal. Uncovering android master key that makes 99 http://bluebox.com/corporate-blog/bluebox-uncovers-android-masterkey/, July 2013. [4] J. Freeman. Exploit (& fix) android master key. http://www.saurik.com/id/17, July 2013. 8
[5] Google. Permissions. http://developer.android.com/guide/topics/security/permissions.html, June 2013. [6] Google. Manifest.permission. http://developer.android.com/reference/android/manifest.permission.html, June 2013. [7] Google. Signing in release mode. http://developer.android.com/tools/publishing/appsigning.html#releasemode, June 2013. [8] Google. Google play developer console. https://play.google.com/apps/publish/signup/, June 2013. [9] T. Grinsted. Guardian android app: being open about permissions. http://www.guardian.co.uk/mobile/insideguardian/android-apppermissions, April 2013. [10] D. W. Kravitz. Digital signature algorithm, July 27 1993. US Patent 5,231,668. [11] S. Moore. Meet-in-the-middle attacks. http://stephanemoore.com/pdf/meetinthemiddle.pdf, November 2010. [12] Oracle. Java TM cryptography architecture sun providers documentation. http://docs.oracle.com/javase/6/docs/technotes/guides/security/sunproviders.html, 2011. [13] Oracle. Keytool man page. Oracle, http://docs.oracle.com/javase/6/docs/technotes/tools/windows/keytool.html, 2013. 9