Security News

Cybersecurity news aggregator

đź”’
MEDIUM Vulnerabilities Reddit r/netsec

Adbleed: partially de-anonymizing VPN users with adblock filter lists

  • What: A proof-of-concept called Adbleed demonstrates how country-specific adblock filter lists can partially de-anonymize VPN users.
  • Impact: VPN users may be identifiable based on the adblock filter lists enabled in their browser, even when using a VPN.
Read Full Article →

Most people assume that using a VPN makes them anonymous online. Your real IP is hidden, your traffic is encrypted, and websites see the VPN server’s location instead of yours. We’ve already seen that this is not fully the case thanks to browser fingeprinting techniques such as the many that https://amiunique.org or the EFF can show you. But there’s one more fingerprinting vector that VPNs can’t protect against: the country-specific adblock filter lists installed in your browser . I built a proof of concept that demonstrates this. You can try it yourself at https://adbleed.eu . Most AdBlocking base lists only cover English-language ads and major international ad networks. If you’re in Germany, you probably also have EasyList Germany enabled, which blocks German ad networks like adnx.de , adition.de , and adklick.de . If you’re in France, you have Liste FR , which blocks ad6.fr , adaccess.fr , and hundreds of French-specific domains. The same goes for Italy, the Netherlands, Spain, Brazil, Russia, China, Japan, and the Nordics. Most adblockers prompt you to enable your country’s list on install, or enable it automatically based on your locale, such as AdGuard’s Automatically activate language-specific filters feature. Adblockers like uBlock Origin, Brave’s built-in blocker, and AdBlock Plus all use filter lists: big text files full of rules that tell the browser what to block. The most common one is EasyList, which has over 54,000 domain-blocking rules and is enabled by default in pretty much every adblocker. These country-specific lists block domains that are not in the base list. That difference is what makes fingerprinting possible. By figuring out which country-specific filter list your browser is using, I know something about where you are or what language you speak, even if you’re routing all your traffic through a VPN exit node in another country. The VPN hides your IP, but it doesn’t change which adblock rules your browser enforces. Detection method The detection is entirely client-side by using JavaScript running in the browser, probing whether certain domains are blocked. The technique is simple: try to load a tiny resource (a favicon) from a domain that is blocked only by a specific country’s filter list, and measure how fast the request fails. When an adblocker blocks a request, it intercepts it *before* it reaches the network stack. The image fires its onerror event almost instantly, typically in under 5 milliseconds. When there’s no adblocker blocking the domain, the request actually goes out to the network. Even if the domain doesn’t exist ( NXDOMAIN ), the DNS lookup alone takes 50-500ms. A TCP connection timeout takes even longer. That timing difference is the signal. function probeDomain(domain) { return new Promise((resolve) => { const img = new Image(); const start = performance.now(); img.onerror = () => { const timing = performance.now() - start; resolve({ domain, timing, blocked: timing < 30, // <30ms = adblocker intercepted it }); }; img.onload = () => resolve({ domain, timing: performance.now() - start, blocked: false }); img.src = `https://${domain}/favicon.ico?_=${Date.now()}`; setTimeout(() => resolve({ domain, timing: 3000, blocked: false }), 3000); }); } For each country, I probe 30 domains. If 20 or more come back as blocked (error in under 30ms), I conclude that the country’s filter list is active. The threshold of 20/30 is deliberately high: different browsers and adblockers bundle different base lists beyond the standard EasyList, and some of those lists may coincidentally block a handful of country-specific domains. A user with the actual country list enabled will easily hit 25-30 out of 30, while a false positive from overlapping base lists will typically land at 2-8. The 20/30 threshold sits comfortably between those ranges. This research was done using Brave Browser with default Shields settings. I first ran the tool without any country lists enabled to identify which domains Brave’s built-in lists already blocked, then removed those from the probe sets. If you’re testing with uBlock Origin, AdBlock Plus, or another adblocker, your false positive baseline may differ since they each ship different default lists. Compiling the signature lists The hardest part is making sure the domains being probed are actually unique to a country’s list and not in the base EasyList. If ad.doubleclick.net is in my probe set, every adblocker user would trigger it, regardless of country lists. I wrote a script that: 1. Fetches the base EasyList and extracts all 54,415 ||domain^ blocking rules 2. Fetches each country-specific list and extracts its domain rules 3. Subtracts the base EasyList set from each country set 4. Prioritizes domains with country-code TLDs ( de , fr , it , etc.) Before running the country probes, I run two sets of controls: Positive controls: domains that are in the base EasyList, like pagead2.googlesyndication.com and ad.doubleclick.net . If these aren’t blocked, the us...

Share this article