Search

The Hitchhiker's Guide to Hacking Connected Cars: The Devil's Details of TCU Init Scripts in Android


A dissection of attacks resulting from faulty logic in the writing of init scripts in Telematics Control Units


"Son, the greatest trick the Devil pulled was convincing the world there was only one of him." ― David WongJohn Dies at the End


Overview of Init


Most TCUs and Head Units will run a flavor of Linux, whether it's Nvidia Linux, Android, or some other real-time operating system (RTOS). It's important to think of Android as more of an application framework that sits atop of Linux. Android is supplied as open source code, but does not bind the user with the constraints of the GPL and has no requirement for developers to make public any code developed using Android. Understanding that Android sits on top of Linux is not too dissimilar to recalling how Windows 3 sat on top of the old DOS operating system (dating myself here).


Having said that, Unix-based operating systems run an initialization (init) continuously that controls startup and shutdown of the operating system (OS) and corresponding commands that get executed during those specific "init levels." Init is the very first process that is executed during the boot of the embedded system that runs as a daemon until the embedded system is shut down and is started by the Kernel, typically as PID (Process ID) 1.


Many platforms will run SysV-style (System 5) init. At any moment a running System V is in one of the predetermined number of states referred to as run levels. At least one run level is the normal operating state of the system, such as 0 for HALT the system, 1 for Single User Mode, or run level 6 for Reboot. Simply typing $ init 6 at the command-line will for example reboot the embedded system.

"It's the little details that are vital. Little things make big things happen." -John Wooden

In Android, the init language is used in plain text files that take the file extension of .rc and are typically found in more than one number in quantity across different locations on the system. Particularly, /init.rc is the primary .rc file and is loaded by the init executable at the beginning of its execution and is responsible for the initial setup of the embedded system, for purposes of this article, we'll be reviewing mistakes made on different penetration tests of a TCU.



Actions and Order of Execution


Actions in Android are named sequences of commands. Actions have a trigger, which is used to determine when the action is executed. When an event occurs which matches an action's trigger, that action is added to the tail of a to-be-executed queue. Actions take the form of:


on <trigger> [%% <trigger>]*


<command>


<command>


These commands are added to the queue and executed on the order that the file contains them was parsed then sequentially within an individual file.

Therefore the order in which commands appear in the init files is critical to the security and integrity of the TCU.



Android Debugger


Android Debug Bridge (ADB) is a standard suite of tools and protocols which allow interaction with an Android system via USB/serial connections. It can be used to copy data to or from an Android device, present the user with a system shell on the device, and support software debugging. During the different tests across numerous OEM TCUs, the data, copy and shell access features were used extensively to access the TCU under test.




Logic Errors and Typos in Sequence


First we'll examine the /init.rc script. As discussed earlier, the sequence in which commands are listed as line items in this file are emphatically critical to the security of the system. If commands are listed in this file in the wrong order, an OEM can easily compromise the security posture of the system inadvertently by putting commands in the wrong sequence. Based on our previous tests, we'll examine some real-life scenarios we've found systemic across multiple OEMs.


# Once everything is setup, no need to modify the / root filesystem

mount rootfs rootfs / rw remount


At first glance, the comment by the developer in this OEM's TCU would indicate an intent to remount the root filesystem as read-only since there was no longer a reason to have the root filesystem as writeable. However, a typo in the command where the developer added the "w" for writeable can be clearly seen here following the "r" switch for read-only. This developer inadvertently remounted the root filesystem as read + write instead of read only like she had originally intended.



# Set Android Debugger Properties and enable the ADB Service


setprop persist.service.adb.enable 1


setprop ro.debuggable 1


setprop service.adb.root 1


Here, with this OEM, the developer is attempting to start the adb service, which was found under the "on boot" section of the init.rc script. However, further down below in the same file, the developer set the property command as the condition to enable the ADB daemon (adbd) accidentally when the intent was to disable it after it had been previously started.


# adbd is controlled by the persist.service.adb.enable system property


service adbd /sbin/adbd


disabled


# adbd on at boot in emulator


on property:persist.service.adb.enable=1


start adbd


on property:persist.service.adb.enable=0