[Editor's note: In this blog post, Raul Siles goes in-depth exploring how to attack a vulnerability in the way Android device lock works. Although a patch was released last week for this flaw, the slow (or nonexistent) update cycle for many users means this attack mechanism will be valid for quite some time to come. The best part of Raul's write-up is his use of both static and dynamic analysis techniques and a variety of tools to tease apart the flaw. Raul ends by showing how you can test that the newly released fixes for Android block exploitation of the flaw. Nice stuff! -Ed.]
By Raul Siles
The "SANS SEC575: Mobile Device Security and Ethical Hacking" training is one of the most entertaining and challenging courses I have ever taught, with enhanced coverage of Android, iOS, Windows Phone, and BlackBerry. The last couple of times I taught it this year, I travelled around the world with six different mobile devices including; Android 2.x & 4.x plus iOS 4.x, 5.x, 6.x & 7.x, my other production mobile devices, two laptops, Wi-Fi access points plus multiple USB cards and antennas, a Wifi Pineapple, a portable stand camera, and a few other gadgets. This makes crossing airport security quite challenging almost creating a kind of extra social engineering exercise for a pen tester. Yes, I get stares.
Last week, a new Android vulnerability was disclosed: "CVE-2013-6271: Remove Device Locks from Android Phone". It affects Android Jelly Bean (JB) 4.3 devices, as well as earlier version based on my own testing, such as Android Ice Cream Sandwich (ICS) version 4.0.3. The flaw allows any mobile application (from now on referred to as an "app") to remove the passcode or lock protection of Android mobile devices, no matter the lock mechanism in place: PIN code, password or passphrase, dot pattern or gesture, or face unlock. That's pretty huge.
Android implements an Inter Process Communication (IPC) mechanism through messages, called Intents. About a year ago, we started covering this feature in Day 3 of the SEC575 class, focusing our Android Intents analysis using the Mercury framework, developed by MWR InfoSecurity. You can read all about Mercury in Chris Crowley's previous article on the SANS Pen-Testing blog, "Intentional Evil: A Pen Tester's Overview of Android Intents". The SEC575 training has been recently updated with its replacement tool, called Drozer. As the Drozer framework is explicitly mentioned in the PoC section of the CVE-2013-6271 vulnerability, I thought this vulnerability was a great opportunity to show on this blog how to dissect an Android app, and offer a quick step-by-step overview of the methods and tools we can use as pen-testers and security researchers to discover and analyze, in depth, this kind of still very common Android app weakness.
A more detailed analysis of the various Android app components (Activities, Services, Receivers, etc.) and their relationships, app attack opportunities, and components exposure are covered in Day 3 of SEC575, including live demos, hands-on exercises and details of real vulnerabilities, such as a similar vulnerability affecting the Android Facebook app, v.1.8.1. (I was not aware of my artistic skills until after Björn took a picture of my screen during SANS London 2013 after going through the vulnerability details :-):
The attack vector that can be leveraged to take advantage of the CVE-2013-6271 vulnerability is based on having an offending app installed on the victim mobile device, previously installed by the user or installed by exploiting any other vulnerability in the Android platform. In order to send an intent to a public Activity, the offending app does not require any special permission in the Android platform. This increases the device exposure, as the most benign looking apps, or even future app updates, could be used now to unlock the Android device...even those apps requesting no permissions at all. BTW, these are the ones that are really suspicious to me!
The SEC575 Android static analysis section mainly focuses on the evaluation of third-party mobile apps from a corporate perspective, such as the ones you can get from Google Play (the official Android app store) or any other source or third-party store. When you need to analyze a default system Android app, such as the Settings app in the case of the CVE-2013-6271 vulnerability, there are a couple of differences that influence the analysis process.
NOTE: The analysis process described uses Windows 7 as the host operating system and the Android emulator as the target mobile environment, although the same steps apply when using a real Android mobile device or a different host operating system.
Android App Static Analysis
In order to analyze any Android app, the first requirement is to get a copy of the corresponding Android package (.apk file) from Google Play or from within an Android device. An Android package is a compressed ZIP file, so it can be easily inspected. Inside you can find resources and certificate information, as well as the two most relevant files for Android apps: AndroidManifest.xml (which includes the permissions required by the app and the components publicly exported by it, among others) and classes.dex (the app binary in Dalvik Executable, or DEX, format):
However, the default system Android apps are optimized to speed up their performance when loading and running, and as a result, the corresponding .apk file does not contain a classes.dex file. Instead, the binary has been extracted out of the .apk file and has been converted to an .odex file (Optimized DEX file).
The CVE-2013-6271 vulnerability affects the default system Settings app (identified as "com.android.settings"). The Settings app is located in the "/system/app/" directory of Android devices, split in two files: Settings.apk and Settings.odex. The adb tool available in the Android SDK can be used to extract these two files:
As the .apk file does not contain the app binary, our analysis will focus on the .odex file. The .odex file has to be deoptimized and disassembled for inspection, a process known as deodexing. The baksmali tool helps to deodex the file and requires four arguments; the Android API level (-a), the target .odex file (-x), a directory containing all the framework libraries (-d), and an output directory to save the disassembled Smali code from the app (-o).
C:\> baksmali -a 18 -x Settings.odex -d framework -o Settings
The API level is based on the Android version and can be easily obtained from the Android "Codenames, Tags, and Build Numbers" webpage. As we are using an Android 4.3 target device, the corresponding API level is 18.
The directory containing all the framework libraries can be created by checking the value of the BOOTCLASSPATH environment variable from the Android 4.3 device. Again, adb can be used to retrieve its value:
You can copy and paste the BOOTCLASSPATH variable contents in a single line into a text file ("BOOTCLASSPATH-jar.txt") and process that file in Windows to obtain (via adb pull) all the Android framework libraries from the device, plus the associated .odex files. The following commands will streamline the process (see the "Additional Resources" section below to get the "BOOTCLASSPATH.bat" script) :
C:\> set /p BCPJAR= < BOOTCLASSPATH-jar.txt
C:\> echo %BCPJAR:.jar=.odex% > BOOTCLASSPATH-odex.txt
C:\> set /p BCPODEX= < BOOTCLASSPATH-odex.txt
C:\> echo %BCPJAR% && echo %BCPODEX%
C:\> FOR %a in (%BCPJAR::= %) do @echo %a >> BOOTCLASSPATH-jar-lines.txt
C:\> FOR %a in (%BCPODEX::= %) do @echo %a >> BOOTCLASSPATH-odex-lines.txt
C:\> mkdir framework
C:\> cd framework
C:\> FOR /F %i in (..\BOOTCLASSPATH-jar-lines.txt) DO adb pull %i
C:\> FOR /F %i in (..\BOOTCLASSPATH-odex-lines.txt) DO adb pull %i
The "framework" directory can now be used as the input for the baksmali "-d" argument.
After running the baksmali command, a new "Settings" directory will be created containing the Settings app Smali code. The smali tool can be used then to reassemble the Smali code into a Dalvik EXecutable file (.dex file). The tool simply requires two arguments, the previously created "Settings" directory and the output DEX filename (-o):
C:\> smali Settings -o Settings.dex
As a result, a new "Settings.dex" file will be created containing a deoptimized binary version of the Settings app. This file would be similar to the "classes.dex" file available in the APK file for third-party apps. At this point, the dex2jar tool can be run on this DEX file to decompile the Dalvik EXecutable and extract the corresponding Java bytecode (.class files):
C:\> dex2jar Settings.dex
The dex2jar tool will create a new "Settings_dex2jar.jar" file that contains the Java bytecode for the Settings app. Through a Java decompiler, such as JD-GUI, it is possible to open this .jar file and obtain the Java source code for the target app, or an approximate representation of it.
Android App Dynamic Analysis
The Drozer framework provides advanced capabilities to interact with Android apps and their different components. After installing the Drozer agent in the target Android device, which will act as the offensive app, it is possible to establish a communication between the Drozer console and the agent. From the Drozer console, all the packages associated with the "settings" term can be listed, trying to identify the target Android Settings app ("com.android.settings"):
Drozer provides multiple modules to perform a deeper inspection on the components exposed by the Settings app, and in particular, the potentially vulnerable Activity from the total 104 Activities exported by the app, named "com.android.settings.ChooseLockGeneric":
At this point, the JD-GUI decompiler can be used to open the Settings app Java bytecode (.jar file) and inspect the specific class we are interested in, via the CVE-2013-6271 vulnerability details and the Activity name previously identified, "com.android.settings.ChooseLockGeneric". By inspecting this class source code, we can see how at the Activity creation time (inside the "onCreate()" function) the "confirm_credentials" extra boolean parameter, is extracted and evaluated from the Intent, trying to determine if a confirmation is required from the user:
Additionally, an extra "lockscreen.password_type" integer parameter is expected from the Intent associated to the Activity used to update the lock preferences:
The app will then call the "updateUnlockMethodAndFinish()" function that contains the final vulnerable code if the value of the previously mentioned parameter is equal to 0 (after going through the "upgradeQuality()" function and the associated code):
After inspecting the source code, it is possible to identify the two extra parameters required by the "com.android.settings.ChooseLockGeneric" Activity to be able to execute the vulnerable code. The Drozer frameworks facilitates the creation of a new Activity and the submission of the Intent with these two extra parameters against the target component:
If the target Android 4.3 device is protected with a passcode (e.g. PIN code), after sending the Intent with the appropriate extra parameters from the Drozer agent to the target Settings app, the vulnerable code previously mentioned will run and the lock protection will be immediately removed from the device as shown below:
When the lock is removed, it's quite startling to see the open device. The combination of both static and dynamic analysis techniques have allowed to identify the vulnerable code and to exploit it to remove the lock protection from the Android device.
Countermeasures Implemented in Android 4.4
When the same analysis is performed in Android 4.4, and Drozer is used to exploit the vulnerability, the behavior observed is the expected one for a non-vulnerable device. Before the user or an app can change or remove the lock or passcode protection, the mobile device prompts the user for confirmation by requesting the previous lock value (e.g. the user has to enter the previous PIN code):
An in depth analysis of the new Settings app in Android 4.4 reveals how the vulnerability was fixed in the latest Android version. The default system Settings app in Android 4.4 is stored in a different location, "/system/priv-app/", the new default location for Privileged Apps (instead of the old default location for all System Apps in previous Android versions, "/system/app"):
The new APK location can be obtained, for example, through the package inspection capabilities available in the Drozer framework, that provide extensive information about any app:
The Settings.odex file can be inspected in-depth following the same analysis process previously described for Android 4.3. The main difference is the extended set of libraries used by the default Android 4.4 framework, as the BOOTCLASSPATH value denotes:
As a result, the following three main differences help to fix the vulnerability and make Android 4.4 not vulnerable to the same attack. The source code of the "com.android.settings.ChooseLockGeneric" class includes a new "InternalActivity" subclass at the bottom of the source code:
A quick comparison of the "ChooseLockGeneric" class source code between Android 4.4 and Android 4.3 exposes the new code introduced in version 4.4. The "onCreate()" function now verifies that the Activity is an instance of the new "InternalActivity" class, to limit its creation from other external apps:
Finally, the AndroidManifest.xml file for the Settings app has been changed from Android 4.3 to Android 4.4 in order not to publicly export the new "InternalActivity" Activity. This XML file is in binary format, so the AXMLPrinter2 tool can be used to convert it to text for in-depth inspection:
C:\> AXMLPrinter2 AndroidManifest.xml > AndroidManifest.txt
Again, the combination of both static and dynamic analysis techniques have allowed you to confirm that Android 4.4 is not vulnerable and identify the fixes introduced in the new code to ask for confirmation before removing the lock protection from the Android device.
NOTE: The different tool commands used during the analysis process are Windows batch scripts that simply invoke the corresponding Java tool, such as baksmali, executing in reality the "java -jar baksmali-2.0.2.jar %*" command.
BOOTCLASSPATH.bat: Windows batch script that creates a 'framework' directory with all the Android framework libraries (both .jar & .odex files) specified in the local "BOOTCLASSPATH-jar.txt" file, extracted via "adb pull" from a local Android device or Android emulator (AVD).
BOOTCLASSPATH-jar_4.3.txt: Default Android 4.3 framework libraries.
BOOTCLASSPATH-jar_4.4.txt: Default Android 4.4 framework libraries.