Tactics, Techniques & Procedures
Attack patterns observed in the wild, mapped to MITRE ATT&CK where applicable.
Attack patterns observed in the wild, mapped to MITRE ATT&CK where applicable.
149 techniques · page 3 of 3
Detects CrowdStrike, SentinelOne, Carbon Black, and StepSecurity Harden-Runner.
Pushes oidc-<hex> branches that rewrite the trusted CI workflow, exchanges OIDC for npm publish tokens, repackages legit tarballs with a malicious preinstall, re-signs via Sigstore (Fulcio/Rekor), and republishes with valid provenance.
GitHub API calls use User-Agent python-requests/2.31.0 to blend with tooling traffic.
Wave 2 postinstall.js (~13 KB, entropy ~5.46) layers obfuscator.io output, a custom base64 alphabet, and an integer-shuffle string table. Statically recoverable by alphabet remapping; decodes to the same oob.moika.tech and X-Secret constants Wave 1 used in cleartext. Matches SafeDep YARA rules dynamic_require_double_obscured (critical), js_char_code_at_substitution, js_hex_obfuscation. Distinguishes Wave 2 from Wave 1's plaintext payload and represents an evasion upgrade by the same operator.
Reads Chromium Login Data and decrypts saved passwords with aes-256-gcm (v10/v11 schemes). ATTRIBUTED to the convicted @apexcraft/nano-key root lineage from prior SafeDep triage and external triage c1896; not decoded in this static pass.
Windows persistence via schtasks and registry Run key.
macOS persistence via LaunchAgent plist (com.launchkeeper.MicrosoftSystem64).
Poisoned PKGBUILD build/prepare steps run shell commands (npm install atomic-lockfile / bun install js-digest) under the building user's privileges via yay/paru/makepkg.
Malware payload bundled as a Node.js SEA (Single Executable Application), producing a standalone binary (81 MB) that embeds the Node.js v20.18.2 runtime. Avoids dependency on victim having Node.js installed and obscures the JavaScript payload within a stripped ELF/PE binary.
XOR encryption with 8-byte key [90, 60, 126, 18, 159, 75, 109, 138] used to encrypt embedded configuration including C2 address and HuggingFace token.
Account rotation across multiple npm accounts (jpeek868, jpeek886, jpeek895, pvnd3540749, yggedd817513, toskypi) to sustain publishing after takedowns.
Wave 2 adds a functional T_IN_ONE_NO_TELEMETRY kill switch honored in code and a run-once de-duplication guard (~/.cache/._t-in-one_init/), reducing repeat beacons and analysis surface. Wave 1's telemetry opt-out env vars were README-only social engineering.
Package README declares a fake telemetry feature with a fabricated opt-out environment variable and plausible internal telemetry domain. This normalizes expected outbound network activity at install time. Developers and security reviewers see a disclosure with an opt-out — standard practice for legitimate telemetry — and do not investigate the actual exfiltration POST to oob.moika.tech. The telemetry domains are not functional C2; they exist only in README text as social engineering artifacts. Fake changelog entries with plausible version history further present the package as a mature, ongoing project rather than a fresh first-and-only publish.
Staging web content (proxy pages with injected ad scripts) on infrastructure to target users who visit the proxy.
Mass-publishing packages to npm via automated shell scripts (auto-publish.sh) to rapidly deploy adware infrastructure across many package names.
Service worker intercepts all fetch events in the web proxy, injecting tab-interception scripts into proxied HTML responses to enable popunder ad monetization.
At least two separate long-dormant RubyGems maintainer accounts were taken over and reactivated within hours to publish malicious gem versions (Dendreo, fastlane-plugin-run_tests_firebase_testlab) plus a fresh impersonation package (git_credential_manager), all wiring in the same dropper dependency chain.
Copies binary to %LOCALAPPDATA%\Microsoft\Windows\0\svchost.exe and sets HKCU\Software\Microsoft\Windows\CurrentVersion\Run\svchost for boot persistence.
macOS persistence via LaunchAgent plist.
Rust infostealer installs a systemd USER service masquerading as a benign daemon (observed colord, haveged) at ~/.config/systemd/user/<daemon>.service pointing at ~/.local/bin/<daemon> for persistence (Amazon Inspector).
Injects JavaScript into the Exodus desktop wallet to capture the wallet password and BIP-39 seed mnemonic as the user enters them, POSTed to the local listener on 127.0.0.1:8738.
Clipboard monitoring with 1-second polling interval.
Direct-bytecode builds capture the game/program window or full screen via pyautogui/ImageGrab and reply_photo to a Telegram chat; pytesseract OCR of screen content.
Collection of .env files, shell history, and host inventory.
Data scraped by the RCE payload running on RubyDoc.info's infrastructure had no direct channel back to the operator, so the swarm shipped results back out through RubyGems itself: publishing the scraped pages as a brand-new gem, or writing them into the package's own README (with the --load line removed) and republishing as a new version.
Recon snapshot of hardware/software profile: model, chip, serial number, hardware UUID, SIP status, firmware version, running processes, installed/running applications.
Enumerates 27+ browser variant profiles and live developer accounts via api.github.com (/user, top repos), registry.npmjs.org (/-/whoami, maintainer search) and api.openai.com.
Scheduled scans and automatic upload of collected data.
Malicious package content delivers exploit code intended to execute in a client application context.
Hardcoded 2FA password and recovery email installed on victim accounts via Telegram updateTwoFaSettings, with the operator's IMAP mailbox auto-submitting the confirmation code.
Listens for messages on Telegram's official OTP sender chat 777000 and forwards every login code to operator-controlled bot channels.
Malware propagates or executes across additional systems by abusing remote management channels.
Compromised npm maintainer accounts across 6+ organizations (jaredwray, sitthidet_arv, onereach.user, qlikossbuild, st-team, multiple @deliveroo accounts) used simultaneously for mass publishing.
Wave 4 payload is an obfuscator.io-style single-line ~160 KB script using a custom lowercase-first base64 alphabet (abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=) PLUS a per-string RC4 layer. Static base64 decode of the string table only recovers primitives such as charCodeAt/fromCharCode; sensitive strings (C2, headers, file list) remain RC4-protected. This differs from Wave 3's WaCk/JScrambler string-array obfuscation.
Abuses npm OIDC Trusted Publishing token exchange to mint package-scoped automation tokens for self-replication; also steals SCM/registry/CI and AI-provider API tokens.
Malware deletes, corrupts, or otherwise destroys local data or system state.
Abuses legitimate web services for staging and C2: gofile.io anonymous file hosting, Cloudflare quick-tunnel (trycloudflare.com) for multiple distinct tunnels (delivery, exfil API, secondary download, WebSocket RAT, shellcode), ipinfo.io for geolocation, Discord API for token validation.
Python used as the execution trigger: modified __init__.py spawns a daemon thread that imports and calls the stager module at package import time.
Wave 4 shifts from full-process.env capture (Waves 1-3) to targeted on-disk credential/secret harvesting. The postinstall reads ~20 files including ~/.ssh, ~/.aws/credentials, ~/.kube/config, ~/.docker/config.json, ~/.npmrc, ~/.netrc, ~/.pgpass, ~/.git-credentials, ~/.env, and ~/.bash_history.
Collected data is exfiltrated as a gzip-compressed HTTPS POST to the path /api/v1/events, gated by a custom X-Secret header. The destination C2 host is RC4+XOR-concealed in the payload and was not statically resolved.
Adversary collects private key material (e.g. SSH private keys) stored on the host.
In addition to the HTTPS POST, Wave 4 issues a DNS resolver beacon, providing a low-profile secondary signalling/exfil channel that survives HTTP egress filtering.
Harvests browser cookies (Network/Cookies, encrypted cookie values) and Local Storage/leveldb across 27+ Chromium/Firefox variants including Flatpak/Snap, plus Slack/Teams/Discord/Telegram stores.
Web-protocol exfiltration. EARLIER static hypothesis: HTTPS exfil with spoofed Mozilla/5.0 UA from a self-contained browser stealer. CORRECTED (Amazon Inspector): the Linux/macOS Rust infostealer second stage POSTs stolen data as multipart/form-data over HTTP using the minreq library, gated behind anti-VM checks.
Module import event triggers daemon thread execution. Any code path that imports the core.telemetry package — application startup, CI test runs, IDE background processes — silently triggers the stager.
Packages masquerade as an internal 'Platform Engineering Team' library set. Constant scope-parameterized metadata fingerprint: README marker 'Internal package — Platform Engineering Team'; author '<Scope> Platform Engineering <platform@<scope>.io>'; repository git+https://github.<scope>.io/platform/<pkg>.git; bugs https://jira.<scope>.io/projects/PLATFORM; homepage https://docs.<scope>.io/platform/<pkg>; fake internal registry lure registry=https://npm.<scope>.io; telemetry cover story to telemetry.<scope>.io; descriptions from a fixed pool (e.g. 'Internal structured logger ... remote drain support', 'Internal configuration loader with env, vault and remote config support'). A decoy dist/index.js require()s a ../src/index.js absent from the tarball, so the library is non-functional and only the postinstall executes.
25 malicious @marketfront packages published at version 7.0.0 to win dependency-confusion resolution against an internal @marketfront scope. Execution is via a postinstall lifecycle hook ('node scripts/postinstall.js') that fires automatically on npm install without any developer import.
Stealer runs as JavaScript at runtime only when the SDK key-derivation functions (PrivateKey.fromMnemonic / fromHex) are invoked; no install hook, deliberately avoiding install-time scanners.
First-stage obfuscator.io downloader fetches a ~10.6MB Rust-compiled infostealer second stage from GitHub Releases (github.com/angelmaybeth21-oss/test/releases/download/v1.0.0/{linux,mac,win.js}) and executes it via a detached child process (Amazon Inspector).