Broken, Abandoned, and Forgotten Code, Part 9

In the previous part, we switched gears back to the Netgear R6200 upnpd after spending some time analyzing httpd. The HTTP daemon provided an understanding of how the firmware header is supposed to be constructed. We found a header parsing function in upnpd that was similar to its httpd counterpart. So similar that it has the same memcpy() buffer overflow. This overflow was more interesting this time around, as it did not require authentication.
Read more

Broken, Abandoned, and Forgotten Code, Part 8

In the previous few posts, we spent time reversing how the Netgear R6200’s HTTP daemon parses a firmware header before writing the firmware image to flash. The goal was to work out how the 58-byte firmware header is constructed and how to generate a new one that can replace the header in a stock firmware. In the end we identified the purpose of all but 4 bytes. The regenerated header plus the original TRX firmware image allowed the HTTP daemon, running in emulation, to reach the stage where it would start writing data to the /dev/mtd1 flash partition.
Read more

Broken, Abandoned, and Forgotten Code, Intermission

We’re about halfway through the Broken, Abandoned series, so this is a good time to pause for a minute and take stock. At this point, things have gotten pretty technical; if you’ve only joined recently, you may be wondering what this series is about. I want to take a moment to summarize where we’ve been and where we can expect to go from here. Overview This series, entitled Broken, Abandoned, and Forgotten Code, is about an unauthenticated firmware update mechanism in the Netgear R6200 wireless router’s UPnP service.
Read more

Broken, Abandoned, and Forgotten Code, Part 7

In the previous post, I finished discussing the abCheckBoardID() function. I called attention to a checksum in the header generated by an unknown algorithm. I provided a python implementation of that algorithm ported from IDA disassembly. In total, I identified four fields parsed by this function, accounting for 30 bytes of the 58 byte header. In this part I’ll give an overview of the remaining functions that parse and validate the firmware header.
Read more

Broken, Abandoned, and Forgotten Code, Part 6

Note: It is assumed that the reader is debugging the processes described in this and the next several posts using emulation and IDA Pro. Those topics are outside the scope of this series and are covered in detail here and here. In the previous post, we switched gears and started looking at the web server for the Netgear R6200. That’s because the HTTP daemon’s code for upgrading the firmware is less broken and easier to analyze.
Read more

Broken, Abandoned, and Forgotten Code, Part 5

In previous installments I shared proof-of-concept code that would exercise the Netgear R6200’s hidden (and badly broken) SetFirmware SOAP action. It satisfied the various wonky conditions necessary to get into the sa_parseRcvCmd() function. Then I showed where in that function a firmware would be decoded from the SOAP request and written to flash. I showed how to identify a code path that leads to firmware writing. In part four, I showed how an undersized malloc() means a stock firmware crashes upnpd.
Read more

Broken, Abandoned, and Forgotten Code, Part 4

In the last post, I described how upnpd’s sa_parseRcvCmd() function finds the body of a SOAP request and how it parses that SOAP request. This is a large and complicated function that processes many types of SOAP requests. I demonstrated how to work out the desired path of execution to decode and write firmware. At the end I made an educated guess as to how the SOAP request should be formed, and how the firmware should be represented in the request body.
Read more

Broken, Abandoned, and Forgotten Code, Part 3

In the previous posts, I talked about the hidden “SetFirmware” SOAP action in the Netgear R6200’s UPnP daemon, and the weird timing games we have play to deal with UPnP daemon’s broken networking code. I also discussed the haphazard parsing of the HTTP headers across multiple functions. I made a guess at what headers might get our SetFirmware SOAP request passed to the sa_parseRcvCmd() function where hopefully an encapsulated firmware image will be decoded.
Read more

Broken, Abandoned, and Forgotten Code, Part 2

In the part 1, I showed how the Netgear R6200’s upnpd binary contains what appears to be a hidden SOAP action related to the string “SetFirmware”. I also showed how we can get into the upnp_receive_firmware_packets() function if we play timing games and send our request in multiple parts. In this part I’ll describe additional timing considerations needed to avoid hanging the server. I’ll also discuss sloppy parsing of the SOAP request, and I’ll make some guesses as to how that request should be formed.
Read more

Broken, Abandoned, and Forgotten Code, Part 1

Introduction This series of posts describes how abandoned, partially implemented functionality can be exploited to gain complete, persistent control of Netgear wireless routers. I’ll describe a hidden SOAP method in the UPnP stack that, at first glance, appeared to allow unauthenticated remote firmware upload to the router. After some reverse engineering, it became apparent this functionality was never fully implemented, and could never work properly given a well formed SOAP request and firmware image.
Read more