Understanding the Polyfill Attack (Polykill)
And some thoughts about what it shows about our tooling trends
Supply chain threats are growing. Most concerningly, it seems more and more like we’re dealing with nation level threats taking over small unmaintained open source projects. Once again, I’ve got to start by talking about Tidelift being the only company focusing on the real problem here - helping companies treat maintainers like the contractors/vendors they are. If maintainers had any financial benefit or guardrails for transitioning maintenance, and clear communication channels to their “customers,” it would go a long way to reducing our national security risk.
In this article, we’ll cover what Polykill is, what happened, how to respond it, and reflect on what tools would’ve been able to detect it. I also released a video on it.
What is Polyfill?
Polyfills are ways of hacking new features into older browsers. An easy example is older browsers not supporting `@media` queries in CSS (which tell your screen size). If someone was on a phone using a really old browser, which is not as much of an issue in our post-chrome utopia, you could run Javascript to instead figure out how to display the proper sizes and make it work anyways.
If we continue with the media queries example, Internet explorer 8 (2009) doesn’t support them, but you still want to change some things based on screen size. Using a Polyfill, developers could deliver screen size specific content to older browsers.
Polyfill’s can be implemented in a number of ways. Since polyfills were popular before widespread adoption of `npm` and other package managers, using a content delivery network (CDN) was a popular way of setting it up. At the end of the day, a polyfill just requires getting a javascript file delivered to the browser - so developers choose the easiest way of doing that.
Deliver via installing the package and delivering it to the user. This may or may not be vulnerable depending on the package - as Sonatype points out, some packages used the CDN under the hood, others didn’t.
Deliver by manually entering the CDN in the head of the document.
In summary, Polyfill is not that different from other “magic” feeling Javascript services, which should frankly alert us to the larger issue here. Even my incredibly basic homepage at Latio links to Google, Flaticon, Sentry-cdn, Cloudflare, and DataDog. These are all trusted services, but so was Polyfill for a time - it all comes down to the long term maintenance difficulties of dependency checking.
Am I vulnerable?
This attack didn’t get as much publicity as I expected, I suspect for the same reasons XZ utils didn’t, that the attack was mitigated fairly quickly upstream. Thankfully, Namecheap took down the polyfill.io domain, and Cloudflare and Fastly provided mirrors that could be swapped out to preserve functionality.
Ultimately, Namecheap is really to thank for mitigation, but it would’ve been trivial for a different less reputable hosting service to have been distributing the malicious code. While there’s not an immediate threat thanks to their actions, a few additional steps should be taken.
Check if you use cdn.polyfill.io and make sure it gets removed in case the domain goes live again in the future
Here are some of the easiest ways to check if you’re vulnerable. Reading between the lines of the vendor posts on this topic reveals the DAST sized gap in most security companies at the moment. Turns out DAST isn’t quite as dead as we thought.
Manually search your code base and website html for polyfill.io. Be sure to include your npm dependencies. This is usually easiest via either an IDE or just your Source Code Manager (SCM - usually Github or Gitlab)
Run a DAST scan
Zap scan - I found this to be the easiest with the docker one liner
Via the polykill.io website which will send you an email (run by Leak Signal, a very cool team also on the List). I ran this and it’s been a few hours without an email yet - not sure how long it takes
Run an SCA or SAST scan - no provider is claiming to have created exhaustive detection for it. A funny side effect is that most providers are using their SAST engines instead of SCA for this because it’s just searching for a string.
It’s unlikely you use these, but these domains have also been discovered as being under malicious ownership:
bootcdn.net
, bootcss.com
, staticfile.net
, staticfile.org
, unionadjs.com
, xhsbpza.com
, union.macoms.la
, newcrbpc.com
.
Check for the indicators of compromise in your logs - these would be egress network traffic by users or services that received the malicious Javscript
https://kuurza.com/redirect?from=bitget https://www.googie-anaiytics.com/html/checkcachehw.js https://www.googie-anaiytics.com/ga.js https://cdn.bootcss.com/highlight.js/9.7.0/highlight.min.js https://union.macoms.la/jquery.min-4.0.2.js https://newcrbpc.com/redirect?from=bscbc
bootcdn.net
staticfile.net
staticfile.org
unionadjs.com
xhsbpza.com
Another weirdness with this attack is that we’re used to backend vulnerabilities getting targeted via supply chain. Log4j, Solarwinds, XZ Utils were all dangerous because attackers could target and exfil internal company data. This attack instead targeted your users, scraping their data, or redirecting them to attacker owned sites without their knowledge.
Some basic research has been done at this point into what the attack was doing, it seems mostly like it was tracking user activity and trying to redirect users under specific conditions to malicious websites. We won’t ultimately know what happened for a while because the code was obfuscated.
Interesting Lessons
We were warned about the possibility of attack in February, but most people didn’t do anything. I’m not blaming them, they probably weren’t aware, because you use thousands of open source dependencies and tracking the minutiae of every one is too big a problem. To be frank, the cybersecurity ecosystem is overly dependent on “creator buzz” at the moment - big JavaScript content creators were honestly a large part of creating awareness.
Linkedin Post from February
Cloudflare post from February
Post from the maintainer in February
I’m not aware of any solutions that could’ve detected and fixed this at runtime because it would need to be done on the client side - essentially companies were serving malware without knowing it. Secure browsers and extensions would’ve been the best option. Maybe something like Contrast could rewrite the code once it was deployed, but I’m not sure how their Javascript agent works.
Only DAST solutions could’ve detected this malicious activity in the first place, hence why Sansec were the ones to discover it. Another similar tool is “script watch” from report-uri. While they focus on CSP monitoring, most companies doing this just include monitoring Javascript packages at runtime because it’s closely related. DAST isn’t quite ready for the waste bin!
A lot of vendor blogs are suggesting some wack mitigations:
Content Security Policy (CSP) wouldn’t have helped because you’d be including polyfill.io as a trusted source.
SCA scanners are unreliably building rules to look for it in older packages, and there’s no CVE for it.
SAST scanners are really just running code searches.
The supply chain problem is greater than Software Composition Analysis (SCA) and Software Bill of Materials (SBOMs). Ironically, you ask for an SBOM from SaaS companies to prevent these kinds of attacks, and yet this wouldn’t have shown up on one.
I still include supply chain under Application Security Posture Management (ASPM) because I think this attack indicates why we just want all these scanners under the same tool. At the end of the day, every supply chain attack will require some different scanning capability, which is why SAST and DAST scanners were ahead on this one.
The supply chain problem can still only be fixed at the source, by creating relationships with open source maintainers. In this case, so that the maintainer could’ve more easily gotten the word out to stop using the polyfill site once it was sold. Once again, establishing maintainer relationships is the only actual solution.
Thanks for including Aikido in the analysis James!