Talos Vulnerability Report

TALOS-2017-0496

June 19, 2018

CVE Number

CVE-2017-14447

Summary

An exploitable buffer overflow vulnerability exists in the PubNub message handler for the "ad" channel of Insteon Hub running firmware version 1012. Specially crafted commands sent through the PubNub service can cause a stack-based buffer overflow overwriting arbitrary data. An attacker should send an authenticated HTTP request to trigger this vulnerability.

Tested Versions

Insteon Hub 2245-222 - Firmware version 1012

Product URLs

CVSSv3 Score

8.5 - CVSS:3.0/AV:N/AC:H/PR:L/UI:N/S:C/C:H/I:H/A:H

CWE

CWE-121: Stack-based Buffer Overflow

Details

Insteon produces a series of devices aimed at controlling and monitoring a home: wall switches, led bulbs, thermostats, cameras, etc.
One of those is Insteon Hub, a central controller which allows an end-user to use his smartphone to connect to his own house remotely and manage any other device through it.
The Insteon Hub board utilizes several MCUs, the firmware in question is executed by a Microchip PIC32MX MCU, which has a MIPS32 architecture.

The firmware uses Microchip's "Libraries for Applications" as core for the application code.
Its functionality resides on a co-operative multitasking loop, which continuously executes all the existing tasks: the library already defines several tasks, e.g. for reading and sending network packets and calling the relative callbacks.
Custom applications building on this library simply need to add new functions at the end of the loop, taking care of executing tasks as quickly as possible, or splitting them in several loop cycles, in order to let other tasks running smoothly.

To enable remote interaction via the Internet, Insteon Hub uses an online service called PubNub (https://www.pubnub.com/).
End-users install the "Insteon for Hub" application on their smartphone. Both the smartphone application and Insteon Hub include the PubNub SDK, which allows for a bi-directional communication using PubNub's REST API.

The interaction with PubNub happens by means of publish/subscribe methods. Each device has a series of channels it can subscribe to, in order to receive published messages.
To subscribe to a specific channel it's enough to call the function pubnub_subscribe (defined in the PubNub SDK), passing as parameter the channel name and a callback function that will be called when a message is received on the specified channel.

The device defines a function which parses messages received from PubNub on channel "ad": sub_9d011224. The function uses the cJSON library for parsing "JSON" messages and receives a cJSON object as parameter, which corresponds to the message fetched from PubNub.
As an example, this is a valid JSON message which is used to set the host and URL used by the device to request a firmware update:

{
"ser": "",
"cmd": "up_firm",
"h": "192.168.0.2",
"u": "/getfw"
}

The "ad" channel is used specifically for managing firmware operations. The function first checks that the ser parameter is defined. Then it reads the cmd parameter, and depending on its value it proceeds to extract other expected parameters, in this case h and u. Host and URL are then saved in a global variable for later processing.

The src parameter for strcpy at [1] is unconstrained, and can lead to a stack-based buffer overflow.

Exploit Proof-of-Concept

The following proof of concept shows how to overflow the buffer and overwrite $ra to jump to "0x9d008d30": this simulates a call to the AnnouunceIP function, so that a series of packets on UDP port 30303 can be seen upon successful exploitation.

To send a message, an HTTP GET should be used which embeds the JSON string in the "path" portion of the URL:

$ curl https://pubsub.pubnub.com/publish/<pub>/<sub>/<callback>/<channel>/<payload>?auth=<auth-key>
<pub>: PubNub's publishKey. The device uses pub-c-a415cc66-b0ca-4d1d-8d9e-947390b35df3
<sub>: PubNub's subscribeKey. The device uses sub-c-e1c54032-1685-11e4-b69f-02ee2ddab7fe
<callback>: can be set to 0
<channel>: composed by "<insteon-id>-<channel-suffix>". <insteon-id> corresponds to the lower 3 octets of the MAC address and <channel-suffix> is the actual channel name, in this case "ad" (example of full channel name: 112233-ad)
<payload>: contains the JSON message string, the minimal JSON for Insteon is {"ser":""}
<auth-key>: key for access control, 16 bytes hex-encoded

The "cmd" buffer is at $sp+0xC0-0x40 while $ra is saved at $sp+0xC0-0x4. The saved $ra already points to the parent function which has the most significant byte set to "0x9d", so in order to overwrite the return address with "0x9d008d30", this command could be used: