Continuous User Behavior Monitoring using DNS Cache Timing Attacks

Hannes Weissteiner

Network and Distributed System Security (NDSS) Symposium 2026 · Day 3 · Network Security

Overview

This paper presents a comprehensive evict-and-reload style attack on local DNS caches that enables continuous monitoring of a user's browsing activity. While prior work demonstrated that DNS cache timing could reveal recent website visits, those techniques were limited to one-shot measurements that destroyed the cached information upon observation. This research solves that limitation by identifying multiple reliable eviction primitives that allow an attacker to repeatedly flush and re-probe the DNS cache, enabling persistent surveillance of which domains a user visits over time.

Watch on YouTube · Slides

Visual summary for Continuous User Behavior Monitoring using DNS Cache Timing Attacks by Hannes Weissteiner
Visual summary for Continuous User Behavior Monitoring using DNS Cache Timing Attacks by Hannes Weissteiner

Key moments

  1. 0:00 Introduction to DNS cache timing attacks and motivation
  2. 2:00 JavaScript-based DNS timing measurement via fetch requests
  3. 4:00 Scriptless attacks using CSS font alternatives
  4. 6:00 Cache eviction primitives: flooding and hole punching
  5. 10:00 Error-based eviction: flush entire cache with one request
  6. 12:00 End-to-end attacks: cross-VM and JavaScript results
  7. 14:00 Vendor disclosure responses and lack of fixes
  8. 16:00 Q&A: router caches, CNAME redirections, and RFC violations

Continuous User Behavior Monitoring using DNS Cache Timing Attacks

Speakers: Hannes Weissteiner

Conference: NDSS Symposium

YouTube: https://www.youtube.com/watch?v=Uv2dxCYxAUQ

Overview

This paper presents a comprehensive evict-and-reload style attack on local DNS caches that enables continuous monitoring of a user's browsing activity. While prior work demonstrated that DNS cache timing could reveal recent website visits, those techniques were limited to one-shot measurements that destroyed the cached information upon observation. This research solves that limitation by identifying multiple reliable eviction primitives that allow an attacker to repeatedly flush and re-probe the DNS cache, enabling persistent surveillance of which domains a user visits over time.

The attack operates across three execution contexts -- native code, JavaScript in the browser, and even entirely scriptless HTML/CSS -- making it remarkably versatile. The researchers demonstrate end-to-end attacks both cross-VM (a Python script inside a VM monitoring the host) and from JavaScript running in the browser, achieving F1 scores of 92.5% and approximately 80% respectively. Perhaps most concerning, no vendor has deployed fixes: systemd considers the resolver local-only, Chromium sees no practical mitigation path, Firefox defers to the local resolver, and Apple has only promised a future update.

Background

▶ Watch: Introduction to DNS cache timing attacks and motivation (0:00)

The Domain Name System (DNS) maps human-readable domain names to IP addresses. Because DNS resolution adds latency to every connection, most operating systems implement a local DNS cache to eliminate redundant lookups. This cache creates an inherent timing side channel: cached entries resolve faster than uncached ones, and an attacker who can measure this difference can infer which domains have been recently accessed.

Previous research demonstrated this timing side channel for one-shot measurements, but lacked the ability to continuously monitor user activity because probing the cache would cache the attacker's own lookups, contaminating future measurements. Concurrent work at USENIX Security 2025 explored a similar attack vector but focused on router caches rather than the local OS-level DNS cache. The local cache is a more attractive target because it remains exploitable even when users employ VPNs, configure alternative DNS servers, or use DNS over TLS -- the attack interacts only with local software, not network traffic.

The primary DNS resolver studied is systemd-resolved, which is the default on most mainstream Linux distributions including Ubuntu. The researchers also examined macOS and Windows, finding varying degrees of exploitability across platforms.

Key Findings

▶ Watch: Scriptless attacks using CSS font alternatives (4:00)

The research establishes several critical findings across measurement and eviction capabilities:

