0-Day Deserialization Vulnerabilities in Android
Total Page:16
File Type:pdf, Size:1020Kb
ONE CLASS TO RULE THEM ALL 0-DAY DESERIALIZATION VULNERABILITIES IN ANDROID Or Peles, Roee Hay IBM Security {orpeles,roeeh}@il.ibm.com Abstract I. Introduction We present previously unknown high severity vulnera- bilities in Android. Android is the most popular mobile operating system The first is in the Android Platform and Google with 78% of the worldwide smartphone sales to end Play Services. The Platform instance affects Android users in Q1 2015 [1]. 4.3-5.1, M (Preview 1) or 55% of Android devices Android apps are executed in a sandboxed envi- at the time of writing1. This vulnerability allows for ronment to protect both the system and the hosted arbitrary code execution in the context of many apps applications from malware [2]. The Android sandbox and services and results in elevation of privileges. In this relies on the Linux kernel’s isolation facilities. While paper we also demonstrate a Proof-of-Concept exploit sandboxing is a central security feature, it comes at the against the Google Nexus 5 device, that achieves code expense of interoperability. In many common situations, execution inside the highly privileged system_server apps require the ability to interact. For example, the process, and then either replaces an existing arbitrary browser app should be capable of launching the Google application on the device with our own malware app Play app if the user points toward the Google Play or changes the device’s SELinux policy. For some other website. To recover interoperability, a key aspect of devices, we are also able to gain kernel code execution the Android architecture is Inter-App Communication by loading an arbitrary kernel module. We had respon- (IAC) , which enables modular design and reuse of sibly disclosed the vulnerability to Android Security functionality across apps and app components. The Team which tagged it as CVE-2015-3825 (internally Android IAC model is implemented as a message- as ANDROID-21437603/21583894) and patched An- passing system, where messages are encapsulated by Intent Intent droid 4.4 / 5.x / M and Google Play Services. objects. Through s, an app (or app component) can utilize functionality exposed by another For the sake of completeness we also made app (or app component), e.g. by passing a message a large-scale experiment over 32,701 of Android to the browser to render content or to a navigation applications, finding similar previously unknown app to display a location and provide directions to it. deserialization vulnerabilities, identified by For implementing IAC, including sending and receiving CVE-2015-2000/1/2/3/4/20, in 6 SDKs affecting Intents, Android uses a mechanism called Binder. As multiple apps. We responsibly (privately) contacted described thoroughly by [3],in the center of the Binder the SDKs’ vendors or code maintainers so they would mechanism is the Binder Linux driver, that transfers provide patches. Further analysis showed that many of messages between processes. Each such Inter-Process the SDKs were vulnerable due to weak code generated Communication (IPC) message is a ’transaction’. When by SWIG, an interoperability tool that connects C/C++ an application talks to a service, it does so using with a variety of languages, when fed with some bad proxy and stub methods that get translated to Binder configuration given by the developer. We therefore transactions under the hood, albeit appear like a local worked closely with the SWIG team to make sure function call to the developer. it would generate more robust code — patches are Due to its significance, much past research has been available. invested, from multiple angles, in IAC. The research varies from Testing [4, 5, 6], Verification [7], Prevention 1https://developer.android.com/about/dashboards [8, 9] and Offensive Security [10, 11, 12, 13, 14, 15, 16]. 1 II. Serialization serious because oftentimes the inserted object is auto- matically deserialized, and later freed by the Garbage Intents may contain arbitrary data of arbitrary types Collector (GC), which calls the finalize method of via a provided Bundle2 object. For instance, an appli- the deserialized object. The finalize method may cation may provide another app with a String which switch into native code that may access non-transient can then be accessed via Bundle.getString(String pointers provided by the deserialized object, that the key) or through Intent.getStringExtra(String adversary controls. In current Android versions, any key). Moreover, a completely arbitrary object can be object put inside a Bundle can be initialized by a sent and later be accessed by the recipient via the victim app (or service) if the latter only uses (touches) Bundle.getObject(String key) method. In order a Bundle arriving from the attacker’s IAC. Using a to be able to send objects via IAC they must be Bundle is a very common behavior among apps.. serialized (or use the Parcelable interface explained Internally, when the Bundle is touched (e.g. by call- briefly below). The recipient needs to deserialize them ing getStringExtra() or similar), it unparcels it- upon instantiation. self - initializing (and instantiating) all of its val- General-purpose serialization of objects can be ues (even unused ones). These values may include achieved by implementing the Serializable interface Serializable and Parcelable objects, that will get in the object’s class. Object members which shall not deserialized (or unparcelled). Together with his dis- be serialized (for example, pointers used in native code) closure, Horn released a Proof-of-Concept (PoC) code can easily be declared by the developer by providing the crashing Android’s system_server which runs under transient modifier before each of such a member. By the system context. Horn’s PoC worked by provid- default, during deserialization, ObjectInputStream’s ing system_server with an evil, non-Serializable defaultReadObject method is called, receives the android.os.BinderProxy object, by inserting it class name of the object being deserialized from the into the setApplicationRestrictions’s method stream, and instantiates it, populating its fields that are Bundle parameter. While Horn’s PoC only crashed non-transient and non-static with the stream’s data. In system_server, it clearly demonstrated the problem, addition, developers can implement special methods in which indeed proved to be exploitable as a few months their classes, that will override the default serialization later Yaron Lavi and Nadav Markus released a write-up methods. These methods, covered by the Java Doc- [18] describing a fully working exploit. 3 umentation include readObject, readResolve and Despite the fact that CVE-2014-7911 has been writeReplace. patched, there can still be Serializable classes avail- In addition, Android provides another serialization able to applications that are dangerous to load if they facility through the Parcleable interface. Objects of can be controlled by the adversary. One prominent implementing classes can be placed inside a Parcel4 scenario happens if the developer had forgotten to add object which is designed as a high-performance IPC the transient modifier to a sensitive member (such as a transport. pointer). This game is asymmetric as one vulnerable class III. The General Android Problem that is available to the default Android class loader is enough for all apps (or one highly-privileged ser- In 2014, Jann Horn has disclosed a significant vulner- vice) to be compromised. Objects of such classes may cause damage in several ways, including automatic code ability [17] in Android. The vulnerability, identified as finalize CVE-2014-7911, was a serious flaw in the way An- execution of their method with deserialized ObjectInputStream params or by other methods (such as writeReplace droid derserialized objects via . or writeObject In Android versions earlier than 5.0, the deserializing ) that can be called implicitly . code did not verify that the received object is indeed Hypothetically, even in an ideal world where there serializable by making sure that its class implements aren’t such vulnerable classes available in the Android the Serializable interface. This allowed for inserting framework, such classes could be found in third-party arbitrary objects (available to the target’s class loader) frameworks (SDKs) or in specific apps - making a more into a target app or service. Things became more targeted attack. It is important to note that Bundle isn’t the only vec- 2http://developer.android.com/reference/android/- tor. Each code path that leads to Parcel’s readValue, os/Bundle.html readParcelable or readSerializable will also in- 3http://docs.oracle.com/javase/7/docs/api/java/io/Serializable.html/ 4http://developer.android.com/reference/android/- stantiate whatever object is on the stream (that is os/Parcel.html loadable). 2 IV. Finding a Vulnerable Class VirtualMachine vm = <retrieved when attached to debuggee > f o r (ReferenceType ref : vm.allClasses()) We wanted to find a class available to any Android { app that both implements the Serializable interface, i f ( ! ( r e f i n s t a n c e o f ClassType)) { holds a native pointer as a member without declaring it continue ; to be transient, and also provides a finalize method } which accesses that pointer. The finalize method does ClassType cref = (ClassType)ref; not have to be implemented by the class itself, but rather boolean isSerializable = f a l s e ; f o r (InterfaceType iref : cref.allInterfaces()) by an ancestor class, accessing the pointer via a call to { an overidden method. i f ("java.io.Serializable".equals(iref .name())) { We automatically created a list of candidate classes isSerializable = true ; using the following mechanics. We first wrote a small break ; Activity } app with a single , and then ran it, waiting for } a debugger, using the following am command, under an i f (!isSerializable) continue ; emulator running Android 4.2 through 5.1.1. boolean hasFinalize = f a l s e ; am start -D -n <activity class> f o r (Method m : cref.methodsByName("finalize")) { We remotely attached our custom debugger to the String declaringClass = m.declaringType().name(); application through JDWP.