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.
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.
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.
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.
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/
Figure 5: Shikra Pinout Guide
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.
Figure 7: Identifying and Connecting to the UART Ports
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.
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.
Figure 10: Modified UBOOT Bootargs With "Setenv" Command to Set Up Single-user Mode Access
Figure 11: Single-user Mode on Night Owl Camera
Figure 12: Captured Root's Hash in /etc/passwd
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
Figure 14: Root Login via Serial Console
Now that we gained a shell, we began enumerating our environment by using the “env” command to check our environment variables.
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.
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.
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.
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.
Figure 19: Checksec Output Shows a Stack Canary
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.
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.
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.
Figure 22: Files Used to Control the Camera via Web Requests
Figure 23: Potential Login With Creds to a Wechat Server in China
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.
Figure 24: Enable Telnet via debug.ini and an SD Card
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.
Figure 25: Used fdisk to Determine the Filesystem on the SD Card
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.
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.
Figure 28: Hostapd Configuration for Wifi Access Point
Figure 29: DHCPD Configuration
Upon connecting to the WiFi access point, our system was provided with an IP address in the range of 126.96.36.199-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 188.8.131.52 so that devices on the access point can access the camera to complete the setup.
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.
Figure 30: Telnet from Remote Device to Camera
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.
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.