Timing measurements are highly reliable across all execution contexts. From native code, cached vs. uncached DNS entries produce histograms with zero overlap, making classification trivial. From JavaScript, while absolute timings fluctuate due to network jitter, the relative difference between cache hits and misses remains constant and distinguishable. Even scriptless attacks using only HTML and CSS achieve similar accuracy to JavaScript-based measurements.

DNSSEC actually increases attack effectiveness. Counter-intuitively, enabling DNSSEC widens the timing gap between cached and uncached entries, making the side channel easier to exploit. This means a security-hardening measure inadvertently improves the attacker's signal.

Four distinct eviction primitives were identified, applicable in different scenarios: direct cache flushing (unprivileged on most systems), individual request flooding, large DNS response injection, and error-based eviction. The error-based primitive is particularly powerful, requiring only a single request to flush the entire cache.

The attack works cross-VM. An attacker running inside a virtual machine can monitor DNS activity on the host machine (or other VMs sharing the same resolver), achieving a 92.5% F1 score with very few false positives.

Browser-based attacks achieve approximately 80% accuracy. From JavaScript, continuous monitoring is possible with error-based eviction and browser cache bypass, though accuracy varies by target website due to differing noise profiles.

No deployed mitigations exist. Despite responsible disclosure, systemd, Chromium, and Firefox have not deployed fixes. Chrome on Linux even bypasses DNS over HTTPS protections because it reads the DNS server from /etc/resolv.conf, which on systemd-resolved systems points to localhost.

Technical Deep Dive

▶ Watch: Error-based eviction: flush entire cache with one request (10:00)

The attack has two core components: measurement and eviction.

Measurement from native code is straightforward. The resolvectl query command reports whether an entry came from cache or network, eliminating the need for timing entirely. When this command is unavailable (e.g., inside a VM or Docker container), timing-based classification works with zero overlap in the histograms.

Measurement from JavaScript requires triggering DNS lookups via fetch() requests. Since these perform full HTTP requests, noise is added. However, the Cross-Origin Resource Sharing (CORS) mechanism actually helps the attacker by blocking most cross-origin responses quickly, reducing the HTTP overhead. By plotting relative differences between cache hits and misses rather than absolute times, the jitter problem is eliminated.

Scriptless measurement uses CSS font alternatives to serialize requests without JavaScript. A font declaration with three alternatives is crafted: the first loads from the attacker's server (starting a timer), the second attempts the target domain (triggering DNS resolution), and the third returns to the attacker's server (stopping the timer). When each font fails to load, the browser proceeds to the next alternative, creating a serialized timing measurement entirely through CSS.

For eviction, the systemd-resolved cache holds a maximum of 4,096 entries and evicts the entry with the lowest TTL first. The individual request flooding primitive exploits this by sending requests for random domains with maximum TTL values, pushing all existing entries out. However, this fills the cache with attacker-controlled entries that would immediately evict legitimate user entries (which typically have lower TTLs). The researchers solve this with a "hole punching" technique: they craft a DNS response containing many resource records with very short (1-second) TTLs. Systemd-resolved evicts enough cache entries to fit all records at once, and these short-TTL entries then quickly expire, leaving empty slots for legitimate domains to occupy.

The error-based eviction primitive is the most elegant. Sending an oversized DNS response causes the upstream DNS server to return a SERVFAIL or timeout. Systemd-resolved retries three times, then switches to the backup DNS server, flushing the entire cache in the process. This requires just one request and is extremely fast, though it was inadvertently mitigated in newer systemd versions that implement Extended DNS Errors (EDE) -- which, as noted in the Q&A, technically violates the RFC by making decisions based on unauthenticated error codes.

Demo / Proof of Concept

▶ Watch: End-to-end attacks: cross-VM and JavaScript results (12:00)

Two end-to-end attack scenarios were demonstrated in the paper:

Cross-VM attack: A Python script running inside a VM continuously monitors the DNS cache of the host machine. The victim accesses a random subset of 100 domains, and the attacker uses error-based eviction for cache flushing. The attack achieves an F1 score of approximately 92.5% with very few false positives, demonstrating that VM isolation does not protect against this side channel.

