Bugs in Tenda's AC1900 Wireless Router

In this simple howto we will explore the Tenda's AC1900 wireless router. Let's start.

The firmware

The Tenda's AC1900 is a Wi-Fi router, whose firmware is basically composed by a linux file-system. In this post, we consider the latest available Tenda's firmware at the time of writing: US_AC18V1.0BR_V15.03.05.05_multi_TD01.bin .

The Analysis

After unpacking and reverse engineering for few minutes the above-mentioned firmware, one could immediately deduct that two binaries are involved in handling user's HTTP requests: ./bin/httpd and ./usr/bin/app_data_center. In particular, while the former is demanded to gather user's data from the underlying socket, the latter parses and consumes such data. After decompiling the app_data_center binary, we immediately understand how this works. Consider the following snippet of code, belonging to the main function: Here we can see that if the HTTP method is a GET, the user's query string is retrieved through a getenv and passed to a function called parse_vars. The function parse_vars, as we can see from the snippet below, takes the user's string and parses it, creating a list of objects containing pointers to the passed string (v19). In particular, v5[0] will contain the address of the next element in the list, v5[1] the pointer to an argument in v19, finally v5[2] will point to the values (parsed by urldecode) of v5[1]'s arguments. Finally, when the arguments are parsed and the argument list created, the function do_request_process is called. This function merely acts as a stub for other functions, as you can see from the decompiled code below: Two of these functions contain bugs, let's see each one of them. The first we analyze is process_datamanage_request. As one can see, this function uses the argument list, and looks for the parameters "path" and "op". In particular, if "op" is equal to 1, the parameter "path" is passed to the function process_cmd_dir. This last function takes such a parameter and it copies it into a local buffer whose size is fixed, and it can be inferred by looking at the stack offsets to be equal to 256 bytes. Therefore, if the "path" argument starts with "/usb/" followed by a number of characters greater than 251, a buffer overflow is triggered. Another very similar bugs are present in the function do_download_redirect: Also in this case the user's data is recklessly copied into a fixed-size buffer (i.e., v5), possibly causing a buffer overflow. The last bug we found is present in the function process_datamanage_usbeject, shown right below. Here, though a buffer overflow is not present as the safe funtion snprintf is used, a user can influence the content of the variable v6, thus possibly executing arbitrary commands throughs the system call. At the time of writing we are still investigating on the possible impact of these bugs, stay tuned...