Unit 2: Reading and checking files · Lesson 6 of 6 · 20 min

Case file: a script you do not control

A single third-party script tag gave a stranger code on every page. Find yours and pin it.

mission

You are
You are the analyst reviewing what the shop's pages load.
Situation
The integrity check failed on index.html. The change added a script tag that loads code from another company's server on every visit.
Goal
Find every external script, check whether it is pinned, and produce the pin for the local one.
Hand in
A short list: script, host, pinned or not, and the fix.

case file

Polyfill.io Domain Takeover

polyfill.io (websites embedding it) · 2024

In February 2024 the polyfill.io domain and GitHub account were acquired by a company named Funnull, prompting warnings from the original author and from Cloudflare. In June 2024 Sansec reported that the service was injecting malicious code into more than 100,000 websites that loaded the script, redirecting some mobile users to scam/betting sites. The registrar later put the domain on hold, and CDN providers offered mirrors.

What went wrong

Websites loaded executable JavaScript from a third-party domain at runtime, so a change of domain ownership gave the new owner code execution in every visitor's browser.

What would have stopped it

  • Self-host third-party scripts or pin them with Subresource Integrity hashes rather than loading mutable scripts from external domains.
  • Use a Content Security Policy that limits allowed script sources, and review it when dependencies change.
  • Monitor ownership and reputation changes for external domains your site depends on, and remove dependencies no longer needed.

What defenders could have seen

  • Client-side script monitoring flagging changed content from a third-party script URL.
  • CSP violation reports or user reports of unexpected redirects on mobile.
  • Threat intel alerts on domain ownership changes for embedded script hosts.

sourcessansec.iotechtarget.comblog.cloudflare.com

01

Find every script tag

learner@root-lab
grep -rn '<script' --include=*.html .
./index.html:3:<head><meta charset="utf-8"><title>Example Shop</title><script src="https://cdn.example-metrics.net/m.js"></script></head>

you should see One tag, in index.html, loading from cdn.example-metrics.net.

02

Pull out the hosts

Every external host in a src attribute can change what your visitors run.

learner@root-lab
grep -rhoE 'src="https://[^/"]+' --include=*.html . | sort | uniq -c
      1 src="https://cdn.example-metrics.net

you should see One external host.

03

Is it pinned?

Subresource Integrity puts a hash in the tag. The browser refuses the file if the hash does not match.

learner@root-lab
grep -c 'integrity=' index.html
0

you should see 0. Nothing stops that host from sending different code tomorrow.

04

Make a pin for your own script

SRI hashes are SHA-384 in base64. This is the value for the shop's own app.js.

learner@root-lab
openssl dgst -sha384 -binary assets/js/app.js | openssl base64 -A; echo
4h81cTvsL1O461b2sCPOA/JJdd19AAj2A5mN7gYbXe1sZ1kOiO7BQCN6PglNxJ/p

you should see A 64-character base64 string. It goes in the tag as integrity="sha384-...".

defender tip SRI only works for files that never change. For a script that a vendor updates daily, host a reviewed copy yourself instead.

The same script, two ways

Loaded live
<script src="https://cdn.example-metrics.net/m.js">

The owner of that domain decides what runs

Self-hosted and pinned
<script src="/assets/js/m.js"
  integrity="sha384-..."
  crossorigin="anonymous">

A copy you reviewed, refused if it changes

What a defender takes away

  1. 1Every external script is code you run but do not control.
  2. 2Pin with SRI or host a reviewed copy.
  3. 3Domains change hands; your page keeps trusting them.

Questions

0 of 3 solved

Answer each one from what you find on your lab machine.

  1. Show hint

    grep -rhoE for src="https:// and count unique hosts.