Famous Chollima Targets PHP Developers Through Compromised Packagist Package
A targeted supply chain attack attributed to Famous Chollima compromised a development branch of the legitimate PHP package 'roberts/leads' on Packagist. The attackers injected an obfuscated JavaScript loader into a tailwind.js configuration file, which utilizes blockchain RPC infrastructure as a dead drop to retrieve and execute secondary payloads like DEV#POPPER RAT, likely as part of a Contagious Interview developer lure.
- sha256522b28a2f78771715497ba53729d4ab9a50e982322c391379f3bddf7c8cb363fSHA-256 hash of the compromised package archive.
- sha25696afdba882046385242cbed46871e41147c8055c5d9eff7460847b2c01a77dc3SHA-256 hash of the malicious tailwind.js file containing the obfuscated loader.
- urlhxxps://github[.]com/roberts/leads/blob/drewroberts/feature/test-case/tailwind[.]jsURL hosting the affected tailwind.js file in the compromised GitHub branch.
Detection / HunterGoogle
What Happened
Security researchers discovered malicious code hidden inside a specific test version of a legitimate software package used by PHP developers. The attackers, believed to be a North Korean group known as Famous Chollima, likely used this poisoned package as part of fake job interviews to trick developers into downloading it. Once installed, the hidden code uses cryptocurrency networks to secretly download and run more dangerous malware on the developer's computer. This could allow the attackers to steal sensitive company passwords, source code, and other private data. Developers should be extremely cautious when asked to install specific, non-standard software versions during job interviews or coding tests.
Key Takeaways
- Malicious obfuscated JavaScript was discovered hidden within a tailwind.js file in a specific development branch of the legitimate 'roberts/leads' PHP package on Packagist.
- The loader utilizes public blockchain RPC infrastructure (TRON, Aptos, BNB Smart Chain) as a dead drop to retrieve encrypted secondary payloads.
- The attack is highly targeted, likely utilizing 'Contagious Interview' lures where developers are instructed to clone or install the specific poisoned branch.
- The payload executes via eval() and can launch a detached, hidden Node.js child process to run secondary malware like DEV#POPPER RAT or BeaverTail.
- The malicious code is concealed using massive whitespace gaps, making it difficult to spot during casual code review.
Affected Systems
- PHP developer environments
- Node.js developer environments
- CI/CD pipelines
Attack Chain
The attack begins with a developer being lured into installing a specific, compromised development branch of a PHP package (roberts/leads) during a fake job interview or coding test. Upon installation or execution of the project build steps, an obfuscated JavaScript payload hidden within tailwind.js is triggered. This loader queries public TRON and Aptos blockchain RPC services to retrieve encrypted payload pointers from transaction data. The retrieved data is decrypted using hardcoded XOR keys and executed via eval() or a detached Node.js child process, ultimately delivering secondary malware like DEV#POPPER RAT or BeaverTail to steal credentials and source code.
Detection Availability
- YARA Rules: No
- Sigma Rules: No
- Snort/Suricata Rules: No
- KQL Queries: No
- Splunk SPL Queries: No
- EQL Queries: No
- Other Detection Logic: Yes
- Platforms: grep, git
The article provides local bash commands using
grepandgit grepto scan repositories for specific campaign markers and malicious strings associated with the loader.
Detection Engineering Assessment
EDR Visibility: Medium — EDRs can detect detached Node.js processes and suspicious child process spawning, but the initial execution happens within the context of normal developer build tools, which are inherently noisy and often allowlisted. Network Visibility: Medium — Network monitoring can spot unusual outbound connections to blockchain RPC nodes (TRON, Aptos) from developer endpoints, though the traffic is HTTPS and blends with legitimate Web3 development if applicable to the organization. Detection Difficulty: Moderate — The malicious code is heavily obfuscated and hidden in standard configuration files using excessive whitespace. Detecting it requires identifying anomalous Node.js behavior or unexpected connections to blockchain infrastructure.
Required Log Sources
- Process Creation (Event ID 4688 / Sysmon Event ID 1)
- Network Connections (Sysmon Event ID 3)
- Command Line Logging
Hunting Hypotheses
| Hypothesis | Telemetry | ATT&CK Stage | FP Risk |
|---|---|---|---|
| Consider hunting for Node.js processes making outbound network connections to known blockchain RPC endpoints (e.g., trongrid.io, aptoslabs.com) if Web3 development is not expected in your environment. | Network Connections, DNS Logs | Command and Control | High in Web3/blockchain development environments; Low otherwise. |
Look for Node.js processes spawning detached child processes with hidden windows (windowsHide: true), especially when executing inline scripts via node -e. | Process Creation, Command Line Logging | Execution | Medium |
Control Gaps
- Standard SAST/DAST tools may miss payloads hidden via excessive whitespace and obfuscation in configuration files.
- Lack of strict egress filtering on developer workstations allows connections to arbitrary public APIs.
Key Behavioral Indicators
- Node.js executing inline scripts with
node -econtaining campaign markers likeglobal['!']. - Unexpected horizontal scrolling or massive whitespace gaps in configuration files like
tailwind.js.
False Positive Assessment
- Low for the specific file hashes, XOR keys, and campaign markers provided. Medium to High for network connections to blockchain APIs if the organization engages in Web3 development.
Recommendations
Immediate Mitigation
- Verify against your organization's incident response runbook and team escalation paths before acting.
- Consider scanning local repositories and CI/CD environments for the provided campaign markers (e.g.,
global['!']='9-0264-2') using the suggested grep commands. - If the compromised package version was executed, evaluate whether to rotate all potentially exposed credentials, including CI secrets, SSH keys, and cloud tokens.
Infrastructure Hardening
- Evaluate whether to restrict CI/CD secrets to the minimum required scope and avoid exposing long-lived credentials to branch builds.
- Consider implementing egress network filtering on build servers to block unexpected connections to public blockchain RPC nodes.
User Protection
- Consider enforcing dependency pinning for known good versions and restricting the use of development branches (
dev-*) in package managers. - If supported by your tooling, evaluate implementing pre-commit or pre-build hooks that scan for heavily obfuscated JavaScript or excessive whitespace in configuration files.
Security Awareness
- Consider training developers to treat unfamiliar build instructions or specific branch checkouts during interviews or coding tests as high-risk activities.
- Evaluate adding 'Contagious Interview' lure awareness to your security training program, emphasizing the risks of running untrusted code on corporate devices.
MITRE ATT&CK Mapping
- T1195.002 - Supply Chain Compromise: Compromise Software Supply Chain
- T1204.002 - User Execution: Malicious File
- T1059.007 - Command and Scripting Interpreter: JavaScript
- T1027 - Obfuscated Files or Information
- T1102.001 - Web Service: Dead Drop Resolver
- T1105 - Ingress Tool Transfer
Additional IOCs
- Command Lines:
- Purpose: Victim lure instructions to install the compromised dev package | Tools:
composer| Stage: Initial Access |composer require roberts/leads:dev-drewroberts/feature/test-case - Purpose: Victim lure instructions to clone the compromised repository branch | Tools:
git| Stage: Initial Access |git checkout drewroberts/feature/test-case - Purpose: Launch a hidden detached Node.js process for the second-stage payload | Tools:
node,child_process| Stage: Execution |require("child_process").spawn("node", ["-e", "global['_V']='A9-0264-2';
- Purpose: Victim lure instructions to install the compromised dev package | Tools:
- Other:
0xbe037400670fbf1c32364f762975908dc43eeb38759263e7dfcdabc76380811e- Aptos fallback identifier used for payload retrieval.0x3f0e5781d0855fb460661ac63257376db1941b2bb522499e4757ecb3ebd5dce3- Aptos fallback identifier used for payload retrieval.2[gWfGj;<:-93Z^C- Hardcoded XOR key used to decrypt the first-stage payload.m6:tTh^D)cBz?NM]- Hardcoded XOR key used to decrypt the second-stage payload.6c5c3c7655ce76399af11126b7e9a9058eb2e45d- Observed malicious branch commit hash.global['!']='9-0264-2'- Campaign marker found in the obfuscated JavaScript.
Related
- Malicious Postinstall Hook Found Across 700+ GitHub Repositories, Including Packagist and Node.js Projects·3
- pnpm 11 Adds Supply Chain Protection Defaults for Minimum Release Age and Exotic Subdependencies·3
- North Korea’s Contagious Interview Campaign Spreads Across 5 Ecosystems, Delivering Staged RAT Payloads·3