CVE-2023-4806: glibc getaddrinfo Use After Free and NSS Hooks

  • Thread Author
A subtle but consequential bug in the GNU C Library’s name-resolution path — tracked as CVE-2023-4806 — exposed a rare use‑after‑free in getaddrinfo() that can crash networked applications and, in realistic scenarios, be abused for denial of service. The issue is notable not because it’s easy to trigger across stock systems, but because it lives at the intersection of legacy interfaces (NSS modules), unusual getaddrinfo() flags, and large multi‑address DNS responses — a combination that produced a heap use‑after‑free and required a careful upstream fix (and a follow‑up regression patch) to close the gap.

Linux server running glibc exposed to CVE-2023-4806 buffer overflow vulnerability.Background / Overview​

The GNU C Library (glibc) implements the standard POSIX network name resolution routines that millions of Linux applications rely on. Among those, getaddrinfo() is the workhorse: applications call it to translate hostnames into address structures that the OS and network stack use.
CVE‑2023‑4806 is a memory-safety flaw in getaddrinfo() that manifests as a use‑after‑free. It requires a very particular environment:
  • a pluggable Name Service Switch (NSS) module that implements only certain legacy hooks ([I]nss_gethostbyname2_r and [I]nss[/I][/I]_getcanonname_r) but does not implement [I]nss[/I]*_gethostbyname3_r;
  • a getaddrinfo() call that requests IPv6 addresses (family AF_INET6) with all of these flags set: AI_CANONNAME, AI_ALL, and AI_V4MAPPED;
  • and a resolved name that returns a large list of both IPv6 and IPv4 addresses.
Under these conditions, getaddrinfo() can end up dereferencing memory that has already been freed, producing an application crash (a clear availability impact). The issue was reported, fixed upstream in glibc, and assigned a CVSS v3.1 base score of 5.9 (Medium). A later regression introduced by the initial fix produced a memory‑leak path and was tracked as CVE‑2023‑5156; that regression was subsequently corrected.

Why this matters — beyond the patch note​

At first glance CVE‑2023‑4806 reads like a niche bug: it’s hard to trigger and depends on third‑party NSS modules behaving in a particular, partially complete way. But the real operational concern is broader:
  • Name resolution is everywhere. Almost every server process and many client tools call getaddrinfo() (web servers, SMTP servers, SSH clients, monitoring agents, container runtimes). A crash here can translate to a service outage.
  • Custom NSS modules are common in enterprise environments. Organizations sometimes deploy custom NSS modules for internal directory services, bespoke name lookups, or legacy integrations. Those modules are the primary risk vector for this CVE.
  • DNS can be weaponized. An attacker controlling DNS for a target domain (or able to influence returned answers) can craft responses with many addresses to meet the “large number of IPv6 and IPv4” requirement.
  • Patch fallout is real. The initial fix for CVE‑2023‑4806 led to a separate memory‑leak regression (CVE‑2023‑5156), demonstrating how delicate changes deep in glibc can create follow‑on problems if not carefully validated.
Taken together, this is a reminder that obscure, legacy interfaces (NSS hooks) and uncommon flag combinations can still expose critical availability risks when deployed in complex environments.

Technical deep dive: what goes wrong​

To understand the root path, you don’t need to be a glibc committer — you need to understand three moving parts: the NSS plugin API, getaddrinfo()’s handling of mixed IPv6/IPv4 results, and how certain API combinations cause double‑invocations and buffer reallocations.
  • NSS plugin hooks
  • NSS modules can implement multiple variants of the host‑lookup API: historically there are gethostbyname2_r, gethostbyname3_r, and related hooks. A module that implements only gethostbyname2_r and getcanonname_r but not gethostbyname3_r presents a narrower surface for glibc to interact with — and that omission is key to the bug’s trigger conditions.
  • Flags and address families
  • getaddrinfo() supports flags like AI_CANONNAME, AI_ALL, and AI_V4MAPPED. Combining AF_INET6 (IPv6 family) with those flags causes the resolver to retrieve both IPv6 and IPv4 addresses (the latter mapped into IPv6 space) and to ask for a canonical name via a plugin hook.
  • The memory choreography
  • In the vulnerable code path, getaddrinfo() (via its internal helper often called gethosts) calls the NSS module multiple times: once for IPv6, then again for IPv4 (or vice‑versa), and finally to retrieve the canonical name. If the first NSS call consumes and reallocates a temporary buffer enough times that some field (for example h_name) ends up referencing heap storage inside that buffer, a later path that frees the temporary buffer (for example on a NSS_STATUS_TRYAGAIN from the plugin) leaves that field as a dangling pointer. When getcanonname_r then accesses the canonical name, it dereferences that freed memory — a classical use‑after‑free.
