Part 2 of a series about participation in the Pwn2Own Toronto 2023 contest.
This blogpost is the second part of the series about our journey to the pwn2own Toronto 2022 contest.
In Our Pwn2Own journey against time and randomness, part 1 we explained how we attacked the router from the WAN side and lost our battle against randomness and time just by a few seconds. Here we will describe two vulnerabilities that we found on the LAN side of the Netgear RAX30 router.
Pwn2own Toronto 2022 occurred on December 6-9, 2022, so why publish this now ?
Well, we reported the discovered vulnerabilities to the vendor and followed a coordinated vulnerability disclosure process that took a lot of time, and we decided not to rage-quit and just publish them, so after a lengthy coordination process we reached the agreed date for publication and here's the blog post.
LAN vulnerabilities
Buffer Overflow inside soap server
This vulnerability known as CVE-2023-27368 was not attributed to us, it seems that another competitor also found it. However, since we found this vulnerability during the competition, we will describe it nonetheless.
On the LAN side, a server brought to our notice this program called soap_serverd
, it is a server that is exposed on all LAN interfaces but does not seem to be designed for human interaction, which is of great interest to us.
In fact, this service is used by the Netgear application to communicate with the router.
During our analysis, we realized from the first line of parsing the HTTP entry that some things could go wrong. Indeed, as you can see in the decompiled code below, the parsing of the HTTP header is using sscanf
with a string format without size control.
memset(auStack_1820,0,2044);
local_1e24 = 0;
memset(auStack_1e20,0,508);
local_1c24 = 0;
memset(auStack_1c20,0,508);
local_1a24 = 0;
memset(auStack_1a20,0,508);
local_1024 = 0;
memset(auStack_1020,0,2044);
local_824 = 0;
memset(auStack_820,0,2044);
iVar1 = FUN_00019050(&local_1824,0x800);
if (iVar1 == 0) {
log_log(7,"handle_soapRequest",0x182,"line:[%s]",&local_1824);
pcVar6 = "No request found.";
}
else {
iVar1 = __isoc99_sscanf(&local_1824,"%[^ ] %[^ ] %[^ ]",&local_1e24,&local_1c24,
&local_1a24);
if (iVar1 == 3) {
iVar7 = strcasecmp((char *)&local_1e24,"post");
if (iVar7 == 0) {
FUN_00015060(param_1);
soap_serverd
reads the HTTP headers calling sscanf
to extract the HTTP method, path, and protocol version.
Because we didn't want to waste any time unnecessarily, our strategy was to focus on vulnerabilities that were easier to exploit, and we kept this vulnerability for the time we had left. The Netgear hotfix released right before the contest forced us to change our plans and we never went any further than a simple DOS with this vulnerability.
However, we were happy to see that, in their last release Netgear corrected this vulnerability by controlling the size of the parsed elements.
iVar1 = __isoc99_sscanf(&local_1824,"%511[^ ] %511[^ ] %511[^ ]",&local_1e24,&local_1c24,
&local_1a24);
If you are interested in a blogpost that converts this vulnerability into a remote code execution one, we strongly encourage you to read this blogpost.
A Denial of service vulnerability
The Netgear RAX30 router integrates several paths to access a set of services, some with authentication and some without.
Among the unauthenticated calls, there is the possibility to push files to the router via the rex_cgi
binary.
Below, an extract of rex_cgi
which handles the file uploads.
if (http_docroot != '\0') {
if (http_boundary == (void *)0x0) {
pcVar1 = "/tmp/uploadFile";
} else {
pcVar1 = "/tmp/multipartFile";
}
strcpy(psz_dest_file,pcVar1);
pfile_dest = fopen(psz_dest_file,"w+");
if (pfile_dest != (FILE *)0x0) {
for (i = http_content_length; i != 0; i = i - 0x400) {
if (i < 0x401) {
fread(buffer,i,1,stdin);
fwrite(buffer,i,1,pfile_dest);
break;
}
fread(buffer,0x400,1,stdin);
fwrite(buffer,0x400,1,pfile_dest);
}
fclose(pfile_dest);
strcpy(&DAT_00027427,psz_dest_file);
}
As you can see, the file is directly written inside the /tmp
directory, and no size verification is done. Thus, if you submit a file of a size greater than router's available RAM, the router will freeze.
To try this you can use this script:
import requests
url = 'http://192.168.1.1/tm_block/tm_block.cgi'
files={'testfile':open('test.cfg','rb')}
resp = requests.put(url, files=files)
print(resp.status_code)
To have a POC that works properly, you should have a test.cfg
file of size over 1G, the RAM size of this router.
This vulnerability is not critical, but it could be really inconvenient for anyone wanting to use this router.
Signature bypass of the whole firmware
We reverse engineered the firmware format of the Netgear RAX. The figure below details it precisely:
This analysis was based on the original image found on the manufacturer's website, the bcm_flasher
binary and its library libbcm_flashutil.so
allowing to flash the image on the NAND memory and the library libpu_util.so
containing two interesting functions for the understanding of the firmware format:
puUtl_signCfg
is used to check the signature embedded in the firmware format, andpuUtl_getSignHeader
is used to retrieve the important information contained in the proprietary header.
The router uses a wrapping header for the ITB format used on Broadcom chipset and some other chipset, the ITB format is a firmware format based on FDT (Flattened Device Tree) for SoC (System-on-a-Chip) of the ARM processor family. The ITB format is designed to store a firmware image that includes both the firmware binary code and a Flattened Device Tree representation of the devices embedded in the SoC. This representation allows the firmware to recognize the hardware devices and configure them correctly. The ITB format also allows for the storage of important metadata such as firmware version, security information and firmware integrity checks. It is possible for instance to create a signed image commonly called a FIT image, but for our case it is not used. They have their own method for signing the firmware.
In fact, one field is called signature
, and this signature is based on sha256 and 2 salted parts (K and K2). This verification is found inside the puUtl_signCfg
function.
SHA256_Init(sha_context);
SHA256_Update(sha_context,"hr89sdfgjkehx",0xd);
SHA256_Update(sha_context,&Header,iVar4 + 4U);
SHA256_Update(sha_context,ITB,size_ITB);
SHA256_Update(sha_context,"nohsli9fjh3f",0xc);
SHA256_Final((uchar *)&uStack_548,sha_context);
A sha256 hash is computed with hr89sdfgjkehx
+ PADDING + TYPE_VER + SIZE + VERSION + TYPE_VER + SIZE + DB_VERSION + ITB_HEADER + ITB + nohsli9fjh3f
.
Thus, because the "signature" of a firmware image is just the SHA256 digest of image data concatenated with a secret string embedded in the firmware it is possible to create firmware images with valid signatures that will pass the signature validation check.
Conclusion
During our participation in the Pwn2Own Toronto 2022 contest, we discovered a couple of vulnerabilities that were exploitable on the LAN side of the router. One of them was also discovered by another participating team and it is fixed in the latest firmware version. We reverse engineered the firmware's format and also discovered that it is possible to create custom firmware with a valid signature and flash it on the router for persistence. We reported the vulnerabilities to Netgear and followed a 173-day coordinated disclosure process for publication.
Update - 2023-11-15
After the intial publication of this blogpost on 7th of November 2023,
Jimi Sebree informed us on X that Tenable discovered the same vulnerabilities
(Tenable blogpost).
These two vulnerabilities are known as CVE-2023-28338 for the denial of service
and CVE-2023-28337 for the signature bypass of the whole firmware explained
above.
Disclosure timeline
- 2023-05-18 Quarkslab sent email to Netgear Technical Support asking for product security contact information explaining that Clause 3 of their Bug Bounty's terms on Bugcrowd makes it unacceptable to report vulnerabilities using it.
- 2023-05-18 Netgear opened
case #47304021
in their technical support portal. - 2023-05-19 Netgear technical support asked for purchase invoice and picture of the router.
- 2023-06-23 Netgear technical support closed the support case due to lack of response.
- 2023-07-14 Quarkslab sent the technical report describing the vulns, proof-of-concept program, a picture of the router and a copy of the purchase invoice.
- 2023-04-14 Netgear opened
case #47468661
in their technical support portal. - 2023-07-17 Netgear informed that it escalated the case to Level 2 Tech support and asked for a phone number and time for a callback within 48 hours.
- 2023-07-20 Netgear sent email to Quarkslab's generic contact email requesting contact information for Quarkslab Vulnerability Reports team.
- 2023-07-20 Quarkslab Vulnerability Reports team sent contact information and said it preferred to communicate over email so a record of the discussion could be kept and all parties (vendor, coordinator, researchers) could remain synchronized and informed. Nonetheless offered to discuss in a conference call if required.
- 2023-07-26 Netgear sent email to Quarkslab's generic contact email and to a sales representative acknowledging the findings and requesting to work directly with the vulnerability reports team. Asked for an email or phone number to contact it.
- 2023-07-26 Quarkslab Vulnerability Reports sent contact information (vulnreport@quarkslab.com) and asked Netgear to continue further communications using only that email address.
- 2023-08-01 Quarkslab reminded Netgear that the contact information was provided 5 days ago.
- 2023-08-01 Netgear said their engineering team would like direct contact with Quarkslab and asked for a phone number.
- 2023-08-02 Quarkslab replied that it did not have a phone number but offered to do a videoconference if necessary.
- 2023-08-03 Netgear PSIRT confirmed receiving the report and passing it to the engineering team for validation and analysis. Requested a 120-day embargo period.
- 2023-08-08 Netgear PSIRT requested an update from Quarkslab.
- 2023-08-13 Netgear L2 technical support asked if Quarkslab had received their PSIRT's email.
- 2023-08-14 Quarkslab replied to Netgear PSIRT agreeing to a 120-day embargo, counting from the first report date. Publication date was set to November 6, 2023. Noted that its likely other researchers will find the same bugs.
- 2023-08-14 Quarkslab notified Netgear L2 tech support that it already replied to the PSIRT team and asked them to stop using Quarkslab's commercial contact email address for vuln report coordination.
- 2023-08-21 Netgear PSIRT said that since the initial date of the report was July 31st, the disclosure date should be November 28th. Asked Quarkslab to confirm the date.
- 2023-08-22 Quarkslab replied that the report was sent on July 14, 2023 and the tech support case was opened on the same date, therefore that should be considered the initial date of the report. Also mentioned that a prior support case was opened on May 18th and closed on June 6th because Quarkslab did not provide a picture of the router and copy of the purchase invoice. We reaffirmed November 6, 2023 as final day for coordinating disclosure.
- 2023-08-22 Netgear L2 tech support asked if it could close the support case.
- 2023-08-23 Netgear PSIRT agreed to the proposed disclosure date of November 6, 2023.
- 2023-08-24 Quarkslab told Netgear L2 tech support that it would prefer to keep the case opened until the bugs are fixed. Asked again to remove Quarkslab's generic contact email address from the case.
- 2023-09-27 Netgear L2 tech support closed the case.
- 2023-11-07 This blog post is published.