
The attackers behind the supply chain attack targeting the popular Trivy scanner are suspected of carrying out a follow-up attack that led to the compromise of numerous npm packages with a previously undocumented self-propagating worm called CanisterWorm.
The name comes from the fact that the malware uses an ICP canister, which refers to a tamper-proof smart contract on the internet computer blockchain, as a dead drop resolver. This development marks the first publicly documented exploitation of an ICP canister for the express purpose of obtaining a command and control (C2) server, said Aikido security researcher Charlie Eriksen.
The list of affected packages is below –
@EmilGroup 28 packages in scope @opengov 16 packages in scope @teale.io/eslint-config @airtm/uuid-base32 @pypestream/floating-ui-dom
This development comes less than a day after threat actors leveraged compromised credentials to publish the release of malicious Tribby, Tribby Action, and Setup Tribby, including a credential stealer. A cloud-focused cybercrime operation known as TeamPCP is suspected to be behind this attack.
The infection chain involving npm packages involves leveraging a post-installation hook to run the loader. The loader then drops a Python backdoor that is responsible for connecting to the ICP canister dead drop and obtaining a URL pointing to the next stage payload. Because dead drop infrastructure is decentralized, it is resilient and resistant to takedown efforts.
“Canister controllers can exchange URLs at any time and push new binaries to all infected hosts without touching the implant,” Eriksen said.
Persistence is established by the systemd user service. This service is configured to automatically start the Python backdoor after a 5 second delay if it terminates for any reason using the “Restart=always” directive. The systemd service disguises itself as the PostgreSQL tool (“pgmon”).
As mentioned earlier, the backdoor calls the ICP canister every 50 minutes with a spoofed browser user agent and retrieves the URL in clear text. The URL is then parsed and the executable file is retrieved and executed.
“If the URL contains youtube[.]com, the script will skip that,” Eriksen explained. “This is canister hibernation. The attacker disarms the implant by pointing the canister at the real binary, and disarms it by pointing it back to the YouTube link. Once the attacker updates the canister to point to the new URL, all infected machines will get the new binary on their next poll. The old binary will continue to run in the background because the script does not kill the previous process.”
It is worth noting that there is a similar YouTube[.]com-based kill switch has also been flagged by Wiz in connection with the Trojanized Trivy binary (version 0.69.4). This binary also accesses the same ICP canister via a Python dropper (‘sysmon.py’). At the time of writing, the URL returned from C2 is a Rickroll YouTube video.
Hacker News found that ICP Canister supports three methods: get_latest_link, http_request, and update_link. This allows threat actors to change their behavior and deliver the actual payload at any time.
In addition to this, the package comes with a “deploy.js” file that the attacker manually executes to spread the malicious payload to all packages that the stolen npm token provides access to in a programmatic manner. The worm is said to be vibe-coded using artificial intelligence (AI) tools and makes no attempt to hide its functionality.
“This is not caused by npm install,” Aikido said. “This is a standalone tool that attackers run using stolen tokens to maximize blast radius.”
To make matters worse, subsequent CanisterWorm iterations detected in ‘@teale.io/eslint-config’ versions 1.8.11 and 1.8.12 were found to self-propagate without the need for manual intervention.
Unlike “deploy.js”, which is a self-contained script that the attacker needed to run using a stolen npm token to push a malicious version of the npm package to the registry, the new variant incorporates this functionality into “index.js” within the findNpmTokens() function that is executed during the post-installation phase to collect the npm authentication token from the victim machine.
The main difference here is that the post-installation script, after installing the persistent backdoor, attempts to find all npm tokens from the developer’s environment and immediately spawns the worm using those tokens by launching “deploy.js” as a completely isolated background process.
Interestingly, the attackers allegedly replaced the ICP backdoor payload with a dummy test string (‘hello123’) to ensure that the entire attack chain was working as intended before adding the malware.
“This is the point where the attack moves from ‘compromised account exposes malware’ to ‘malware compromises more accounts and exposes itself,'” Eriksen said. “Every developer or CI pipeline that installs this package and has access to the npm token unwittingly becomes a propagation vector. The package gets infected, downstream users install them, and if any of them have the token, the cycle repeats.”
(This is a developing story. Check back for more details.)
Source link