OSS‑Security archives and upstream commit comments explain the sequence succinctly: the first lookup may cause a malloc for tmpbuf and place th->h_name inside it; a subsequent call frees tmpbuf and the final getcanonname_r dereferences th->h_name. The fix is to ensure canonical names are copied out of transient buffers and freed at the correct time.

Scope & exploitability: how realistic is an attack?​

Short answer: possible, but constrained.
  • Exploitable only with specific NSS behavior. Systems using the standard NSS modules shipped by mainstream distributions (for example libnss_files, libnss_dns) generally do not present the exact hook combination that enables the bug.
  • Requires specific getaddrinfo() flags and a domain that returns a very large set of both IPv6 and IPv4 addresses. That means the attacker must either control DNS for a target domain or intercept/poison DNS answers.
  • Attack complexity is moderate-to-high because the attacker must orchestrate both the name resolution result set and the target invocation context (application using the vulnerable getaddrinfo() flag combination). CVSS assessments reflect this: the base score is moderate (5.9), and many vendor advisories describe the vulnerability as exploitable only in “extremely rare” situations.
  • Impact is predominantly availability: crashing a process or service that relies on getaddrinfo() is a reliable denial‑of‑service vector. Claims that this path leads to arbitrary code execution are speculative without evidence; those are not supported by public upstream analysis. Treat any such claims with caution unless a credible exploit chain is published.

Where you’re likely to see exposure​

  • Systems running custom NSS modules — especially homegrown or third‑party modules that implement older hook variants but not the newer gethostbyname3_r.
  • Multi‑protocol network services that:
  • call getaddrinfo() with AF_INET6 and the AI_CANONNAME | AI_ALL | AI_V4MAPPED flags, and
  • perform lookups for hostnames that can resolve to many addresses.
  • Containers and virtual machines using base images that haven’t received glibc security updates.
  • Managed or internal services where DNS is large and dynamic (CDN edge pools, internal name registries that return many addresses).
Note for Windows admins: if you run Linux workloads (cloud VMs, WSL2/WSLg, Docker images, Azure Linux images), they can be affected. Microsoft’s product attestation processes may identify specific Microsoft‑published images that include affected glibc versions; if you depend on those images in your estate, treat them as in‑scope for updates.

Vendor response and patches (what happened)​

Upstream glibc maintainers fixed the use‑after‑free by making canonical names safe to access after transient buffers are freed — essentially copying the name to owned storage. Distributions rapidly produced security advisories and package updates.
Two practical follow‑ups to be aware of:
  • Distributions like Red Hat, Ubuntu, SUSE, Amazon Linux, and others published advisories and pushed glibc package updates addressing CVE‑2023‑4806.
  • The initial upstream fix introduced a regression (a memory‑leak path) that was subsequently tracked as CVE‑2023‑5156. Distributors released corrected updates that include both the CVE‑4806 fix and the regression fix.
Actionable guidance: install the vendor‑supplied glibc security update from your distribution repository. If you have strict change windows, prioritize systems that run custom NSS modules and high‑availability network services.

Detection: how to check whether you’re vulnerable or being targeted​

  • Identify your glibc version and recent updates
  • Check runtime glibc version: ldd --version or ldconfig -p | grep libc
  • Check package version via your package manager: rpm -q glibc (RHEL/CentOS/Fedora), dpkg -s libc6 (Debian/Ubuntu), or zypper info glibc (SUSE).
  • Inventory NSS modules and their implementation
  • Inspect /etc/nsswitch.conf to see what NSS services are used for hosts, passwd, etc.
  • Locate NSS shared libraries, commonly under /lib or /lib64, with names like libnss_*.so.
  • Use nm -D /lib[I]/libnss_[/I].so | grep gethostbyname to see which gethostbyname hooks the module exports. If a module exports [I]nss_gethostbyname2_r and [I]nss[/I][/I]_getcanonname_r but not [I]nss[/I]*_gethostbyname3_r, it is a candidate for exposure.
  • Search for crashes and core dumps
  • Look in system logs (journalctl, /var/log/messages, /var/log/syslog) for process crashes near getaddrinfo or libc stack traces.
  • Enable core dumps for suspicious services (temporarily) and analyze stack traces with gdb to look for getaddrinfo or getcanonname_r frames.
  • Runtime detection and telemetry
  • Application monitoring: high rate of process restarts, SIGSEGVs, or OOMs occurring during hostname resolution are signals.
  • Network telemetry: look for queries that return unusually large address sets for hostnames used by your services.

Mitigation and hardening: short‑term and long‑term steps​