JavaScript browser attack: The attacker operates entirely from a web page loaded in the victim's browser. JavaScript fetch requests measure DNS cache state, error-based eviction flushes the systemd cache, and additional requests bypass the browser's own DNS cache (which is partitioned by origin due to network state partitioning). This achieves approximately 80% accuracy, with DNSSEC slightly improving performance. Accuracy varies significantly by target website, as different sites generate different amounts of noise from their normal request patterns.

Defensive Implications

▶ Watch: Q&A: router caches, CNAME redirections, and RFC violations (16:00)

The defensive outlook for this vulnerability is notably bleak. The researchers conducted responsible disclosure to all major affected parties, and the responses highlight a fundamental accountability gap:

Systemd considers the DNS resolver local-only and therefore not a security boundary, even though the researchers demonstrated remote exploitation from browsers. Chromium acknowledged the issue but stated there is no practical fix without significant performance or compatibility drawbacks. Firefox defers responsibility to the local resolver. Only Apple committed to addressing the issue in a future update, without specifics.

DNS over HTTPS (DoH) should theoretically prevent the attack by having the browser resolve DNS independently, but Chrome on Linux reads its DNS server configuration from /etc/resolv.conf, which on systemd-resolved systems points to 127.0.0.53 (localhost). This completely bypasses DoH's protections. Firefox has DoH disabled by default in all but four countries.

Defenders should consider the following mitigations: enabling DoH in Firefox where possible, monitoring for anomalous DNS query patterns that could indicate cache flooding, limiting the ability of untrusted code to make arbitrary DNS requests, and evaluating whether systemd-resolved's cache size and eviction policies can be hardened. Organizations running multi-tenant systems or containers on shared hosts should be particularly aware that DNS cache side channels can leak browsing activity across isolation boundaries.

Key Takeaways

  • DNS cache timing attacks can be performed continuously using newly discovered eviction primitives, enabling persistent surveillance of user browsing activity
  • The attack works from native code (92.5% F1 score), JavaScript (~80% accuracy), and even scriptless HTML/CSS with no JavaScript required
  • Systemd-resolved's 4,096-entry cache with TTL-based eviction enables practical cache flooding and "hole punching" techniques
  • DNSSEC paradoxically makes the attack easier by widening the timing gap between cached and uncached entries
  • Error-based eviction can flush the entire DNS cache with a single request on Ubuntu 24.04 and other systems running older systemd versions
  • DNS over HTTPS is ineffective on Chrome/Linux because it reads resolver config from /etc/resolv.conf pointing to localhost
  • No vendor has deployed fixes despite responsible disclosure, creating a persistent privacy risk across Linux desktops

About the Speaker(s)

Hannes Weissteiner is a researcher presenting at NDSS Symposium. His work focuses on cache-based side channel attacks, particularly in the DNS resolution infrastructure. The research demonstrates strong expertise in systems-level security, browser internals, and DNS protocol mechanics, with practical attack development spanning native code, JavaScript, and CSS-only exploitation vectors.

Reviews

Dr. Zero (Offensive Security Researcher) — STRONG ACCEPT

A technically rigorous side-channel attack that turns the local DNS cache into a continuous browsing surveillance tool. The eviction primitives are novel, the cross-VM and browser-based PoCs are solid, and the error-based single-request cache flush on systemd-resolved is genuinely elegant. This is real systems security research with working exploits and measurable results.

Heather Calloway (CISO) — STRONG

A well-executed privacy side-channel attack that demonstrates continuous browsing surveillance through DNS cache timing. While the technical work is solid, the practical impact for enterprise defenders is moderate -- this primarily affects Linux desktop environments and requires either local code execution or getting the user to visit an attacker-controlled page. The vendor non-responses highlight a concerning accountability gap in the DNS resolver ecosystem.

→ Top-rated talks at Network and Distributed System Security (NDSS) Symposium 2026

All talks from Network and Distributed System Security (NDSS) Symposium 2026