By Nicolas Bidron, and Nicolas Guigo.
U-boot is a popular boot loader for embedded systems with implementations for a large number of architectures and prominent in most Linux based embedded systems such as ChromeOS and Android Devices.
Two vulnerabilities were uncovered in the IP Defragmentation algorithm implemented in U-Boot, with the associated technical advisories below:
- Technical Advisory – Hole Descriptor Overwrite in U-Boot IP Packet Defragmentation Leads to Arbitrary Out of Bounds Write Primitive (CVE-2022-30790)
- Technical Advisory – Large buffer overflow leads to DoS in U-Boot IP Packet Defragmentation Code (CVE-2022-30552)
Proof of concept code will be made available once the fixes have been published.
Technical Advisories:
Hole Descriptor Overwrite in U-Boot IP Packet Defragmentation Leads to Arbitrary Out of Bounds Write Primitive (CVE-2022-30790)
Project | U-Boot |
Project URL | https://github.com/u-boot/u-boot |
Versions affected | all versions up to commit TBD |
Systems affected | All systems defining CONFIG_IP_DEFRAG |
CVE identifier | CVE-2022-30790 |
Advisory URL | TBD |
Risk | Critical 9.6 (CVSS:3.1/AV:A/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H) |
Authors | Nicolas Guigo, Nicolas Bidron |
Summary
U-boot is a popular boot loader for embedded systems with implementations for a large number of architectures and prominent in most linux based embedded systems.
Location
In u-boot/net/net.c
the __net_defragment
function line 900 through 1018.
Impact
The U-Boot implementation of RFC815 IP DATAGRAM REASSEMBLY ALGORITHMS is susceptible to a Hole Descriptor overwrite attack which ultimately leads to an arbitrary write primitive.
Description
In compiled versions of U-Boot that define CONFIG_IP_DEFRAG, a value of ip->ip_len
(IP packet header’s total Length) higher than IP_HDR_SIZE
and strictly lower than IP_HDR_SIZE+8
leads to a value for len
comprised between 0
and 7
. This ultimately results in a truncated division by 8
resulting in a value of 0
, forcing the hole metadata and fragment to point to the same location. The subsequent memcpy then overwrites the hole metadata with the fragment data. Through a second fragment, this attacker-controlled metadata can be exploited to perform a controlled write to an arbitrary offset.
This bug is only exploitable from the local network as it requires crafting a malformed packet which would most likely be dropped during routing. However, this it can be effectively leveraged to root linux based embedded devices locally.
static struct ip_udp_hdr *__net_defragment(struct ip_udp_hdr *ip, int *lenp)
{
static uchar pkt_buff[IP_PKTSIZE] __aligned(PKTALIGN);
static u16 first_hole, total_len;
struct hole *payload, *thisfrag, *h, *newh;
struct ip_udp_hdr *localip = (struct ip_udp_hdr *)pkt_buff;
uchar *indata = (uchar *)ip;
int offset8, start, len, done = 0;
u16 ip_off = ntohs(ip->ip_off);
/* payload starts after IP header, this fragment is in there */
payload = (struct hole *)(pkt_buff + IP_HDR_SIZE);
offset8 = (ip_off IP_OFFS);
thisfrag = payload + offset8;
start = offset8 * 8;
len = ntohs(ip->ip_len) - IP_HDR_SIZE;
The last line of the previous excerpt from u-boot/net/net.c
shows how the attacker can control the value of len
to be strictly lower than 8
by issuing a packet with ip_len
between 21
and 27
(IP_HDR_SIZE
has a value of 20
).
Also note that offset8
here is 0
which leads to thisfrag = payload
.
} else if (h >= thisfrag) {
/* overlaps with initial part of the hole: move this hole */
newh = thisfrag + (len / 8);
*newh = *h;
h = newh;
if (h->next_hole)
payload[h->next_hole].prev_hole = (h - payload);
if (h->prev_hole)
payload[h->prev_hole].next_hole = (h - payload);
else
first_hole = (h - payload);
} else {
Later in the same function, execution reaches the above code path. Here, len / 8
evaluates to 0
leading to newh = thisfrag
. Also note that first_hole
here is 0
since h
and payload
point to the same location.
/* finally copy this fragment and possibly return whole packet */
memcpy((uchar *)thisfrag, indata + IP_HDR_SIZE, len);
In the above excerpt the call to memcpy()
overwrites the hole metadata (since thisfrag
and h
both point to the same location) with arbitrary data from the fragmented IP packet data. With a len
value of 6
, last_byte
, next_hole
, and prev_hole
of the first_hole
all end- up attacker-controlled.
Finally the arbitrary write is triggered by sending a second fragment packet, whose offset and length only need to fit within the hole pointed to by the previously controlled metadata (next_hole
) set from the first packet.
Recommendation
This bug was disclosed to U-Boot support team and will be fixed in an upcoming patch. Update to the latest master branch version once the fix has been committed.
Large buffer overflow leads to DoS in U-Boot IP Packet Defragmentation Code (CVE-2022-30552)
Project | U-Boot |
Project URL | https://github.com/u-boot/u-boot |
Versions affected | all versions up to commit TBD |
Systems affected | All systems defining CONFIG_IP_DEFRAG |
CVE identifier | CVE-2022-30552 |
Advisory URL | TBD |
Risk | High 7.1 (CVSS:3.1/AV:A/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:H) |
Authors | Nicolas Guigo, Nicolas Bidron |
Summary
U-boot is a popular boot loader for embedded systems with implementations for a large number of architectures and prominent in most linux based embedded systems.
Location
u-boot/net/net.c
lines 915 and 1011.
Impact
The U-Boot implementation of RFC815 IP DATAGRAM REASSEMBLY ALGORITHMS is susceptible to a buffer overflow through a specially crafted fragmented IP Datagram with an invalid total length which causes a denial of service.
Description
In compiled versions of U-Boot that define CONFIG_IP_DEFRAG, a value of ip->ip_len
(IP packet header’s total length) lower than IP_HDR_SIZE
leads to len
taking a negative value, which ultimately results in a buffer overflow during the subsequent call to memcpy()
that uses len
as its count
parameter.
This bug is only exploitable from the local network as it requires crafting a malformed packet with an ip_len
value lower than the minimum accepted total length (21 as defined in the IP specification document: RFC791) which would most likely be dropped during routing.
static struct ip_udp_hdr *__net_defragment(struct ip_udp_hdr *ip, int *lenp)
{
static uchar pkt_buff[IP_PKTSIZE] __aligned(PKTALIGN);
static u16 first_hole, total_len;
struct hole *payload, *thisfrag, *h, *newh;
struct ip_udp_hdr *localip = (struct ip_udp_hdr *)pkt_buff;
uchar *indata = (uchar *)ip;
int offset8, start, len, done = 0;
u16 ip_off = ntohs(ip->ip_off);
/* payload starts after IP header, this fragment is in there */
payload = (struct hole *)(pkt_buff + IP_HDR_SIZE);
offset8 = (ip_off IP_OFFS);
thisfrag = payload + offset8;
start = offset8 * 8;
len = ntohs(ip->ip_len) - IP_HDR_SIZE;
The last line of the previous excerpt from u-boot/net/net.c
shows where the underflow to a negative len
value occurs if ip_len
is set to a value strictly lower than 20 (IP_HDR_SIZE
being 20). Also note that in the above excerpt the pkt_buff
buffer has a size of CONFIG_NET_MAXDEFRAG
which defaults to 16 KB but can range from 1KB to 64 KB depending on configurations.
/* finally copy this fragment and possibly return whole packet */
memcpy((uchar *)thisfrag, indata + IP_HDR_SIZE, len);
In the above excerpt the memcpy()
overflows the destination by attempting to make a copy of nearly 4 gigabytes in a buffer that’s designed to hold CONFIG_NET_MAXDEFRAG
bytes at most, which leads to a DoS.
Recommendation
This bug was disclosed to U-Boot support team and will be fixed in an upcoming patch. Update to the latest master branch version once the fix has been committed.
Disclosure Timeline
May 18th 2022: Initial e-mail from NCC to U-boot maintainers announcing two vulnerabilities were identified. U-Boot maintainers responded indicating that the disclosure process is to be handled publicly through U-Boot’s mailing list.
May 18th 2022: NCC posted a full writeup of the two vulnerabilities identified to U-Boot’s public mailing list.
May 25th 2022: a U-Boot maintainer indicated on the mailing list that they will implement a fix to the two findings.
May 26th 2022: a patch has been proposed by U-Boot maintainers to fix both CVEs through the mailing list.
May 31st 2022: U-boot maintainers and NCC Group agree to publishing the advisories in advance of patch deployment, given the public mailing-list-based discussion of the vulnerability and proposed fixes.
Thanks to
Jennifer Fernick, and Dave Goldsmith for their support through the disclosure process.
U-Boot’s maintainers.
Authors
Nicolas Guigo, and Nicolas Bidron