Objective
I wrote this article originally to simplify the research work of WiFi penetration testing. we wanted to use the Wiwo, released last year by Core security, to create a transparent channel between the computer network interface and the WiFi router.
The first step in the study was to choose a suitable tool, in which I would first select an appropriate router for the transformation.
Over a period of time, I chose Tp-link's tl-wa5210g wireless router, which allows secure custom firmware (so I can install the previously mentioned tools), and he is also an outdoor router (originally designed to be so).
I first found a problem, the hardware version of the router I purchased (version 2.0) did not match the version of the firmware that could be customized, so it might be troublesome to install Wiwo. I also read some blogs, sometimes although the hardware version is different, but the firmware can be the same. Unfortunately, the equipment in my hand is not allowed. The hardware and firmware version of the device was matched, and I did not find a way to downgrade the firmware (tl-wa5210g_v2_140523) when I tried to downgrade using the Web interface, an error occurred.
Using the serial port
I dropped the initial goal for the moment, and instead I tried to find a way to control the device and install the software I needed. My first method was to use the UART serial communication method, I soldered the UART pin to a pin, using bus Pirate (my choice) or something like that to connect him to the computer and see what I can do. (This step requires the enclosure to be opened and operated on a green board)
After connecting to the UART serial port, I found a console that could run a limited command, and some of its options were disabled, such as the first and second ones.
Source:https://forum.openwrt.org/viewtopic.php?id=17252&p=6
I tried other different numbers and letters, hoping to find the hidden features, although I found some, but did not find useful to me.
The second method is to analyze the Web program, and I find that many UART consoles can also be accessed from the Web Interface menu, which is described in the OpenWrt wiki. For the device in my hand, I found a hidden menu:
Http://192.168.1.254/userRpm/NatDebugRpm26525557.htm
Vulnerabilities found
In the hidden menu found in the previous step, there are many buttons that show a lot of interesting information about the device. There is a default open UDP port that caught my attention.
After doing some research, I learned about the protocols that are running on this UDP port:
https://www.google.com/patents/CN102096654A?cl=en
TDDP is a simple protocol for debugging that uses a packet that uses different message types in the payload to complete the request or command delivery. The following picture is the packet information for the TDDP.
I also found that some other message types were recorded in the document. Debugging information is useful if you want to get some information about the status of your device from your device. I want to know what I can do, so I downloaded its firmware from Tp-link's official website.
After the download is complete, I use IDA to start searching for code with implementation protocols to determine how the protocols in the document are implemented in the firmware. I have found a description of the second edition of the Agreement, but by reverse I find that he and the first edition are different.
Without a description of the first version of the agreement, I decided to reverse protocol processing part of the program to understand the main differences. Although the package is structurally similar, I have found some important differences: The first edition does not support authentication and encryption of packet payloads, while the second edition requires authentication and encryption.
Analyzing the V1 version of the handler, I found that some of V2 's handlers also appeared in V1, and they were set_configuration, get_configuration and set_macaddr.
1.set_configuration for Facility Equipment configuration
2.get_configuration used to get device configuration
Based on what I now know, I'm ready to write a Python script that implements the minimum functionality of the TDDP V1 protocol, and I first focus on the get_configuration request, hoping to gather the information I need.
After a packet is sent using a script, the hardware returns a configuration file that looks like a critical value. Reading this file, we actually found the account number and password. (We do not require authentication when reading configuration information.)
It was fun, but we just got the configuration file for the device. We're still a far cry from our goal of installing a custom firmware, and that's what I really want to do. Reading the document again, I think a protocol intended for debugging is likely to have many problems. I went on to reverse-process the rest of the program, and a few hours later, when I was delving into set_configuration, I found a class-strcpy-style function that led to a simple overflow vulnerability.
After a preliminary analysis, I found that there are some limitations to the shellcoder that exploit this vulnerability, such as the inability to show 0 or a space.
Through this loophole, I can hijack the execution stream of the TDDP service, point to my own code, and then patch the update function to allow me to install my own firmware (including the old version).
The main problem with the work is that there is no debugger on the device, and for some strange reason the UART pin is not working, and I don't know why >_>. The only information I can get from the device is the value of the PC register and the value of the SP register, which they found in the Web hiding feature.
The picture below shows what the process list looks like, and you can see the values of the PC and SP clearly.
I'm going to use "Jump Debug" to write a exploit script that executes successfully or fails, and the JMP instructions will make the PC jump to a different location.
The following picture is an example of using this method to manipulate the PC pointer:
In this example, the file descriptor (0xa) is loaded into the register and then the JMP instruction is executed, which proves that the register controls the value we need.
Design the Exploit code
A few days later, using the details described earlier, I could have used ROP technology to control the PC registers via gadgets, but when I was ready to let him run my own code (I considered the limitations mentioned earlier), I failed.
I have never written the exploit code of the MIPS architecture before, after reading an article "1", I know why failed, because the MIPS cache is not refreshed (this involves the "cache consistency" processing in the MIPS architecture---Translator note), so, Write Shellcoder is not available, the blog describes that the solution to this problem is to call the sleep () function to clear the cache, but in my case, the firmware is not signed, it is difficult to recognize the sleep function, so I began to learn how the MIPS cache works, How can I erase it.
Reading this article "2" Let me know that the cache of MIPS is dual.
One is the data cache (D-cache), the other is the instruction cache (I-cache), the process of clearing the two cache is: first, set the Tagli and Taghi of the coprocessor to 0, and then call the instruction "cache 8, 0 ($a 0)" (Clear I-cache) and instructions "cache 9, 0 ($a 0)" (Clear D-cache).
Looking at the entire firmware, I found a function that was exactly what I wanted. (may be used to initialize)
I found this code to have a small problem.
This function uses the JR $ra as the other functions in the firmware return. As a conclusion, the value in the $ra register is set when the function is called by JALR, for example, you can call the Foo function:
The function of the $ra register is to determine the return address. In this example, the return command uses the JR, because, contrary to the jalr instruction, the JR instruction does not set the $ra register.
The usual solution is to use the ROP chain (or, for the MIPS architecture, say Jop better), set the value of the $ra register (for example, 0x12345678), and then call the function to jump to 0x8016b910 (the cache cleanup function), which clears the cache, You can then call your own function (for example, 0x12345678).
The problem is that the $ra register is set only at the end of the function, just like this.
The previous picture is the end of the function, and here you can see that after getting the value from the stack, the $ra register is used to return the caller, and if I set it to 0x8016b910 (clear cache), I lose control because it forms a wireless loop.
So, what?
I think that when I-cache is cleared, the new instructions are immediately set, which means I can modify the end of the Purge function (0x8016b910) and use the instructions instead of "JR $ra" "JR $fp" (or similar), using this method, I can clear the cache and jump into my shellcoder.
The following shows the change of function instruction before and after the attack;
Finally, the role of Shellcoder is to patch the code, invoke instructions to activate the patch, and turn off the firmware check.
After talking to @_topo, he suggested that I read the section layout about MIPS, and I later found that I could use KSEG1, not kseg0, so that the MIPS cache could be circumvented (http://cdn.imgtec.com/mips-training/ Mips-basic-training-course/slides/me ...). I didn't try.
Postscript
First of all, the good news is that the service cannot be connected from the WAN to, in fact, connected to WiFi is inaccessible, so you need to use a wired connection. Second, this firmware version is 2014. However, at that time, the firmware was the latest version of the device. Sadly, many of the people who use this device are not upgraded.
For other tp-link devices with a lot of new firmware, we have installed the latest firmware for TL-MR3020 (released in 2015), this service still exists, by default on the listening port. The first version of the Protocol code still exists in this firmware, although some of the first version of the instructions were deleted (for example, the code to get the configuration file was deleted), we are not sure whether the new version of the vulnerability we found. We need to study. Although we do not have equipment testing, however, by static analysis of the firmware for 2016 years, the same situation still exists.
Depending on the attack scenario and the configuration of the device (again, the WiFi connection and the public network cannot access the service), the vulnerability could be most likely to allow an attacker to change the router firmware (possibly including a persistent backdoor) so that he can obtain information from the network.
Conclusion
People are concerned about embedded security for some time now, and we don't usually spend a lot of time focusing on all the common problems.
It is a bad thing for manufacturers to be aware of the fact that a default-enabled debug protocol can be accessed without the need for identity verification. From the above research, we can find that memory overflow vulnerability is very common. A proven approach to security should also be used in embedded applications. For example, the MIPS device now supports the XI (Execute Inhibit) technology, which is similar to Intel's NX technology to prevent the execution of data entered by the user. In fact, the right approach should be used in development, such as source auditing and penetration testing.
Reference links
"1" http://www.devttys0.com/2012/10/exploiting-a-mips-stack-overflow/
"2" http://cdn.imgtec.com/mips-training/mips-basic-training-course/slides/Caches.pdf
(Posted in 360 safe guest http://bobao.360.cn/learning/detail/3221.html)
My translator--a story about Tp-link Debug Protocol (TDDP) Vulnerability mining