If you manage Linux systems, follow this prioritized checklist:
  • Patch first
  • Update glibc via your distribution’s security channel. This is the definitive fix.
  • If using container images, rebuild base images with updated glibc packages and redeploy.
  • Audit NSS modules
  • Locate custom or third‑party NSS modules in /lib and /usr/lib.
  • Verify exported symbols; if a module lacks [I]nss[/I]*_gethostbyname3_r, request or build an updated module that implements the hook, or replace it with a supported implementation.
  • Apply temporary workarounds if you cannot patch immediately
  • Remove or disable suspect NSS modules from production (after testing), or edit /etc/nsswitch.conf to avoid using them for hosts.
  • Where feasible, avoid calling getaddrinfo() with the problematic flag combination (AF_INET6 + AI_CANONNAME + AI_ALL + AI_V4MAPPED) in high‑exposure code paths. This may not be possible for vendors or third‑party binaries.
  • Reduce DNS attack surface
  • Limit external control of DNS for domains your services rely on.
  • Use DNS response size and address count limits at your authoritative DNS servers or resolvers.
  • Harden service process supervision
  • Use service managers (systemd, supervisor) to limit damage from a single process crash — e.g., implement controlled restart backoff to avoid crash loops and preserve host stability.
Numbered step example for a minimal emergency patch process:
  • Identify all hosts with affected glibc versions.
  • Schedule a rolling update to install the vendor glibc package.
  • For services that cannot be restarted immediately, isolate them from untrusted networks and restrict DNS responses for the domains they resolve.
  • After patch, monitor for crashes for at least 24–48 hours.

Practical admin commands and checks​

  • Check libc/glibc runtime:
  • ldd --version (shows glibc version)
  • rpm -q glibc or dpkg -s libc6 (package info)
  • Find NSS libraries:
  • ls -1 /lib[I]/libnss_[/I].so*
  • Inspect exported symbols for hooks:
  • nm -D /lib/x86_64-linux-gnu/libnss_example.so | grep gethostbyname
  • Look for _nss_example_gethostbyname2_r, _nss_example_gethostbyname3_r, _nss_example_getcanonname_r
  • Confirm /etc/nsswitch.conf usage:
  • grep '^hosts:' -n /etc/nsswitch.conf
  • Monitor for crashes:
  • journalctl -u your-service-name --since "1 hour ago"
  • coredumpctl list and coredumpctl gdb PID for analysis
Note: library paths and commands vary across distributions and architectures; adjust the paths (/lib vs /lib64) as needed.

Risks, caveats, and unverifiable claims​

  • The publicly available analyses and vendor advisories consistently describe CVE‑2023‑4806 as a use‑after‑free leading to application crash with a limited and specific exploit surface. Claims that it enables remote code execution are not backed by published exploit chains. Treat any such claims as speculative unless a trusted research or vendor demonstrates a reliable RCE chain.
  • The regression CVE‑2023‑5156 shows that even security fixes must be validated in realistic workloads. Upstream and vendors moved quickly to remediate the regression, but operators should verify that their vendor patch includes both the original fix and the regression correction.
  • False sense of security can arise from assuming “most distributions are not affected” — while default NSS modules may avoid the issue, corporate environments frequently deploy specialized NSS plugins. Always validate the actual runtime environment rather than relying on generic guidance.

How to communicate this to stakeholders (operations, security, execs)​

  • For technical ops teams: prioritize patching hosts that run custom NSS modules, publicly accessible network services, and containers derived from older images. Record the glibc package upgrade as a security release and test service restarts in staging before production rollouts.
  • For security teams: add CVE‑2023‑4806 to the vulnerability tracking board with a high‑availability impact tag. Confirm whether any internal NSS modules exist, and request a review of their exported hooks.
  • For executives: explain that this is a proven denial‑of‑service vector in rare configurations and that a standard vendor patch mitigates the risk. Emphasize that post‑patch regression monitoring is essential because a follow‑on memory‑leak regression occurred during the hardening process.

Final assessment and recommendations​

CVE‑2023‑4806 is an instructive case study: it shows how decades‑old APIs and extensibility points can produce modern availability bugs when combined with uncommon operational patterns. Although not broadly exploitable on stock systems, the potential for targeted DoS against high‑value services that rely on custom NSS plugins makes timely remediation necessary.
Concrete, prioritized recommendations:
  • Patch glibc from your distribution’s official repository as the immediate, primary mitigation.
  • Audit and remediate custom NSS modules — ensure they implement the full, current set of gethostbyname hooks or replace them.
  • Harden DNS and resolvers to limit the size and address multiplicity of responses you accept for crucial hostnames.
  • Rebuild and redeploy container images with updated glibc to prevent drift.
  • Monitor logs and core dumps for resolution‑related crashes, and run a short retention period to catch any regressions.
The vulnerability highlights a persistent truth in systems security: the most obscure interfaces often yield the most surprising outages. Fixing those bugs requires the combined vigilance of library maintainers, distribution security teams, and operators who understand the unique composition of their environments. Do the updates, audit the plugins, and confirm that your runtime configuration — not just a generic distribution default — is safe.

Source: MSRC Security Update Guide - Microsoft Security Response Center
 

Back
Top