We identified multiple security vulnerabilities affecting the UPnP implementation of Broadcom’s SDK when developing detection rules for Broadcom binaries.
While we found indications that Broadcom patched these vulnerabilities as early as 2011, we discovered them to still be affecting devices released years later by major vendors such as Cisco, DD-WRT, or Linksys.
This led to the disclosure of security vulnerabilities such as CVE-2021-34730 (an unauthenticated remote code execution as root affecting Cisco RV110/RV130/RV215, which turned a forever-day). We also linked one of these vulnerabilities to a security advisory released jointly by DD-WRT and SSD-Disclosure in early 2021.
This further demonstrates the crucial need for supply chain security validation, such as secure development lifecycles and source code reviews on the supplier’s end, and third-party source code review on the device vendor’s end. Using IoT Inspector, this and many other supply chain issues can be identified automatically. In an effort to making IoT secure, you can verify if you are affected by the issues reported in this blog post, free of charge.
Overview
In the continuous quest to extend our software composition analysis, we were exploring rules for Broadcom binaries that we frequently find in connected devices by a variety of manufacturers. The filenames of these binaries usually start with bcm (e.g., bcm_atmctl, bcmcastctl, bcm_flasher, …).
In the process, we also investigated a Broadcom binary implementing a UPnP service that we found in a 4G/LTE router manufactured by a Chinese vendor. This binary was named bcmupnp, and in the reversing process we discovered two obvious flaws:
a stack buffer overflow via SSDP M-SEARCH packets
a heap buffer overflow via UPnP PortmapAdd calls
When documenting these flaws, we noticed that some of these vulnerabilities were previously disclosed and documented already. However, none of the previous publications tied the vulnerabilities to the actual producer of that code: Broadcom.
With this new knowledge, we developed a vulnerability detection rule for IoT Inspector, and uncovered multiple affected vendors and manufacturers in our dataset.
Broadcom did not reveal the exact versions of their SDK that are affected by these flaws to us, so we can only provide some guesstimates based on diffing Broadcom source code leaked in GitHub public repositories. Furthermore, we are unable to provide generic CVE identifiers for these issues, as Broadcom never issued one and vendors such as DD-WRT or Cisco started issuing their own. However, we did try our best to untangle some pretty messy supply chains.
Q. Kaiser, IoT Inspector Research Lab
Selim Enes Karaduman, working with SSD Disclosure
The only information on fix/non fix was obtained from Broadcom’s source code leaks on GitHub. First appearance of fix for stack overflow in upstream with a change towards strncpy:
This array matches the HTTP verb from the incoming SSDP message (M-SEARCH) to a specific handler (ssdp_msearch).
In ssdp_msearch, headers HOST, MAN, and ST are parsed successively. On line 31, the code checks whether the ST header starts with uuid:. If it does, an insecure call to strcpy is made on line 35 to copy the rest of that header line into a fixed sized buffer (name):
/* Parse the M-SEARCH message */
int ssdp_msearch(UPNP_CONTEXT *context)
{
char name[128];
int type;
char *host;
char *man;
char *st;
/* check HOST:239.255.255.250:1900 */
host = context->HOST;
if (!host || strcmp(host, "239.255.255.250:1900") != 0)
return -1;
/* check MAN:"ssdp:discover" */
man = context->MAN;
if (!man || strcmp(man, "\"ssdp:discover\"") != 0)
return -1;
/* process search target */
st = context->ST;
if (!st)
return -1;
if (strcmp(st, "ssdp:all") == 0) {
type = MSEARCH_ALL;
}
else if (strcmp(st, "upnp:rootdevice") == 0) {
type = MSEARCH_ROOTDEVICE;
}
else if (memcmp(st, "uuid:", 5) == 0) {
/* uuid */
type = MSEARCH_UUID;
st += 5;
strcpy(name, st);
}
}
To exploit this bug, one would simply need to send an SSDP M-SEARCH request resembling the one below:
This bug is fully exploitable given that we control the program counter. In the example below, we demonstrate that we control registers $r4 through $r11 on an ARM-based target.
We developed a quick proof-of-concept for that bug with Metasploit targeting Cisco RV130, based on our initial work targeting these brands of devices. You can see the exploit in action below.
Heap Buffer Overflow via upnp_portmap_add
The UPnP protocol allows local devices to automatically set port forwarding rules for themselves, so that a port they expose internally can be reached from the WAN interface of the device exposing a UPnP service. This is usually done by sending a SOAP request to the UPnP control service. This request should contain the internal client, internal port, remote IP, remote port, protocol, and duration for that rule to live on.
This is what a legitimate port mapping request would look like:
There’s a heap buffer overflow via the UPnP port mapping function, the overflow happens in a linked list of port mapping entries (map).
On line 3, a mapping between the SOAP action AddPortMapping and its expected argument and handler is defined (excerpt from ./device/InternetGatewayDevice/soap_x_wanipconnection.c):
upnp_portmap_add starts by requesting a portmap controller and validates the received protocol from line 23 to 27.
It then checks whether that port map is already set on line 30. If the port map is not yet present, a new port map structure is allocated on the port map controller’s port map list (lines 45-75). On lines 89 to 92, four insecure calls to strcpy are made, which is the core of this vulnerability:
/* Add a new port mapping entry */
int
upnp_portmap_add
(
UPNP_CONTEXT *context,
char *remote_host,
unsigned short external_port,
char *protocol,
unsigned short internal_port,
char *internal_client,
unsigned int enable,
char *description,
unsigned long duration
)
{
UPNP_PORTMAP_CTRL *portmap_ctrl;
UPNP_PORTMAP *map;
/* Get control body */
portmap_ctrl = (UPNP_PORTMAP_CTRL *)(context->focus_ifp->focus_devchain->devctrl);
/* data validation */
if (strcasecmp(protocol, "TCP") != 0 &&
strcasecmp(protocol, "UDP") != 0) {
upnp_syslog(LOG_ERR, "add_portmap:: Invalid protocol");
return SOAP_ARGUMENT_VALUE_INVALID;
}
/* check duplication */
map = upnp_portmap_find(context, remote_host, external_port, protocol);
if (map) {
if (strcmp(internal_client, map->internal_client) != 0)
return SOAP_CONFLICT_IN_MAPPING_ENTRY;
/* Argus, make it looked like shutdown */
if (enable != map->enable ||
internal_port != map->internal_port) {
if (map->enable) {
map->enable = 0;
upnp_osl_nat_config(map);
}
}
}
else {
if (portmap_ctrl->num == portmap_ctrl->limit) {
UPNP_PORTMAP_CTRL *new_portmap_ctrl;
int old_limit = portmap_ctrl->limit;
int old_size = UPNP_PORTMAP_CTRL_SIZE + old_limit * sizeof(UPNP_PORTMAP);
int new_limit = old_limit * 2;
int new_size = UPNP_PORTMAP_CTRL_SIZE + new_limit * sizeof(UPNP_PORTMAP);
/*
* malloc a new one for twice the size,
* the reason we don't use realloc is when realloc failed,
* the old memory will be gone!
*/
new_portmap_ctrl = (UPNP_PORTMAP_CTRL *)malloc(new_size);
if (new_portmap_ctrl == 0)
return SOAP_OUT_OF_MEMORY;
/* Copy the old to the new one, and free it */
memcpy(new_portmap_ctrl, portmap_ctrl, old_size);
free(portmap_ctrl);
/* Assign the new one as the portmap_ctrl */
portmap_ctrl = new_portmap_ctrl;
context->focus_ifp->focus_devchain->devctrl = new_portmap_ctrl;
portmap_ctrl->limit = new_limit;
}
/* Locate the map and advance the total number */
map = portmap_ctrl->pmlist + portmap_ctrl->num;
portmap_ctrl->num++;
}
/* Update database */
map->external_port = external_port;
map->internal_port = internal_port;
map->enable = enable;
map->duration = duration;
map->book_time = time(0);
strcpy(map->remote_host, remote_host);
strcpy(map->protocol, protocol);
strcpy(map->internal_client, internal_client);
strcpy(map->description, description);
/* Set to NAT kernel */
if (map->enable)
upnp_osl_nat_config(map);
return 0;
}
Interestingly, this heap overflow can be turned into a stack buffer overflow under specific conditions. This bug is therefore directly exploitable, given that we control the program counter. In the example below, we demonstrate that we control registers $r4 through $r11 on an ARM-based target.
Setting NewEnabled to 0 turns it into a stack buffer overflow, and we can bypass the NewRemoteHost validation (checking that it corresponds to the WAN IP) by setting a string value rather than a dotted decimal IP value.
Previous Discoveries
When googling for strings present in the binary, we stumbled upon Broadcom’s source code hosted in DD-WRT’s Subversion repository. This is when things got interesting.
svn log -r 45725
------------------------------------------------------------------------
r45725 | brainslayer | 2021-02-09 10:11:39 +0100 (Di, 09 Feb 2021) | 1 line
rework other potential insecure code
------------------------------------------------------------------------
Let the Hunt Begin
So, we have two serious vulnerabilities affecting the UPnP implementation that is part of Broadcom’s SDK, but no advisory was ever released about it. The only publication so far mentions DD-WRT.
We quickly wrote a vulnerability detection rule and went hunting into our firmware dataset. We identified the following affected devices:
Cisco RV110, RV215, RV130 – Affected by both stack and heap overflows.
Huawei device (B593) – A binary is affected by both issues but it is a leftover artifact.
Firmware images from Asus and NETGEAR contained a UPnP binary built from Broadcom’s SDK, but both stack and heap overflows were fixed.
Mapping the Supply Chain
The diagram below should help you get a better understanding of the complex supply chains. Items marked with a star on top are related to the stack overflow tracked as CVE-2021-27137.
In an ideal world, the initial discovery of these issues in 2012/2013 should have been reported to Broadcom, if not by the researchers, then at least by the affected manufacturers. Broadcom would have issued a patch, which in turn would have been applied by all manufacturers relying on Broadcom’s UPnP stack. Instead, the vulnerability still lives on in 2021 – but at least can be identified automatically by IoT Inspector.
Going Upstream
In order to pin down affected vendors, we rely on GitHub’s powerful search engine to identify repositories containing Broadcom’s UPnP code.
During the process, we uncovered uncanny similarities between two different SDKs: one from Ralink Tech Inc., released in 2002, and the one under investigation from Broadcom, released mid-2008.
While there may not be a hundred ways to write a UPnP service implementation in C, these two implementations make the exact same mistakes at the exact same locations in their codes. Each of them could have made use of insecure C functions at other locations, but they only made them in these two specific functions.
We can only speculate if Broadcom took inspiration from Ralink – but if that’s the case, these two UPnP bugs have been alive and well for almost 20 years.
Conclusion
As awareness for supply chain transparency is on the rise among security experts, this is yet another example of the vast implications of an obscure IoT supply chain. Too often, critical vulnerabilities are the result of an opaque supply chain for three simple reasons:
On the supplier’s end, insufficient secure software development practices, in particular lack of security testing and code review, resulted in critical security issues to be introduced into Broadcom’s SDK. Insufficient communication and lack of public advisories led to downstream vendors to remain unaware of these vulnerabilities although Broadcom patched them.
On the product vendor’s end, we see manufacturers with access to Broadcom’s source code (a requirement to build Broadcom SDK binaries for their own platform) who missed to sufficiently validate their supply chain, left the issues unspotted and distributed the vulnerabilities to hundreds of thousands of end customers – leaving them vulnerable to attacks.
But supply chain issues can go upstream, too. During our research, we discovered that security researchers and pen-testers have previously identified issues in devices relying on the Broadcom SDK, but didn’t link these issues to Broadcom directly. This lead to these issues being rediscovered and fixed over a course of a decade, leaving many users vulnerable in the process.
PSIRTS of vendors along a supply chain must start working closer with each other to assure that security issues are reported up and down the supply chain in a timely manner. Then we stand a chance that critical vulnerabilities are addressed before they are exploited by cyber criminals.
Our firmware analysis platform IoT Inspector can support in detecting such crucial supply chain issues. It automatically detects whether a firmware is based on a vulnerable Broadcom SDK. In an effort to making IoT secure, you can verify if you are affected, free of charge.
Timeline
2021-07-02 – We contact Broadcom’s security team to check if they’re aware that CVE-2021-27137 affects their SDK
2021-07-02 – Broadcom confirms it’s not present in their current products and will check if older products are affected
2021-07-03 – We start hunting for affected products and devices.
2021-07-19 – We notify affected vendors (Cisco, Huawei, Linksys) via their respective PSIRTs, and get back to Broadcom asking if they could release some kind of advisory – given that recent models are still affected.
2021-07-19 – Broadcom answers that “The code in question is not used in any current or remotely recent products. The last even remotely similar issues were corrected years ago and customers notified.”
2021-07-23 – We confirm with Huawei analysts that the affected binary is not launched and is a leftover artifact from building the image with Broadcom’s SDK.
2021-08-18 – We contact Linksys a second time, requesting they acknowledge reception of our vulnerability report.
2021-08-18 – Cisco releases an advisory tracking the issues as CVE-2021-34730
2021-10-05 – Releasing this post.
About ONEKEY
ONEKEY is the leading European specialist in Product Cybersecurity & Compliance Management. The unique combination of an automated Product Cybersecurity & Compliance Platform (PCCP) with expert knowledge and consulting services provides fast and comprehensive analysis, support and management to improve product cybersecurity and compliance from product purchasing, design, development, production to end-of-life.
Critical vulnerabilities and compliance violations in device firmware are automatically identified in binary code by AI-based technology in minutes – without source code, device or network access. Proactively audit software supply chains with integrated software bill of materials (SBOM) generation. “Digital Cyber Twins” enable automated 24/7 post-release cybersecurity monitoring throughout the product lifecycle.
Integrated compliance checking already covers the upcoming EU Cyber Resilience Act and existing requirements according to IEC62443-4-2, EN303645, UNR155 and many others.
The Product Security Incident Response Team (PSIRT) is effectively supported by the integrated automatic prioritisation of vulnerabilities, significantly reducing the time to remediation.
Leading international companies in Asia, Europe and the Americas already benefit from the ONEKEY Product Cybersecurity & Compliance Platform and ONEKEY Cybersecurity Experts.