Remotely Exploiting IoT Pet Feeders
Multiple vulnerabilities in Skymee Petalk AI and Petwant PF-103
Independent Security Evaluators (ISE) has discovered nine vulnerabilities in two IoT pet feeders: Skymee’s Petalk AI and Petwant’s PF-103. Marketed to owners of dogs and cats, these devices feature a camera and treat dispenser, controllable from their respective mobile apps.
ISE identified the flaws in firmware version 3.2.2.30 of the Petalk AI and 4.3.2.50 of the PF-103. We initially contacted both vendors between March and April 2019 in an attempt to conduct coordinated disclosure. However, as of November 2019, Petwant has only resolved CVE-2019-16734, while Skymee has not addressed any of the vulnerabilities.
Our findings are exploitable with the default configuration, and many allow remote attackers to execute arbitrary code with root privileges if certain ports are exposed. All disclosed issues are common to both devices due to their use of highly similar firmware. Since all of the unpatched vulnerabilities allow remote code execution without authentication, ISE strongly recommends that owners of these devices keep them behind a firewall and avoid opening any ports to the outside world.
Below are timelines of ISE’s communication with each vendor.
Skymee Disclosure Timeline
- March 19, 2019: Emailed Skymee at
wholesalesa@skymee.com. Inquired as to preferred medium for disclosure. - March 22, 2019: After no response from Skymee, sent vulnerability report in email attachment.
- September 7, 2019: Followed up on previous disclosure and sent over the details for another vulnerability.
Petwant Disclosure Timeline
- April 25, 2019: Emailed Petwant at service@petwant.com. Inquired as to preferred medium for disclosure.
- April 25, 2019: Petwant requested findings over email.
- April 25, 2019: Sent vulnerability report in email attachment.
- September 7, 2019: Followed up on previous disclosure and sent over the details for another vulnerability.
Findings
Firmware Updates Over Unencrypted HTTP (CVE-2019-16732)
To check for and download firmware updates, the Petalk AI and PF-103 reach out to either 112.124.112.116
or 47.254.22.43
over plaintext HTTP. Furthermore, the devices perform no cryptographic validation of their own to ensure the integrity and authenticity of firmware downloads.
The lack of transit encryption in the upgrade process allows man-in-the-middle attackers to modify firmware images while they are in flight, resulting in the ability to execute arbitrary code on the pet feeder.
Skymee Remediation: This vulnerability has not been patched in the Petalk AI.
Petwant Remediation: This vulnerability has not been patched in the PF-103.
Telnet Enabled with Default Credentials (CVE-2019-16734)
Both devices start a Telnet server on boot that prompts for a username and password:
$ telnet 192.168.2.3
Trying 192.168.2.3...
Connected to 192.168.2.3.
Escape character is '^]'.IPCAM login:
It is possible to enumerate valid users and their password hashes by inspecting the firmware image’s /etc/shadow
file, whose contents are shown below.
root:FCb/N1tGGXtP6:10957:0:99999:7:::
daemon:*:14576:0:99999:7:::
bin:*:14576:0:99999:7:::
sys:*:14576:0:99999:7:::
sync:*:14576:0:99999:7:::
ftp:*:14576:0:99999:7:::
nobody:*:14576:0:99999:7:::
The root user’s hash includes neither an $id
or $salt
value. According to the manual entry for crypt(3)
, a password entry without an $id
prefix indicates that the hashing algorithm is the original DES-based one. The man page also warns that DES-crypt is vulnerable to brute-force attacks of its key space:
Warning: the key space consists of 2**56 equal 7.2e16 possible
values. Exhaustive searches of this key space are possible using
massively parallel computers. Software, such as crack(1), is
available which will search the portion of this key space that is
generally used by humans for passwords. Hence, password selection
should, at minimum, avoid common words and names.
However, there was an easier method available at the time of my research. By Googling the hash string “FCb/N1tGGXtP6”, I found that a helpful GitHub user had already cracked this password for a different manufacturer’s device:
I was then able to provide the credentials root:059AnkJ
to access a shell via Telnet:
$ telnet 192.168.2.3
Trying 192.168.2.3...
Connected to 192.168.2.3.
Escape character is '^]'.IPCAM login: root
Password:
BusyBox v1.20.2 (2016-08-18 18:04:09 CST) built-in shell (ash)
Enter 'help' for a list of built-in commands.skrip profile....
~ # pwd
/root
Skymee Remediation: This vulnerability has not been patched in the Petalk AI.
Petwant Remediation: Version 4.22.2.42 of the PF-103 keeps the same DES-hashed password but disables Telnet by default, effectively mitigating this vulnerability.
No Authentication on udpServerSys Service (CVE-2019-16731)
The Petalk AI and PF-103 run a UDP server on 0.0.0.0:9003
called udpServerSys
. It links a shared library called libcommon.so
to provide a custom (but straightforward) binary protocol that requires no authentication.
While I never saw any communication between the mobile apps and either of the pet feeders on this port, the server is equipped to handle requests that modify device settings. The below decompilation of parseCommand()
in libcommon.so
shows a few of the commands that udpServerSys
accepts.
As no authentication is required to interface with the server, remote attackers can use functionality (and exploit the attack surface) in these handlers if port 9003 is exposed. The following six vulnerabilities take advantage of this fact to gain RCE in the udpServerSys
binary.
Skymee Remediation: This vulnerability has not been patched in the Petalk AI.
Petwant Remediation: This vulnerability has not been patched in the PF-103.
Command Injection in processCommandSetMac() (CVE-2019-16737)
Inspecting the decompiled handler for command ID 1, processCommandSetMac()
, we can see that the function runs a shell command to set the NVRAM value of ethaddr
in the uboot
zone (lines 27 and 28 below).
The command receives a single shell argument (which param_7 + 1
points to) for the interface’s new MAC address. However, the user controls this value, and neither udpServerSys
nor libcommon.so
validates its format beforehand.
This appeared to be a clear instance of command injection, so I wrote a Python script that connects to port 9003 on the pet feeder and sends a “Set MAC” request with a malicious command instead of a MAC address. The following proof of concept breaks out of the hardcoded /usr/sbin/nvram_set
command context to start telnetd
on port 1337.
Attackers can then use this vulnerability to run telnet
and gain a root shell on the device without authentication.
$ ./CVE-2019–16737.py 192.168.2.3
$ telnet 192.168.2.3 1337
Trying 192.168.2.3…
Connected to 192.168.2.3.
Escape character is ‘^]’.BusyBox v1.20.2 (2016–08–18 18:04:09 CST) built-in shell (ash)
Enter ‘help’ for a list of built-in commands./ #
Skymee Remediation: This vulnerability has not been patched in the Petalk AI.
Petwant Remediation: This vulnerability has not been patched in the PF-103.
Command Injection in processCommandSetUid() (CVE-2019-16733)
This vulnerability is very similar to the previous command injection in CVE-2019-16737. It stems from another udpServerSys
command called “Set UID”, which has an ID of 3 in the custom protocol. The decompiled form of processCommandSetUid()
is given below.
Lines 27 and 28 contain the same form of vulnerability as CVE-2019-16737: a call to system_cmd()
to update NVRAM storage settings with user-supplied input. By adjusting the previous PoC to send the little-endian integer representation of 3 for the command ID, we can adapt it to exploit the command injection in processCommandSetUid()
instead of processCommandSetMac()
.
After running the above script, attackers connect to Telnet on port 1338 to gain a root shell without authentication.
$ ./CVE-2019-16733.py 192.168.2.3
$ telnet 192.168.2.3 1338
Trying 192.168.2.3...
Connected to 192.168.2.3.
Escape character is '^]'.BusyBox v1.20.2 (2016-08-18 18:04:09 CST) built-in shell (ash)
Enter 'help' for a list of built-in commands./ #
Skymee Remediation: This vulnerability has not been patched in the Petalk AI.
Petwant Remediation: This vulnerability has not been patched in the PF-103.
Command Injection in processCommandUpgrade() (CVE-2019-16730)
The “Upgrade” command of udpServerSys
, defined in libcommon.so
, allows remote firmware upgrades of the Petalk AI or PF-103. The processCommandUpgrade()
handler takes string arguments for the upgrade type (“SYS” or “UI”) and the filename of a firmware archive (the archive must already exist on the filesystem). It then starts a thread to perform the upgrade in the background, passing the string arguments to the thread in a single C structure (update_info1
).
Lines 25 and 26 of the decompiled output show processCommandUpgrade()
creating a new thread for a routine called thread_Upgrade()
.
Within thread_Upgrade
, the application constructs a shell command string for /usr/sbin/upgrade.sh
with the two user-supplied arguments and sends it to system_cmd()
(lines 9 through 11, below).
This results in another instance of exploitable command injection. The only limitation is that the payload must fit within 24 characters, due to the call to memcpy()
with a length argument of 0x18 on line 25 of processCommandUpgrade()
. The Python proof of concept below uses netcat to start a bind shell on port 1339.
Skymee Remediation: This vulnerability has not been patched in the Petalk AI.
Petwant Remediation: This vulnerability has not been patched in the PF-103.
Command Injection (CVE-2019-17364) and Stack Buffer Overflow (CVE-2019-16735) in processCommandUploadLog()
The “Upload Log” command (ID: 0x21) of udpServerSys
allows remote users to upload a specified log file from the device to the HTTP server at 112.124.112.11:80
. Line 61 of the function processCommandUploadLog()
calls sprintf()
to write the necessary curl
command into a 384-byte local array (acStack432
) for execution by system()
.
In the function above, param_7
is a pointer to the user-controlled log filename. The use of system()
and sprintf()
without any sort of input validation results in two vulnerabilities affecting processCommandUploadLog()
: command injection and a stack-based buffer overflow.
The following Python proof of concept exploits the instance of command injection to start a Telnet server on port 1340.
For the buffer overflow, the script below sends a 512-byte payload as the log filename, crashing udpServerSys
with a segmentation fault.
While address space layout randomization (ASLR) is present, the program A) immediately restarts upon crashing and B) uses only a 32-bit address space. As a result, a brute-force bypass of ASLR to perform return-oriented programming (ROP) is likely feasible. Furthermore, ASLR does not apply to the text segment because udpServerSys
is not a position-independent executable (PIE) — any gadgets within the main executable are located at predictable addresses.
Skymee Remediation: These vulnerabilities have not been patched in the Petalk AI.
Petwant Remediation: These vulnerabilities have not been patched in the PF-103.
Stack Buffer Overflow in processCommandUploadSnapshot() (CVE-2019-16736)
The “Upload Snapshot” command (ID: 0x19) of udpServerSys
uploads a user-specified file on the feeder to the HTTP server at 112.124.112.116
. Line 142 of processCommandUploadSnapshot()
uses sprintf()
to construct a curl
command string (only for debugging output; not actually executed) that represents this upload.
Because sprintf()
is writing to a 400-byte local array (acStack456
) with user input as one of the arguments (param_7
), this function is vulnerable to a stack-based buffer overflow. The PoC below sends a 512-byte UDP payload that overflows the array and crashes udpServerSys
with a segmentation fault (the service immediately restarts).
As with the issue detailed in CVE-2019-16735, attackers can most likely exploit this vulnerability to gain remote code execution.
Skymee Remediation: This vulnerability has not been patched in the Petalk AI.
Petwant Remediation: This vulnerability has not been patched in the PF-103.
Sign up to get our latest blogs.
Shaun Mirani is a Security Analyst at Independent Security Evaluators, a firm of security specialists that provide a wide range of services including custom security assessments and software development. ISE also runs IoT Village, which hosts talks by expert security researchers who dissect real-world exploits and hacking contests consisting of off-the-shelf IoT devices.
Twitter: @ISESecurity