Unique 0-click deanonymization attack targeting Signal, Discord and hundreds of platform
hi, i’m daniel. i’m a 15-year-old high school junior. in my free time, i hack billion dollar companies and build cool stuff.
3 months ago, I discovered a unique 0-click deanonymization attack that allows an attacker to grab the location of any target within a 250 mile radius. With a vulnerable app installed on a target’s phone (or as a background application on their laptop), an attacker can send a malicious payload and deanonymize you within seconds–and you wouldn’t even know.
I’m publishing this writeup and research as a warning, especially for journalists, activists, and hackers, about this type of undetectable attack. Hundreds of applications are vulnerable, including some of the most popular apps in the world: Signal, Discord, Twitter/X, and others. Here’s how it works:
By the numbers, Cloudflare is easily the most popular CDN on the market. It beats out competitors such as Sucuri, Amazon CloudFront, Akamai, and Fastly. In 2019, a major Cloudflare outage knocked most of the internet offline for over 30 minutes.
One of Cloudflare’s most used feature is Caching. Cloudflare’s Cache stores copies of frequently accessed content (such as images, videos, or webpages) in its datacenters, reducing server load and improving website performance (https://developers.cloudflare.com/cache/).
When your device sends a request for a resource that can be cached, Cloudflare retrieves the resource from its local datacenter storage, if available. Otherwise, it fetches the resource from the origin server, caches it locally, and then returns it. By default, some file extensions are automatically cached but site operators can also configure new cache rules.
Cloudflare has a vast global presence, with hundreds of datacenters in 330 cities across 120+ countries—an estimated 273% more datacenters than Google. In the U.S. East region, for example, the nearest datacenter to me is less than 100 miles. If you live in a developed country, there’s a good chance the nearest datacenter to you is less than 200 miles from you.
A few months ago, I had a lightbulb moment: if Cloudflare stores cached data so close to users, could this be exploited for deanonymization attacks on sites we don’t control?
You see, Cloudflare returns information about a request’s cache status in the HTTP response.
cf-cache-status
can be HIT
/MISS
and cf-ray
includes the airport code for the closest airport to the datacenter that handles the request (in my case, IAD).
If we can get a user’s device to load a resource on a Cloudflare-backed site, causing it to be cached in their local datacenter, we can then enumerate all Cloudflare datacenters to identify which one cached the resource. This would provide an incredibly precise estimate of the user’s location.
There was a one major hurdle I had to get through before I tested this theory.
You can’t simply send HTTP requests to individual Cloudflare datacenters. For “security purposes” (presumably DDoS protection), all Cloudflare IP ranges are strictly anycast. All TCP connections opened to their network are always handled by the nearest available datacenter to you, there’s no way you can ask a datacenter in Canada to handle your request if you live in the US.
However, after some research, I found a forum post (https://community.cloudflare.com/t/how-to-run-workers-on-specific-datacenter-colos/385851) from a community member showing me exactly how. The author shared a bug he found to send requests to specific Cloudflare datacenters with Cloudflare Workers.
I’m still not 100% sure of the specifics of this bug, but using an IP range used internally by Cloudflare WARP (Cloudflare’s VPN client), we could ask certain datacenters to handle HTTP requests. Normally, this IP range blocked inbound connections from external IP addresses but requests sent from Workers could bypass this since the connection would originate from inside Cloudflare’s network.
I spent a few minutes reading their post and I quickly spined up a tool for this: Cloudflare Teleport (https://github.com/hackermondev/cf-teleport). Certain IP ranges corresponded to different datacenters (https://github.com/hackermondev/cf-teleport/blob/main/scripts/data/colos.json).
Cloudflare Teleport is a proxy powered by Cloudflare Workers that redirects HTTP requests to specific datacenters. For example, https://cfteleport.xyz/?proxy=https://cloudflare.com/cdn-cgi/trace&colo=SEA would proxy a HTTP GET request to https://cloudflare.com/cdn-cgi/trace specifically to a Seattle (SEA) datacenter.
Cloudflare would end up completely patching this bug a few months later, making this tool obsolete, but more on that later. For a majority of my initial, I used this tool.
As soon as the Cloudflare Teleport tool was complete, I was able to confirm my theory. I coded a simple CLI program that would send an HTTP GET request to a specified URL and list all datacenters that had the resource cache and its age.
For my first test, I used Namecheap’s favicon (https://www.namecheap.com/favicon.ico). This resource has Cloudflare Caching enabled, it’s just a simple static image of their logo. (This was the quickest site I could find that didn’t have rigorous bot protection):
Boom, it worked. Namecheap had configured their cache age extremely low (5 minutes) but I was able to see every datacenter that had cached the their site’s favicon in the last 5 minutes. Since everytime you load their site, your browser automatically downloads this favicon, this means a user from each one of this locations has visited the Namecheap.com site within the 5 minutes with the last visit from Tokyo, Japan.
This was just meant to be a simple test and there’s almost no impact here, but with this I confirmed my theory. This proved the concept of using Cloudflare caching for deanonymization attacks.
Signal, an open-source encrypted messaging service, is widely used by journalists and activists for its privacy features. Internally, the app utilizes two CDNs for serving content: cdn.signal.org
(powered by CloudFront) for profile avatars and cdn2.signal.org
(powered by Cloudflare) for message attachments.
When a user sends an attachment (e.g., an image) on Signal, it is uploaded to cdn2.signal.org. Once the recipient opens the conversation, their device automatically downloads the attachment. Since Cloudflare caching is enabled for these URLs, an attacker can use the cache geolocation method to pinpoint the recipient’s location.
The https://cdn2.signal.org/attachments/*
path is configured to cache responses with Cloudflare. This means once a user’s device automatically downloads an attachment, it’s possible for an attacker to run a cache geolocation attack to find out which local datacenter they’re near–similar to how law enforcement track mobile devices through cell phone towers.
To test this, I quickly patched the Signal desktop app to remove SSL pinning and configured Burp to intercept and view HTTP requests/responses sent through the app.
This ensures that the app doesn’t download attachments uploaded from the our side (the attacker) since that would cache them to our local datacenter and pollute the results. The best way I found to do this with Burp is to configure intercept rules for attachments, then leave request intercept on and deny all requests.
This should work with any attachment but images are automatically downloaded when the user opens the conversation so they work best. I used a simple 1×1.png image for this test. The upload request is sent to Signal’s CDN and you can see the attachment url in Burp once we send the attachment in the conversation and Signal uploads it (ex. https://cdn2.signal.org/attachments/UjLld11tvaL16M8mrd86).
After the targets opens the conversation (verify this with read recipts), their device should download the attachment which in turn causes Cloudflare to cache the file in a local datacenter.
I ran this attack on myself, used the CLI tool I mentioned earlier with the attachment url and found local datacenters that had cached the attachment.
In my case, I’m in New York and one of the closest datacenters to me is Newark, NJ (EWR) which is about 150 miles from my actual coordinates.
With an innocent-looking attachment, an attacker can deanonymize users and find their location within an approximate radius.
Here’s where things get interesting. Although the 1-click method works, it requires the user to open the Signal conversation. Is it possible to run this attack without a single user interaction? Enter push notifications.
Signal’s mobile app has 3 push notification settings.
Push Notifications are triggered if the user receives a message while not actively on the Signal app. By default, the mobile app includes the author, and message when it sends a push notification to your device.
The image shown on the right of the notification is the attachment sent with the message from Signal.
If the target has push notifications enabled (which it is by default), they don’t even have to open the Signal conversation for their device to download the attachment. Once the push notification is sent to their device, it automatically downloads the image from Signal’s CDN triggering the local datacenter to cache the response.
An attacker can run this deanonymization attack any time and grab a user’s current location without a single interaction.
Signal, like Telegram, is used by journalists, activists, whisteblowers from all over the world. The potiental for this attack is massive. This attack can be used to track Signal accounts, correlate identities, find employees meeting with journalists and much more.
During my research, another app I found vulnerable to this type of attack is Discord. Discord is a free app that allows users to communicate with each other through text, voice, and video. Although the app is targeted towards gamers, Discord has been in the news recently this past year for facilitating government leaks and Discord hosts a significant portion of cybercrime on the internet.
The 1-click aspect is very simple and fairly similar to Signal, I would say the impact is even wider with Discord. Discord allows users with a Nitro subscription (their $9.99/mo premium service) to use custom emojis in a variety of places: Messages, User Presence, Channels, etc. These custom emojis are loaded from Discord’s CDN and are configured to be cached on Cloudflare. An attacker can use the same deanonymization attack with Signal to deanonymize users.
So, instead of sending an attachment in a Discord channel, an attacker can display a custom emoji in their user status and simply wait for the target to open their profile to run a deanonymization attack.
I’ve disclosed the entire HackerOne report I sent to Discord which has specific details, but I want to focus on the 0-click aspect here.
In Discord, mobile push notifications are sent for a variety of events (not just for messages recieved like Signal). For example, sending a friend request to a Discord user triggers a push notification on the user’s mobile device.
Interestingly, even if the user is actively on Discord, friend request notifications are always sent to the user’s mobile device.
How would a deanonymization attack be used with a friend request notification? Well, take a look at the notification.
When you recieve a friend request and Discord sends the notification to your device, it includes the user’s avatar url to be shown with the notification. Your phone