Skip to main content
CVE Vulnerability Database
Vulnerability Database/CVE-2026-28810

CVE-2026-28810: Erlang/OTP DNS Cache Poisoning Vulnerability

CVE-2026-28810 is a DNS cache poisoning vulnerability in Erlang/OTP kernel caused by predictable transaction IDs and lack of port randomization. This article covers technical details, affected versions, and mitigations.

Published:

CVE-2026-28810 Overview

CVE-2026-28810 is a DNS Cache Poisoning vulnerability affecting the Erlang/OTP kernel's built-in DNS resolver (inet_res and inet_db modules). The vulnerability stems from the generation of predictable numbers or identifiers (CWE-340), where the resolver uses a sequential, process-global 16-bit transaction ID for UDP queries without implementing source port randomization.

Response validation relies almost entirely on this predictable transaction ID, making DNS cache poisoning practical for an attacker who can observe one query or predict the next ID. This design conflicts with RFC 5452 recommendations for mitigating forged DNS answers. While inet_res is intended for use in trusted network environments with trusted recursive resolvers, earlier documentation did not clearly state this deployment assumption, potentially leading users to deploy the resolver in environments where spoofed DNS responses are possible.

Critical Impact

Attackers who can observe DNS queries or predict transaction IDs can poison the DNS cache, redirecting traffic to malicious servers and enabling man-in-the-middle attacks, credential theft, or malware distribution.

Affected Products

  • Erlang/OTP versions from OTP 17.0 until OTP 28.4.2, 27.3.4.10, and 26.2.5.19
  • Erlang/OTP kernel versions from 3.0 until 10.6.2, 10.2.7.4, and 9.2.4.11
  • Applications using inet_res module (lib/kernel/src/inet_res.erl)
  • Applications using inet_db module (lib/kernel/src/inet_db.erl)

Discovery Timeline

  • 2026-04-07 - CVE-2026-28810 published to NVD
  • 2026-04-07 - Last updated in NVD database

Technical Details for CVE-2026-28810

Vulnerability Analysis

The vulnerability exists in the Erlang/OTP kernel's DNS resolution implementation within inet_res.erl and inet_db.erl. The core issue is the use of a sequential, process-global 16-bit transaction ID for UDP DNS queries. With only 65,536 possible values and predictable sequencing, an attacker can feasibly guess the correct transaction ID for a DNS response.

Additionally, the resolver does not implement source port randomization, which is a critical defense-in-depth measure recommended by RFC 5452. Without randomized source ports, attackers only need to predict the transaction ID rather than both the port and ID combination, dramatically reducing the entropy an attacker must overcome.

The vulnerability allows attackers to inject forged DNS responses that will be accepted and cached by the resolver, enabling DNS cache poisoning attacks.

Root Cause

The root cause is insufficient entropy in DNS query validation mechanisms. The inet_res module relies on a predictable 16-bit sequential transaction ID without source port randomization. This design decision conflicts with RFC 5452 security recommendations and makes the resolver vulnerable to cache poisoning in untrusted network environments.

The affected program files are:

  • lib/kernel/src/inet_db.erl
  • lib/kernel/src/inet_res.erl

Attack Vector

The attack is network-based and requires the attacker to either observe DNS queries to determine the current transaction ID sequence or blindly predict the next ID. An attacker positioned to intercept or inject network traffic can:

  1. Observe an outgoing DNS query to identify the current transaction ID
  2. Calculate the expected transaction ID for subsequent queries
  3. Send a forged DNS response with the predicted transaction ID before the legitimate response arrives
  4. The resolver accepts the malicious response and caches the poisoned entry

The security patches address the port binding mechanism in gen_udp.erl and inet.erl:

text
-doc(#{equiv => open(Port, [])}).
-spec open(Port) -> {ok, Socket} | {error, Reason} when
-      Port   :: inet:port_number() | -1,
+      Port   :: inet:port_number(),
       Socket :: socket(),
       Reason :: system_limit | inet:posix().

Source: GitHub Commit Update

The patch removes the special -1 port value handling, which was associated with the insecure port assignment mechanism:

text
	      {ip6_address() | 'any' | 'loopback',
	       port_number()}} |
	     undefined, % Internal - no bind()
-	   BPort :: port_number() | -1,
+	   BPort :: port_number(),
	   Opts :: [socket_setopt()],
	   Protocol :: socket_protocol() | 'mptcp',
	   Family :: address_family(),

Source: GitHub Commit Update

Detection Methods for CVE-2026-28810

Indicators of Compromise

  • Unexpected DNS responses arriving from IP addresses that are not configured DNS servers
  • DNS responses with transaction IDs that appear to be sequentially predictable
  • Multiple DNS responses received for single queries (indicating race conditions between legitimate and spoofed responses)
  • Unusual changes in resolved IP addresses for critical domains

Detection Strategies

  • Monitor for anomalous DNS traffic patterns, particularly responses from unexpected source IP addresses
  • Implement network-level logging to detect DNS response injection attempts
  • Analyze DNS transaction ID patterns for sequential or predictable sequences
  • Deploy DNSSEC validation where possible to detect forged responses

Monitoring Recommendations

  • Enable verbose logging on DNS resolution activities in Erlang/OTP applications
  • Implement network intrusion detection rules to identify DNS spoofing attempts
  • Monitor for sudden changes in cached DNS records, particularly for critical infrastructure domains
  • Establish baseline DNS traffic patterns and alert on deviations

How to Mitigate CVE-2026-28810

Immediate Actions Required

  • Upgrade Erlang/OTP to patched versions: OTP 28.4.2, 27.3.4.10, or 26.2.5.19 or later
  • Review deployment environments to ensure inet_res is only used in trusted network segments
  • Consider using external DNS resolution mechanisms until patches can be applied
  • Implement network segmentation to limit exposure of systems using vulnerable Erlang/OTP versions

Patch Information

Security patches are available through the official Erlang/OTP repository. The fixes have been committed to address the predictable transaction ID and port randomization issues:

Detailed information is available in the GitHub Security Advisory.

Workarounds

  • Deploy inet_res only in trusted network environments with trusted recursive resolvers as originally intended
  • Use a local caching DNS resolver (such as unbound or dnsmasq) with DNSSEC validation instead of inet_res
  • Implement network-level protections such as egress filtering and DNS response validation at firewall level
  • Consider using TCP for DNS queries where supported to reduce spoofing risk
bash
# Example: Configure application to use system DNS resolver instead of inet_res
# In your Erlang application configuration (sys.config)
[
  {kernel, [
    {inet_dns_resolve, []}  % Use OS resolver instead of inet_res
  ]}
].

Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

Default Legacy - Prefooter | Experience the World’s Most Advanced Cybersecurity Platform

Experience the Most Advanced Cybersecurity Platform

See how the world’s most intelligent, autonomous cybersecurity platform can protect your organization today and into the future.