Supply chain attacks are often associated with sophisticated nation-state actors compromising massive open-source libraries. But sometimes, they are as simple as a forgotten <script> tag.

1. The $5 Gamble#

It started during a bug bounty hunt on Livesport. While mapping the application, I noticed that they were serving content which loaded a script from hitrang.com, a domain that appeared to be completely dead. I couldn’t force the main application to actually execute the script, but the reference was there.

Normally, I would report the dangling reference and move on. But I was curious. If I owned that domain, could I achieve a Stored XSS or a broader supply chain compromise? I checked the domain registry. It wasn’t explicitly for sale, but it was expiring. I went to DropCatch, a domain backordering service, and placed a $5 gamble on it.

A short while later, the domain was mine.

Domain Purchase Receipt

I set up a quick listener to see if Livesport would eventually call out to it. I reported the dangling script reference via their Bug Bounty program anyway. They quickly removed the script, and I was awarded a small bounty. Great team over there.

I assumed that was the end of the story. But when I checked my Cloudflare Analytics a few weeks later, I saw a massive, continuous stream of traffic that had absolutely nothing to do with Livesport.

Cloudflare Traffic Spike

2. Investigating the Traffic#

The volume was surprising. There were roughly 94,000 requests per month from around 8000 unique IP addresses.

Because Cloudflare’s standard analytics only hold detailed logs for a limited time, I deployed a lightweight Cloudflare Worker to intercept the requests, extract the metadata (User-Agents, Referers, Country), and forward it directly to a private Discord webhook.

Note: The ideal approach would probably be storing this telemetry directly on the edge using Cloudflare D1.

Here is the simplified Worker I used:

Cloudflare Worker Logger
export default {
  async fetch(request, env, ctx) {
    const logEntry = {
      timestamp: new Date().toISOString(),
      victim: {
        ip: request.headers.get('CF-Connecting-IP'),
        country: request.headers.get('CF-IPCountry'),
        ua: request.headers.get('User-Agent'),
      },
      request: {
        method: request.method,
        url: request.url,
        headers: Object.fromEntries(request.headers)
      }
    };

    const discordUrl = "https://discord.com/api/webhooks/...";
    ctx.waitUntil(fetch(discordUrl, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ content: "```json" + JSON.stringify(logEntry, null, 2).substring(0, 2000) + "```" })
    }));

    return new Response('console.log("Security Research");', {
      headers: { 'content-type': 'application/javascript' },
    });
  },
};

After letting it run for some time, I exported the discord logs and stripped out the discord-specific metadata, and started digging into the data using jq.

I wanted to know exactly who was calling this domain.

Extracting Top Referers
cat traffic.json | jq -r '.[] | .request.headers.referer?' | sort | uniq -c | sort -nr | head -n 10

The output was revealing:

Output
  32245 https://www.ljubavni-sastanak.com/
   1427 https://www.cvecara-online.com/
    921 http://www.perast.com/
    461 https://ljubavni-sastanak.com/
    ...

The traffic wasn’t coming from modern tech giants. It was originating from legacy Balkan websites. The top referer was an old Serbian dating site (ljubavni-sastanak.com), followed by a flower shop (cvecara-online.com) and a regional portal for Perast, Montenegro.

To confirm these weren’t just automated scanners or botnets blindly crawling old links, I checked the User-Agents and Geographies:

Extracting Top Countries
cat traffic.json | jq -r '.[] | .victim.country?' | sort | uniq -c | sort -nr | head -n 5
Output
  19111 US
  13408 RS  (Serbia)
   4745 BA  (Bosnia & Herzegovina)
   4522 HR  (Croatia)
   3903 SG

Next, I examined the User-Agents to verify if this traffic was coming from real devices. One specific string immediately looked suspicious. It attempted to mimic an Android browser but contained obvious typos, starting with Mozlila/5.0 instead of Mozilla/5.0 and misspelling “Build” as “Bulid” and “Mobile” as “Moblie”.

Suspicious User Agent
Mozlila/5.0 (Linux; Android 7.0; SM-G892A Bulid/NRD90M; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/60.0.3112.107 Moblie Safari/537.36

While this specific signature was clearly an automated scraper or bot, filtering out this internet radiation showed something interesting. The vast majority of the remaining requests were real people.

Based on the domain name (hitrang.com) and the regional concentration, it became clear what happened. This was likely a popular analytics or “toplist” service used by Balkan web developers around 2010 to 2015.

The service had died and the domain had expired, but the <script> tags were permanently cemented into the HTML headers of these active, albeit aging, websites.

3. The Vulnerability#

The core issue lies in how websites trust external resources. The victim websites still had this legacy code embedded in their HTML source:

Dangling Script Reference
<script type="text/javascript" src="http://storage.hitrang.com/js/trafic.js"></script>

Because I owned hitrang.com, I could serve whatever I wanted from the /js/trafic.js path. By trusting a third-party domain without verification, these websites granted full execution privileges to anyone who registered the expired domain.

This is a textbook example of a Supply Chain Attack via a dangling domain. It is highly similar in concept to the massive Polyfill.io supply chain attack, where a widely trusted JavaScript CDN domain changed hands and started serving malicious code to hundreds of thousands of websites.

4. Impact & Remediation#

If I were a malicious actor, I essentially had persistent, Stored XSS access to thousands of daily users. With full DOM access, the attack possibilities are vast, ranging from injecting fake login overlays to steal credentials, to silent redirects or crypto-mining.

To resolve the issue, I emailed the administrators of the affected legacy websites, advising them to remove the dead <script> tags entirely.

For modern applications, developers can prevent third-party JavaScript hijacking by using Subresource Integrity (SRI). By adding an integrity attribute, the browser only executes the script if its cryptographic hash matches the expected value:

Subresource Integrity
<script src="https://example.com/script.js" integrity="sha384-..." crossorigin="anonymous"></script>

Ultimately, I mitigated the issue by serving a benign JavaScript file that only logged a message to the console. But this was an interesting lesson in how easily legacy infrastructure can become a mass-exploitation vector.

Note: All traffic data collected during this research were used solely for statistical analysis regarding the scope of the vulnerability and were permanently deleted immediately after the investigation.