Talos Vulnerability Report

TALOS-2018-0594

Samsung SmartThings Hub hubCore Google Breakpad backtrace.io information disclosure vulnerability

July 26, 2018
CVE Number

CVE-2018-3927

Summary

An exploitable information disclosure vulnerability exists in the crash handler of the hubCore binary of the Samsung SmartThings Hub. When hubCore crashes, Google Breakpad is used to record minidumps, which are sent over an insecure HTTPS connection to the backtrace.io service, leading to the exposure of sensitive data. An attacker can impersonate the remote backtrace.io server in order 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

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

CWE

CWE-295: Improper Certificate Validation

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 that 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.

The hubCore process utilizes Google Breakpad(https://chromium.googlesource.com/breakpad/breakpad/) for generating minidumps in the event of a crash. These minidumps are then sent over to the backtrace.io service(https://backtrace.io/).

When the process starts, the function backtrace_init is called to set up the crash handler:

.text:008337F8     backtrace_init
.text:008337F8
.text:008337F8 000                 STMFD           SP!, {R4-R6,LR}
.text:008337FC 010                 MOV             R6, R0
.text:00833800 010                 SUB             SP, SP, #0x5A0
.text:00833804 5B0                 MOV             R5, #0
.text:00833808 5B0                 MOV             R0, #:lower16:aHubcore_minidu  ; "HUBCORE_MINIDUMP_URL"
.text:0083380C 5B0                 SUB             SP, SP, #8
.text:00833810 5B8                 STR             R5, [R6]
.text:00833814 5B8                 MOVT            R0, #:upper16:aHubcore_minidu  ; "HUBCORE_MINIDUMP_URL"
.text:00833818 5B8                 BL              getenv                         ; [1]
.text:0083381C 5B8                 SUBS            R4, R0, #0
.text:00833820 5B8                 BEQ             loc_8338E0
.text:00833824 5B8                 MOV             R0, #0x8C
.text:00833828 5B8                 BL              malloc
.text:0083382C 5B8                 CMP             R0, #0
.text:00833830 5B8                 MOV             R4, R0
.text:00833834 5B8                 STR             R0, [R6]
.text:00833838 5B8                 BEQ             loc_833950
.text:0083383C 5B8                 ADD             R0, SP, #0x5B8+var_5A0
.text:00833840 5B8                 MOV             R1, #:lower16:aTmp             ; "/tmp"
.text:00833844 5B8                 SUB             R2, R0, #8
.text:00833848 5B8                 MOVT            R1, #:upper16:aTmp             ; "/tmp"
.text:0083384C 5B8                 BL              std::string::string(char const*,std::allocator<char> const&)
.text:00833850 5B8                 MOV             R6, #0xFFFFFFFF
.text:00833854 5B8                 MOV             R3, #1
.text:00833858 5B8                 ADD             R1, SP, #0x5B8+var_5A0
.text:0083385C 5B8                 STMIA           R4, {R3,R6}
.text:00833860 5B8                 ADD             R0, R4, #8
.text:00833864 5B8                 BL              std::string::string(std::string const&)
.text:00833868 5B8                 LDR             R3, =unk_A42314
.text:0083386C 5B8                 LDR             R2, [SP,#0x5B8+var_5A0]
.text:00833870 5B8                 STR             R6, [R4,#0x14]
.text:00833874 5B8                 SUB             R1, R3, #0xC
.text:00833878 5B8                 STR             R5, [R4,#0x10]
.text:0083387C 5B8                 SUB             R0, R2, #0xC
.text:00833880 5B8                 STR             R5, [R4,#0x18]
.text:00833884 5B8                 CMP             R0, R1
.text:00833888 5B8                 STRB            R5, [R4,#0x1C]
.text:0083388C 5B8                 STRB            R5, [R4,#0x1D]
.text:00833890 5B8                 STR             R5, [R4,#0x20]
.text:00833894 5B8                 STR             R5, [R4,#0x24]
.text:00833898 5B8                 STR             R5, [R4,#0x28]
.text:0083389C 5B8                 STR             R5, [R4,#0x2C]
.text:008338A0 5B8                 STR             R3, [R4,#0xC]
.text:008338A4 5B8                 BNE             loc_8339CC
.text:008338A8
.text:008338A8     loc_8338A8
.text:008338A8 5B8                 MOV             R5, #1
.text:008338AC 5B8                 MOV             R2, #0xFFFFFFFF
.text:008338B0 5B8                 MOV             R3, #:lower16:sub_8337E0
.text:008338B4 5B8                 STR             R2, [SP,#0x5B8+var_5B0]
.text:008338B8 5B8                 STMEA           SP, {R4,R5}
.text:008338BC 5B8                 MOVT            R3, #:upper16:sub_8337E0       ; [2]
.text:008338C0 5B8                 ADD             R0, R4, #0x30
.text:008338C4 5B8                 MOV             R1, R4
.text:008338C8 5B8                 MOV             R2, #0
.text:008338CC 5B8                 BL              google_breakpad::ExceptionHandler::ExceptionHandler(google_breakpad::MinidumpDescriptor const&,bool (*)(void *),bool (*)(google_breakpad::MinidumpDescriptor const&,void *,bool),void *,bool,int)
.text:008338D0 5B8                 MOV             R0, R5
.text:008338D4 5B8                 ADD             SP, SP, #0x5A0
.text:008338D8 018                 ADD             SP, SP, #8
.text:008338DC 010                 LDMFD           SP!, {R4-R6,PC}

At [1], the function retrieves the URL used to submit the minidump to backtrace.io. This URL has a fixed value and is defined in /etc/default/hubcore:

# cat /etc/default/hubcore  | grep URL
export HUBCORE_MINIDUMP_URL="https://smartthings.sp.backtrace.io:8443/post?format=minidump&token=2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881"

Finally, the function sets up the Google Breakpad exception handler. As we can see, the function sub_8337E0 [2] will be called by Breakpad after the minidump has been generated.

.text:008337E0     sub_8337E0
.text:008337E0
.text:008337E0 000                 STMFD           SP!, {R4,LR}
.text:008337E4 008                 SUBS            R4, R2, #0
.text:008337E8 008                 BEQ             loc_8337F0
.text:008337EC 008                 BL              sub_833604
.text:008337F0
.text:008337F0     loc_8337F0
.text:008337F0 008                 MOV             R0, R4
.text:008337F4 008                 LDMFD           SP!, {R4,PC}

.text:00833604     sub_833604
.text:00833604
.text:00833604 000                 STMFD           SP!, {R4-R7,LR}
.text:00833608 014                 MOV             R5, R0
.text:0083360C 014                 MOV             R0, #:lower16:aHubcore_minidu  ; "HUBCORE_MINIDUMP_URL"
.text:00833610 014                 SUB             SP, SP, #0x3FC
.text:00833614 410                 MOVT            R0, #:upper16:aHubcore_minidu  ; "HUBCORE_MINIDUMP_URL"
.text:00833618 410                 BL              getenv
.text:0083361C 410                 MOV             R12, #:lower16:aProduct_nameHu ; "product_name=HubCore"
.text:00833620 410                 MOV             R6, R0
.text:00833624 410                 MOVT            R12, #:upper16:aProduct_nameHu ; "product_name=HubCore"
.text:00833628 410                 ADD             LR, SP, #0x410+var_404
.text:0083362C 410                 LDMIA           R12!, {R0-R3}
.text:00833630 410                 STMIA           LR!, {R0-R3}
.text:00833634 410                 LDMIA           R12, {R0,R1}
.text:00833638 410                 STR             R0, [LR],#4
.text:0083363C 410                 MOV             R0, #aHubcore_releas
.text:00833644 410                 STRB            R1, [LR]
.text:00833648 410                 BL              getenv
.text:0083364C 410                 MOV             R1, #0x14
.text:00833650 410                 MOV             R3, #0x11
.text:00833654 410                 MOV             R2, #:lower16:aVersionD_D_D    ; "version=%d.%d.%d"
.text:00833658 410                 MOV             R4, R0
.text:0083365C 410                 STMEA           SP, {R1,R3}
.text:00833660 410                 MOVT            R2, #:upper16:aVersionD_D_D    ; "version=%d.%d.%d"
.text:00833664 410                 MOV             R1, #0x80
.text:00833668 410                 MOV             R3, #0
.text:0083366C 410                 ADD             R0, SP, #0x410+s
.text:00833670 410                 BL              snprintf
.text:00833674 410                 BL              getGitVersion
.text:00833678 410                 MOV             R2, #:lower16:aGitversionS     ; "gitVersion=%s"
.text:0083367C 410                 MOV             R3, R0
.text:00833680 410                 MOVT            R2, #:upper16:aGitversionS     ; "gitVersion=%s"
.text:00833684 410                 MOV             R1, #0x80
.text:00833688 410                 ADD             R0, SP, #0x410+var_318
.text:0083368C 410                 BL              snprintf
.text:00833690 410                 MOV             R2, #:lower16:aHubidS          ; "hubId=%s"
.text:00833694 410                 MOV             R3, #:lower16:gHubId
.text:00833698 410                 MOVT            R2, #:upper16:aHubidS          ; "hubId=%s"
.text:0083369C 410                 MOVT            R3, #:upper16:gHubId
.text:008336A0 410                 MOV             R1, #0x80
.text:008336A4 410                 ADD             R0, SP, #0x410+var_298
.text:008336A8 410                 BL              snprintf
.text:008336AC 410                 CMP             R4, #0
.text:008336B0 410                 MOV             R3, #:lower16:aUnset           ; "unset"
.text:008336B4 410                 MOV             R2, #:lower16:aChannelS        ; "channel=%s"
.text:008336B8 410                 MOVT            R3, #:upper16:aUnset           ; "unset"
.text:008336BC 410                 MOVT            R2, #:upper16:aChannelS        ; "channel=%s"
.text:008336C0 410                 MOVNE           R3, R4
.text:008336C4 410                 MOV             R1, #0x80
.text:008336C8 410                 ADD             R0, SP, #0x410+var_218
.text:008336CC 410                 BL              snprintf
.text:008336D0 410                 MOV             R2, #:lower16:aPlatformS       ; "platform=%s"
.text:008336D4 410                 MOV             R3, #:lower16:aHubv2           ; "hubv2"
.text:008336D8 410                 MOVT            R2, #:upper16:aPlatformS       ; "platform=%s"
.text:008336DC 410                 MOVT            R3, #:upper16:aHubv2           ; "hubv2"
.text:008336E0 410                 MOV             R1, #0x80
.text:008336E4 410                 ADD             R0, SP, #0x410+var_198
.text:008336E8 410                 BL              snprintf
.text:008336EC 410                 MOV             R2, #:lower16:aUpload_file_mi  ; "upload_file_minidump=@%s"
.text:008336F0 410                 MOV             R1, #0x100
.text:008336F4 410                 LDR             R3, [R5,#0x10]
.text:008336F8 410                 MOVT            R2, #:upper16:aUpload_file_mi  ; "upload_file_minidump=@%s"
.text:008336FC 410                 ADD             R0, SP, #0x410+var_118
.text:00833700 410                 BL              snprintf
.text:00833704 410                 BL              fork
.text:00833708 410                 SUBS            R1, R0, #0
.text:0083370C 410                 BEQ             loc_833724
.text:00833710 410                 MOV             R1, #0
.text:00833714 410                 MOV             R2, R1
.text:00833718 410                 BL              waitpid
.text:0083371C 410                 ADD             SP, SP, #0x3FC
.text:00833720 014                 LDMFD           SP!, {R4-R7,PC}
.text:00833724 ---------------------------------------------------------------------------
.text:00833724
.text:00833724     loc_833724
.text:00833724 410                 MOV             R2, #0x54
.text:00833728 410                 ADD             R7, SP, #0x410+var_298
.text:0083372C 410                 ADD             R0, SP, #0x410+argv
.text:00833730 410                 MOV             R5, #:lower16:aV_0             ; "-v"
.text:00833734 410                 BL              memset
.text:00833738 410                 STR             R7, [SP,#0x410+var_3C4]
.text:0083373C 410                 ADD             R7, SP, #0x410+var_404
.text:00833740 410                 ADD             R3, SP, #0x410+s
.text:00833744 410                 STR             R7, [SP,#0x410+var_3BC]
.text:00833748 410                 MOV             R2, #:lower16:aUsrBinCurl      ; "/usr/bin/curl"
.text:0083374C 410                 ADD             R7, SP, #0x410+var_218
.text:00833750 410                 MOVT            R2, #:upper16:aUsrBinCurl      ; "/usr/bin/curl"
.text:00833754 410                 STR             R3, [SP,#0x410+var_3D4]
.text:00833758 410                 ADD             R0, SP, #0x410+var_318
.text:0083375C 410                 STR             R7, [SP,#0x410+var_3B4]
.text:00833760 410                 MOV             R4, #:lower16:aK               ; [3] "-k"
.text:00833764 410                 ADD             R7, SP, #0x410+var_198
.text:00833768 410                 MOV             LR, #:lower16:aX_0             ; "-X"
.text:0083376C 410                 MOV             R12, #:lower16:aPost_0         ; "POST"
.text:00833770 410                 MOV             R3, #:lower16:aF               ; "-F"
.text:00833774 410                 MOVT            LR, #:upper16:aX_0             ; "-X"
.text:00833778 410                 MOVT            R3, #:upper16:aF               ; "-F"
.text:0083377C 410                 MOVT            R12, #:upper16:aPost_0         ; "POST"
.text:00833780 410                 STR             R0, [SP,#0x410+var_3CC]
.text:00833784 410                 ADD             R1, SP, #0x410+argv            ; argv
.text:00833788 410                 STR             R7, [SP,#0x410+var_3AC]
.text:0083378C 410                 MOVT            R5, #:upper16:aV_0             ; "-v"
.text:00833790 410                 MOVT            R4, #:upper16:aK               ; "-k"
.text:00833794 410                 MOV             R0, R2                         ; path
.text:00833798 410                 ADD             R7, SP, #0x410+var_118
.text:0083379C 410                 STR             R6, [SP,#0x410+var_3A0]
.text:008337A0 410                 STR             R7, [SP,#0x410+var_3A4]
.text:008337A4 410                 STR             R2, [SP,#0x410+argv]
.text:008337A8 410                 STR             R5, [SP,#0x410+var_3E8]
.text:008337AC 410                 STR             R4, [SP,#0x410+var_3E4]
.text:008337B0 410                 STR             LR, [SP,#0x410+var_3E0]
.text:008337B4 410                 STR             R12, [SP,#0x410+var_3DC]
.text:008337B8 410                 STR             R3, [SP,#0x410+var_3D8]
.text:008337BC 410                 STR             R3, [SP,#0x410+var_3D0]
.text:008337C0 410                 STR             R3, [SP,#0x410+var_3C8]
.text:008337C4 410                 STR             R3, [SP,#0x410+var_3C0]
.text:008337C8 410                 STR             R3, [SP,#0x410+var_3B8]
.text:008337CC 410                 STR             R3, [SP,#0x410+var_3B0]
.text:008337D0 410                 STR             R3, [SP,#0x410+var_3A8]
.text:008337D4 410                 BL              execv
.text:008337D8 410                 MOV             R0, #0x7F
.text:008337DC 410                 BL              exit

The function collects the minidump file, as well as a set of other information to be sent to backtrace.io using curl [4]. The actual command executed is:

curl -v -k -X POST -F version=0.20.17 -F gitVersion=6ac91f43 -F hubId=<hub-MAC-address> -F product_name=HubCore -F channel=prod -F platform=hubv2 -F upload_file_minidump=@/tmp/a1fce436-3854-ff88-8cff4b8e-7875d600.dmp https://smartthings.sp.backtrace.io:8443/post?format=minidump&token=2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881

As we can see, the insecure -k switch is used [3], which allows cURL to perform insecure SSL connections. Thus, an attacker with the ability to impersonate the remote "smartthings.sp.backtrace.io" server can intercept the minidump using a self-signed certificate in order to extract sensitive process data.

Note that an hubCore crash can be triggered by using TALOS-2018-0593.

Timeline

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

Credit

Discovered by Claudio Bozzato of Cisco Talos.