Node.js as a Portable Attack Vector in Phishing Campaigns
Attackers are dropping standalone Node.js runtimes into user space to bypass security controls and run persistent implants.
Phishing campaigns are moving beyond simple credential harvesting and macro-enabled Office documents. A sophisticated campaign targeting hospitality organizations across Europe and Asia since April 2026 highlights a highly effective evasion tactic: bringing a portable, legitimate runtime to execute malicious code entirely in user space.
By dropping a standalone Node.js runtime, attackers bypass the need for pre-installed dependencies and evade traditional binary-centric security systems. This technique, coupled with clever delivery methods, presents a unique challenge for security teams and software developers alike.
The Mechanics of Authentication Laundering
To get the malicious payload onto victim machines, the threat actors use a technique called authentication laundering. Instead of sending phishing emails from newly registered domains that would fail basic email authentication checks, they route messages through trusted, legitimate services.
Specifically, the operators use the email notification infrastructure of Calendly and Google's URL redirect service (share.google). Because the emails originate from authorized infrastructure, they successfully pass SPF, DKIM, and DMARC checks. Standard email filters see a valid, authenticated message from a trusted sender.
[Calendly Notification] -> [Google Redirect] -> [Cloudflare-fronted .cfd Domain] -> [ZIP Download]
The email contains a link that routes the victim through a multi-hop chain, ending at a freshly registered .cfd domain protected by a Cloudflare Turnstile challenge. This challenge serves a dual purpose: it makes the page look legitimate to the user and acts as an anti-analysis barrier to block automated security crawlers. Once through, the user downloads a ZIP file named photo-<numbers>.zip containing a malicious shortcut file.
The Bring-Your-Own-Runtime Strategy
The core of this attack lies in how the payload executes. The ZIP archive contains a shortcut file masquerading as an image, using names like IMG-<numbers>.png.lnk in the first wave and PHOTO-<numbers>.png.lnk in the second. The file sizes remain consistent, between 1,989 and 2,079 bytes, indicating the use of a standardized builder tool.
When the victim opens this shortcut, it triggers a multi-stage execution chain:
- PowerShell Execution: The LNK file launches PowerShell. The script uses BigInt arithmetic to decode a hidden download URL and pulls a secondary
.ps1script to the%TEMP%directory. - Dynamic Compilation (Wave 2): In the second wave of the campaign, the PowerShell downloader triggers dynamic .NET DLL compilation using
csc.exe(the C# compiler) to further obfuscate the execution path. - Runtime Delivery: The script downloads a legitimate, official Node.js v24.13.0 runtime directly from
nodejs.organd drops it into user space (AppData\Local\Nodejs). - Implant Execution: The dropped Node.js binary is then used to run a JavaScript-based implant tracked as TonRAT.
Using Node.js as an execution environment is a deliberate, tactical choice. JavaScript is highly expressive, cross-platform, and easy to obfuscate. Because the runtime itself is a digitally signed, legitimate binary from a trusted source, endpoint detection and response (EDR) agents are less likely to flag its execution. The malicious behavior is confined to the JavaScript files it runs, which are harder for traditional static antivirus engines to analyze than compiled Windows executables.
Inside the TonRAT Implant
Once active, TonRAT establishes a persistent foothold and connects back to its command-and-control (C2) infrastructure. It avoids static domain blocklists by resolving its C2 domains dynamically through the TON blockchain API.
After resolving the target address, the implant opens an encrypted WebSocket channel. Security analysts have observed the implant beaconing to fixed IP addresses over non-standard ports, including 8443, 8445, 8453, 5555, and a range from 56001 to 56003.
Additionally, the implant has been observed running headless browser automation using the flags --headless --no-sandbox, performing geolocation checks via ip-api.com, and executing forced system shutdowns using cmd /c shutdown -s -t 0.
Defensive Strategies and Detection
For developers and system administrators, defending against this style of attack requires shifting focus from file signatures to behavioral analysis. Because the Node.js binary is legitimate, blocking the file hash of node.exe is ineffective and could disrupt legitimate development work.
1. Monitor User-Space Execution
There are very few scenarios where a legitimate Node.js binary should run out of AppData\Local or ProgramData, especially when spawned by shell interpreters like PowerShell or cmd.
You can hunt for this behavior using endpoint query languages like KQL:
DeviceProcessEvents
| where ProcessCommandLine has "node.exe"
| where FolderPath has_any ("\\AppData\\Local\\", "\\ProgramData\\")
| where InitiatingProcessFileName in~ ("powershell.exe", "cmd.exe", "explorer.exe")
2. Restrict Network Connections
Node.js processes running from user-writable directories should not be making outbound connections to non-standard ports (such as 8443, 8445, or the 56000 range), nor should they be querying blockchain APIs. Implementing local firewall rules or EDR policies that restrict outbound network access for binaries running in user space can break the C2 channel.
3. Thorough Remediation
If a machine is compromised, cleaning up only the active process or a single registry key is insufficient. The campaign uses a dual-persistence mechanism. It writes a RunOnce entry pointing to ProgramData and a standard Run key for Node.js in AppData\Local\Nodejs. Remediation must target both registry paths, the downloaded Node.js runtime, and the associated JavaScript files. Leaving any of these components intact allows the implant to reinstall itself on the next boot.
Sources & further reading
- Microsoft Warns of Photo ZIP Phishing Campaign Targeting Hotels with Node.js Implant — thehackernews.com
- Photo ZIP campaign targeting hospitality industry delivers Node.js implant for persistent access | Microsoft Security Blog — microsoft.com
- Photo ZIP Campaign Targeting Hospitality Industry Delivers Node.js Implant For Persistent Access | ARROWWOOD — arrowwoodservices.com
- Microsoft Warns of Photo ZIP Phishing Campaign Targeting Hotels with Node.js Implant - InfoSec Today — infosectoday.io
- Photo ZIP campaign targeting hospitality industry delivers Node.js implant for persistent access - Live Threat Intelligence - Threat Radar | OffSeq.com — radar.offseq.com
Ji-ho covers the increasingly tangled overlap between cloud architecture and security, drawing on a background as a penetration tester to keep his reporting grounded in real-world attack paths. He never lets a vendor claim go unquestioned and insists that every buzzword come with a proof of concept.
Discussion 0
No comments yet
Be the first to weigh in.