EDK II - Type Confusion in ParseDnsResponse
ParseDnsResponse dispatches on the attacker-controlled DNS answer section Type field (AnswerSection->Type, byte-swapped from raw wire bytes at line 1416) via a switch statement at line 1496, selecting between incompatible DNS4_TOKEN_ENTRY (for DNS_TYPE_A) and DNS6_TOKEN_ENTRY (for DNS_TYPE_AAAA) struct interpretations.
- Advisory
- BYTERAY-2026-0273
- CWE
- CWE-843
- Vendor
- TianoCore
- Product
- EDK II
- Reported
- 2026-06-25
- Disclosure
- 2026-10-29
- Affected
- EDK II at commit 70741a15d9a714323a5598eac47727e60507e22f (master, 2026-06-21); affected code in NetworkPkg/DnsDxe/DnsImpl.c.
- Credit
- Argus-Systems
Executive Summary
ParseDnsResponse dispatches on the attacker-controlled DNS answer section Type field (AnswerSection->Type, byte-swapped from raw wire bytes at line 1416) via a switch statement at line 1496, selecting between incompatible DNS4_TOKEN_ENTRY (for DNS_TYPE_A) and DNS6_TOKEN_ENTRY (for DNS_TYPE_AAAA) struct interpretations. This switch has no Instance->Service->IpVersion guard. In IPv4 mode, only Dns4TokenEntry is populated (line 1260) while Dns6TokenEntry remains NULL (initialized at line 1166); in IPv6 mode the reverse is true (Dns6TokenEntry set at line 1276, Dns4TokenEntry NULL from line 1165). A malicious DNS server can craft a response whose query section type matches the client's request (passing IsValidDnsResponse) but whose answer sections contain mismatched type records, causing a NULL pointer dereference of the uninitialized token entry for the opposite IP version. The only guard — ASSERT(Dns6TokenEntry != NULL) at line 1563 — is compiled out in RELEASE firmware builds. The mirror case, an IPv6 instance receiving a DNS_TYPE_A answer, dereferences the NULL Dns4TokenEntry at line 1508, guarded only by ASSERT(Dns4TokenEntry != NULL) at line 1501.
This advisory is one of a set reported to VulnCheck on 2026-06-25 for coordinated disclosure to the EDK II maintainers. After several follow-ups over the following months no response was received. 126 days after the initial report, ByteRay is publishing the findings in good faith so that affected integrators can assess and remediate them. All findings were identified against EDK II commit 70741a15d9a714323a5598eac47727e60507e22f (master, 2026-06-21).
Affected Products and Versions
- Vendor: TianoCore
- Product: EDK II (
NetworkPkg) - Affected commit:
70741a15d9a714323a5598eac47727e60507e22f(master, 2026-06-21). The code is present on that commit and later revisions that have not changed it. - Location:
NetworkPkg/DnsDxe/DnsImpl.c:1570(and:1508) - Function:
ParseDnsResponse - Category: Type Confusion (CWE-843)
Technical Details
Controllability: EXTERNAL_UNTRUSTED — High confidence. Classification determined by pattern and LLM agreement: the input source is a remote UDP DNS response packet received via a UdpIoRecvDatagram callback. Any network actor who can deliver a UDP packet to the firmware's DNS port controls the entire packet contents, including the answer section Type field.
Data Flow
The vulnerability originates from a remote UDP DNS response packet delivered to the firmware's DNS port. At DnsImpl.c:1926, DnsOnPacketReceived is registered as a UDP receive callback via UdpIoRecvDatagram. When a packet arrives, raw bytes are extracted via NetbufGetByte(Packet, 0, NULL) at line 1832 and passed unparsed to ParseDnsResponse at line 1838. Inside the parser, Dns6TokenEntry is initialized to NULL at line 1166. In IPv4 mode (lines 1245–1260), IsValidDnsResponse validates only the query section Type/Class, and only Dns4TokenEntry is set; Dns6TokenEntry remains NULL. At line 1416, the attacker-controlled answer section Type is byte-swapped from wire bytes. The non-GeneralLookUp branch at line 1496 dispatches via switch(AnswerSection->Type) with no IpVersion guard. When the attacker injects a DNS_TYPE_AAAA answer (case at line 1559), the ASSERT(Dns6TokenEntry != NULL) at line 1563 is a no-op in RELEASE builds, and execution proceeds to the vulnerable sink at line 1570: Dns6TokenEntry->Token->RspData.H2AData->IpList — a NULL pointer dereference. In IPv6 mode, a DNS_TYPE_A answer reaches the same NULL dereference of Dns4TokenEntry at line 1508.
Affected Callers
DnsOnPacketReceived
Sanitization / Security Controls
-
IsValidDnsResponse(query section validation) —DnsImpl.c:1069–1109: Validates the response Transaction ID, query section Type, and query section Class against outstanding client requests. This is bypassable because it only checks the query section, not the answer section types. A malicious DNS server echoes the client's query type in the response query section (passing validation) while injecting mismatched answer types. -
ASSERTguard —DnsImpl.c:1563 (AAAA) / 1501 (A): TheASSERT(Dns6TokenEntry != NULL)/ASSERT(Dns4TokenEntry != NULL)macros are gated byDebugAssertEnabled(), which returns FALSE in RELEASE firmware builds, making them no-ops in production firmware.
Additionally, RemainingLength bounds checks (lines 1188–1193, 1226–1231, 1424–1429) prevent out-of-bounds reads of the packet structure but do not validate the semantic content of answer section Type values.
Reachability and Preconditions
Attacker position and trust level for this issue are stated in the Controllability line and Data Flow above, and the concrete trigger is in Reproduction below.
Exploitability: Medium
Realism: Medium
Reproduction
- Attacker positions to respond to DNS queries from the target firmware.
- Firmware issues a
DNS_TYPE_A(IPv4) query for a hostname. - Attacker crafts a DNS response with: matching Transaction ID, query section Type=A and matching Class (to pass
IsValidDnsResponse), and an answer section containing aDNS_TYPE_AAAArecord (Type=28, DataLength=16). - Attacker sends the crafted UDP DNS response to the firmware DNS port.
DnsOnPacketReceivedreceives the packet and passes raw bytes toParseDnsResponse.IsValidDnsResponsepasses (query section type matches outstanding A query).- Parser enters the non-GeneralLookUp branch;
switch(AnswerSection->Type)dispatches tocase DNS_TYPE_AAAA. ASSERT(Dns6TokenEntry != NULL)is a no-op in RELEASE build.Dns6TokenEntry->Token->RspData.H2AData->IpListdereferences NULL, causing a firmware crash.
Impact
Remote denial of service (firmware crash / NULL pointer dereference) by the DNS server the firmware queries (which a rogue DHCP server can assign) or an on-path spoofer that matches the transaction ID, affecting UEFI systems with DnsDxe active during network operations. When page 0 is mapped (NULL pointer detection is off by default), the chained pointer reads at line 1570 come from low memory and the CopyMem at line 1572 writes the 16 attacker-supplied RDATA bytes to whatever pointer is found there; that destination is not under attacker control.
Remediation and Mitigation
As of commit 70741a15d9a714323a5598eac47727e60507e22f this issue is unfixed upstream and no CVE has been assigned. Validate the record type against the expected type before dispatching on it. The specific control that is absent or ineffective is identified in the Sanitization / Security Controls list under Technical Details.
Timeline
- 2026-06-25 - Reported to VulnCheck for coordinated disclosure to the TianoCore / EDK II security team.
- 2026-07 to 2026-10 - Several follow-ups sent; no response received.
- 2026-10-29 - Public disclosure in good faith, 126 days after the initial report.
Credits
Discovered and reported by Argus-Systems.