Offensive Security

Chasing doorbells: Finding IoT vulnerabilities in embedded devices

The set-up

NIGHT OWL SMART DOORBELL

Figure 1: Night Owl Smart Doorbell

The goal of this research project was to see if we could find any vulnerabilities and obtain full persistence on an IoT device, while learning about embedded devices in general. This post will take you through our journey to find vulnerabilities in a common, reasonably priced IoT device. For our research, we chose a Night Owl ISP Smart Doorbell – WD2CLM.

We felt the camera would be a good test subject as it is similar to Amazon Ring in size and features. We started the test by performing a complete hardware teardown of the device. This allowed us to identify pinouts for Universal Asynchronous Receiver/Transmitter (UART). We also identified multiple Serial Peripheral Interface (SPI) flash chips, which store the filesystem and the bootloader.

 
Flash chips

Figure 2: Close-Up View of Flash Chips

The chip is identified as a HI Silicon HI3516 CRBCV300, a common chip for these types of devices that is manufactured in China. For more information about the Single Onboard Computer (SOC), we can use Google to obtain the datasheets for this chip. This will provide us with pinouts and different features that are supported such as UART and SPI.

Getting started

A quick tip, before performing a hardware teardown of the device to find the chipset, you can use Google to obtain as much information as possible about the device.

IDENTIFYING SPI CHIP TO HOLD THE FIRMWARE - MODEL # MX25L128XX

Figure 3: Identifying SPI Chip to Hold the Firmware - Model #MX25L128XX

Locate Necessary Parts

To identify the serial ports, we looked for a set of four test points in a row which usually indicates the serial connection.

  • Vcc – Power
  • TX – Transmit
  • RX – Receive
  • GND – Ground

Since this particular product is powered via USB, connecting it only requires GND, TX, and RX.

As you can see from screenshot above, the serial ports are labeled on the board, which is useful for understanding how to connect our Shikra to our jumper wires. The Shikra is a hardware device that utilizes an FT232H chip, which allows us to interface with UART, SPI, JTAG, etc., via USB.

IDENTIFYING SPI CHIP TO HOLD THE FIRMWARE - MODEL # MX25L128XX

Figure 4: Soldered Jumper Wires to the UART Serial Ports

Fortunately for us, this device’s manufacturer labeled the pinouts on the board for the UART connection. However, if they are not labeled, you can use a multimeter to test pinouts to determine the VCC and GND pins.

Here are reference links to hunt down debug ports.

Reference URL: http://www.devttys0.com/2012/11/reverse-engineering-serial-ports/

Reference URL: https://jcjc-dev.com/2016/04/08/reversing-huawei-router-1-find-uart/

Shikra Pinout Guide

Figure 5: Shikra Pinout Guide

The Doorbell's GND, TX, And RX Connected to the Shikra's GND, TX, and RX Pins

Figure 6: The Doorbell's GND, TX, And RX Connected to the Shikra's GND, TX, and RX Pins

Accessing the console

After identifying the UART pinouts, we proceeded to use a combination of minicom and a Shikra to access the console of the camera.

Identifying and Connecting to the UART Ports

Figure 7: Identifying and Connecting to the UART Ports

Minicom Settings for Night Owl Camera

Figure 8: Minicom Settings for Night Owl Camera

We used minicom to inspect the boot process and attempted to pause its execution to gain a local shell on the system. Note that minicom is meant for null modem sessions and it can have a strange impact on the UART console, as such unwanted characters potentially injected into the transmit stream. This can cause unwanted behavior with potentially disastrous effects. To ensure a cleaner connection, we used screen tool to connect to the UART device presented by the Shikra. You can do this with screen as a backup, specify the dev device, and set the clock rate to use for the connection. An example command for this would be:

screen /dev/ttyUSB0 115200

115200 is a common baud rate to use when connecting to serial ports.

The three most common baud rates in order are 9600, 115200, and 300. You will probably only see 9600 and 115200, as 300 is quite slow. If you do not know the baud rate, you can use a tool called ‘baudrate’ by devttys0, or you can try using those three most common baud rates.

Executing the UBOOT Command "Printenv" to Analyze the Bootargs Perimeter

Figure 9: Executing the UBOOT Command "Printenv" to Analyze the Bootargs Perimeter
 

Gaining a shell

To gain a shell on the device, we edited the bootargs command to execute “/bin/sh” instead of init=/linuxrc. This loaded the system and mounted the SPI flash in single user mode. We used this to enumerate the filesystem. One interesting file we obtained was the password for root under /etc/shadow. The hash was easily searchable on Google.

Modified UBOOT Bootargs With "Setenv" Command to Set Up Single-user Mode Access

Figure 10: Modified UBOOT Bootargs With "Setenv" Command to Set Up Single-user Mode Access

Single-user Mode on Night Owl Camera

Figure 11: Single-user Mode on Night Owl Camera

Captured Root's Hash in /etc/passwd

Figure 12: Captured Root's Hash in /etc/passwd

Clear-text Password Obtained Through a Google Search of the Root Hash

Figure 13: Clear-text Password Obtained Through a Google Search of the Root Hash

To test the clear-text password, we rebooted the device and attempted to login with these newly found credentials on the device over the UART serial console

Root Login via Serial Console

Figure 14: Root Login via Serial Console

Next steps

Now that we gained a shell, we began enumerating our environment by using the “env” command to check our environment variables.

Executed the "Env" Command to Better Understand our Environment

Figure 15: Executed the "Env" Command to Better Understand our Environment

It is commonly known that most embedded devices are limited in memory and disk space to keep their size down and functionality. Because of this, they usually run a version of busybox, which can provide several useful tools such as “/bin/sh”, “/usr/bin/telnet”, “/bin/cat”, etc. A helpful tip is to check if your device is using busybox (usually the case on most IoT devices). We can use a command argument from busybox to list all the tools it provides. Figure 16 shows we only listed the binaries we cared about right now.

Executing “busybox –list-full |egrep “nc|wget|python|perl|telnet” to Check for Commonly Used Binaries

Figure 16: Executing “busybox –list-full |egrep “nc|wget|python|perl|telnet” to Check for Commonly Used Binaries

Obtain a process list

To continue with our enumeration, we executed a “ps -auwwx” command to obtain a process list. This provides a listing of all running programs. 

Detailed Process List With Important Processes Highlighted

Figure 17: Detailed Process List With Important Processes Highlighted

The screenshot above shows a few interesting things. First, it looks like a startup script was executed from “/usr/share/ipcam/shell/startup.sh”. Second, the system appears to be running “hostapd” and “udhcpd” since this provides an access point and a DHCP server. Since the system is in pairing mode, it creates a WiFi access point that we can connect to in order to be on the same network as the camera. This is necessary for the camera’s first-time setup.

It also appears to start a process called “app.” We found this to be the main application that controls functionality of the device. We used the open WiFi network to connect to the camera along with netcat to download the binary for app to our analysis system.

Netcat Listener Serving an Application Download

Figure 18: Netcat Listener Serving an Application Download

We ran Checksec against the binary to check compilation protections such as stack canaries, PIE, and NX Protections, etc.

Checksec Output Shows a Stack Canary

Figure 19: Checksec Output Shows a Stack Canary

Using Ghidra

To analyze the binary, we imported it into Ghidra, reviewed it, and exported it to decompiled C code. This step made it easier to perform both static analysis and string analysis to check for hardcoded passwords, code vulnerabilities, etc.

Importing App Binary Into Ghidra

Figure 20: Importing App Binary Into Ghidra

To make our lives a bit easier, we also exported the binary from Ghidra to C code. This is decompiled code and doesn’t have function names, etc. However, we can perform static analysis on the code to look for usernames, passwords, and potential vulnerabilities.

Exported the Binary to Decompiled C Code

Figure 21: Exported the Binary to Decompiled C Code

Some interesting findings

We performed a cursory static analysis and found what we needed to proceed. However, this codebase should be subject to further analysis. One interesting result was the ability to control the device via its webserver, in that it provided us with credentials for a WeChat server, and that it appeared to announce its presence to a WeChat channel.


Files Used to Control the Camera via Web Requests

Figure 22: Files Used to Control the Camera via Web Requests

Potential Login With Creds to a Wechat Server in China

Figure 23: Potential Login With Creds to a Wechat Server in China

Obtaining persistence 

At this point, we looked for ways to obtain persistence on the device. A good way to go about this is to enumerate the startup.sh script. We noticed from the process list that a startup.sh script was currently running. We used “less” command to read it and noticed it appeared to start telnetd at boot if a flag is set in the debug.ini on an SD card. This could help us gain persistence.


Enable Telnet via debug.ini and an SD Card

Figure 24: Enable Telnet via debug.ini and an SD Card

Enabling Telnet

We decided to test this theory of enabling telnet with a flag in the debug.ini by loading onto an SD card. Most SD cards come pre-formatted as fat32, similar to a flash drive. As shown in the screenshot above, the camera does not prefer a specific filesystem type, so we left the SD card formatted as fat32 and mounted it.

Used fdisk to Determine the Filesystem on the SD Card

Figure 25: Used fdisk to Determine the Filesystem on the SD Card

Mounted SD Card and Added Debug and Telnet Flags

Figure 26: Mounted SD Card and Added Debug and Telnet Flags

Testing our access

We dismounted the SD card and inserted it into the doorbell., then rebooted the system to see how the changes would take effect.

Netstat Contents Showing Telnet is Enabled

Figure 27: Netstat Contents Showing Telnet is Enabled

If you remember from our startup script, the device created a WiFi access point. We can use this to connect our attacking system to the doorbell’s network and connect via telnet. We can login with the same credentials we used with the serial connection.

Hostapd Configuration for Wifi Access Point

Figure 28: Hostapd Configuration for Wifi Access Point

DHCPD Configuration

Figure 29: DHCPD Configuration

Upon connecting to the WiFi access point, our system was provided with an IP address in the range of 172.14.10.10-30. This implied that about 20 hosts can be connected to the WiFi access point before it runs out of IPs to lease. It also sets the IP address for the doorbell to 172.14.10.1 so that devices on the access point can access the camera to complete the setup.

Connected via Wifi and Used Nmap to Check for the Open Telnet Port

Figure 30: Connected via Wifi and Used Nmap to Check for the Open Telnet Port

We can now successfully telnet to the device from our attacking machine and login with same credentials.

Telnet from Remote Device to Camera

Figure 30: Telnet from Remote Device to Camera

Conclusion

To conclude, we successfully took a device that we knew nothing about, performed a teardown, and used serial access to obtain a shell on the device. We then used Linux enumeration techniques and Google to obtain credentials to the system and performed post-exploit enumeration to gain a persistent shell on the device via telnet. In this instance, the device vendor included hardcoded credentials that may be used as backdoor. Additionally, the connection to a Chinese WeChat server is suspicious, to say the least.

Disclosure timeline:
1st attempt to contact vendor via email: 6/23/2020
2nd attempt to contact vendor via phone: 7/13/2020
3rd attempt to contact vendor via certified letter: 7/27/2020

Coalfire attempted to reach out to the vendor on multiple occasions, however our attempts were unsuccessful. Per responsible disclosure, we are releasing this blog post as is to the public.

How can we help?