Talos Vulnerability Report

TALOS-2018-0696

Novatek NT9665X XML_GetThumbNail denial-of-service vulnerability

May 13, 2019

CVE Number

CVE-2018-4024

Summary

An exploitable denial-of-service vulnerability exists in the thumbnail display functionality of the NT9665X Chipset firmware, running on the Anker Roav A1 Dashcam, version "RoavA1SWV1.9". A specially crafted packet can cause a null pointer dereference, resulting in a device reboot.

Tested Versions

Anker Roav A1 Dashcam RoavA1SWV1.9

Product URLs

CVSSv3 Score

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

CWE

CWE-476: NULL Pointer Dereference

Details

The Novatek NT9665X SOC is a chipset used in an large number of consumer camera devices, particularly in dashboard cameras. The chip provides default firmware that is a fork of the Embedded Configurable Operating System (eCOS) project, which is found within the Roav A1 Dashcam,the product we are focusing on in this advisory.

The Roav A1 Dashcam by Anker is a dashboard camera that allows users to connect using the Roav app for Android and iOS so they can control the camera remotely. In order to do this, users must first enable the “Wi-Fi AP” setting manually on the dashcam, and then connect to the “RoavA1” SSID, with the default password “goroavcam”.

From here, the app interacts with the dashcam mainly via an eCOS web server running on port 80 that requires no authentication. The standard HTTP POST, GET and DELETE requests can be used to upload, download, or delete videos and pictures from the dashcam, but there’s also a separate interface used for configuration. When requesting any URL, a set of commands is accessed by providing the following HTTP query string: ?custom=1&cmd=<0000-9999>. It should be noted that only a firmware-specific subset of commands are implemented on any given device, the list of which can be found here: http://192.168.1.254/?custom=1&cmd=3012.

This specific vulnerability covers the XML_GetThumbNail command. This particular command is not just found in the Roav line of dashcams, but seems to be a default command in the Novatek NT966XX firmware. Note, however, that while this command shows up in all the NT966XX devices, the device in question might not be vulnerable, as certain devices (e.g. The SJ6 Camera w/ NT96660 chipset) could not be tested.

When the Roav A1 asks for a given file’s thumbnail, it parses the HTTP paths for the following file extensions first: “.MOV”,”.mov”,”.MP4”,”.mp4.” In the case that the file requested ends with one of these strings, the code path handles the situation correctly, and the given crash does not occur. Also, if the HTTP path does not contain a ‘.’ character, the code will return a default response, avoiding the vulnerability.

For all other files of various extensions, if the file exists, it reaches the following code block:

In summary, we grab a temporary buffer using a function pointer inside of [0] that calls the Movie_GetTempBuffer function, and then at [1] we read the open file descriptor (of the file found in the HTTP request) and put the bytes into our Movie_TempBuffer. The open file is then closed at [2] and parsed for EXIF data at [3], which tries to look for a thumbnail.

In our case, the call to Read_EXIF will fail if there’s no EXIF data, causing a branch to a new case, where it repeats the above disassembly (Movie_GetTempBuffer => FileSys_OpenFile => FileSys_ReadFile => FileSys_CloseFile), except instead of looking for EXIF data, the server will try to parse out thumbnail information using the GxImgFile_ParseHeader function instead.

GxImgFile_ParseHeader takes two parameters, the first of which is a pointer to a struct on the stack of the parent function, defined as:

struct {
0x0: char *file_buff;
0x4: unsigned int file_size;
}

Assuming that the address of the file_buff plus the file_size does not cause an overflow/wrap-around (which would cause an error case), the following function will be called with our file_buff as the only parameter:

At [4], the first dereference is performed on the stack address pointing to the GXImgFile structure, and then at [5], a second dereference is performed, which will provide the buffer from Movie_GetTempBuffer.

As we can see, there’s never any error checking on this particular code flow, and if the device is not in “Movie mode” (which can be toggled by sending wificmd 3001), Movie_GetTempBuffer will actually return a null buffer, causing the instruction at [5] to dereference a null pointer, crashing the process and device.

It should be noted that while the null buffer is actually checked for on multiple occasions (as noted by the "Crash Output" log messages), none of the checks stop or redirect the code flow.