- LinkedIn पर software engineer भर्ती का प्रस्ताव देने के बाद, एक private GitHub repository भेजी गई जो सामान्य React/Web3 assignment के रूप में छिपी हुई थी; चलाने पर
tailwind.config.jsमें छिपा JavaScript malware developer के कंप्यूटर पर सक्रिय हो गया - 30,987-byte की configuration file ने हज़ारों spaces के बाद 27KB obfuscated code छिपाया था, remote server से AES-256-CBC से encrypted stage-2 payload लेकर उसे
%TEMP%\packमें save किया और फिरnode packसे execute किया - Windows 11 ARM isolated VM में करीब 10 मिनट तक observation करने पर पाया गया कि payload ने चार components चलाए: remote-control backdoor, browser और wallet stealer, recursive file scanner, और clipboard monitor
- Socket.IO के ज़रिए terminal, SSH, screen, keyboard और mouse को control किया गया, और Chromium databases, wallet extension storage, SSH keys, source code, configuration files आदि collect किए गए; file upload port पर 2,588 requests observe हुईं
- अनजान व्यक्ति द्वारा भेजे गए assignment repository को untrusted code मानकर ऐसे disposable VM या container में inspect करना चाहिए जिसमें real browser profile, SSH keys, cloud credentials या wallets न हों; अगर infection हो गया हो, तो network disconnect और evidence preservation के बाद secrets तक rotate करने चाहिए
सामान्य Web3 hiring assignment के रूप में छिपी repository
- LinkedIn user Wayan Adrian ने shrapnel.com में software engineer role का प्रस्ताव दिया और assignment के रूप में
yevhen-oaccount की private GitHub repositorytech-active-workplace-frontend-mainभेजी - BLAIEXS नाम का NFT campaign platform ऊपर से एक सामान्य React/Web3 project था
- React frontend brand/admin dashboard, campaign management, NFT creation flow आदि प्रदान करता था
- Express API authentication, dashboard data, KYB checks, NFT creation/claim, file upload और कुछ stub endpoints handle करता था
- seed script superadmin, brand और consumer demo accounts,
Demo NFT Dropcampaign, और 100 items वालाDemo CollectibleNFT बनाता था
- असली assignment scope बस एक साधारण MetaMask network display feature था
src/utils/ethereum.jsमें asyncgetChainId()को इस तरह implement करना था कि वहeth_chainIdcall करे और parsed hexadecimal value याnullreturn करे- उसी file में
getNetworkLabel(chainId)को existingNETWORKSobject से पढ़ने योग्य network name खोजने के लिए implement करना था src/components/Wallet/ConnectWalletButton.jsको wallet connect होने के बाद दोनों functions call करने के लिए modify करना था
- Implementation पूरी करके development server चलाया गया, लेकिन वह काफी देर तक start नहीं हुआ; गड़बड़ी भांपकर user ने internet cable unplug कर दी
tailwind.config.js में छिपा executable code
ls -laमेंtailwind.config.js30,987 bytes का था, लेकिन editor में सिर्फ 97 lines दिखीं;wc -cसे भी वही size confirm हुआ- line 95 के आसपास, हज़ारों spaces के बाद इंसान के लिए पढ़ना मुश्किल एक बड़ा JavaScript blob छिपा हुआ था
- Code ने सामान्य JavaScript obfuscation techniques इस्तेमाल कीं
- अहम strings को एक बड़े array में store करना
- checksum match होने तक array को rotate करना
- string access को decoder function के पीछे छिपाना
- साफ names को numeric indexes और wrapper calls से replace करना
- दो decoders में से एक Base64 format में strings recover करता था, जबकि दूसरा हर string के key और RC4-जैसे stream cipher को apply करता था; decoder indexes सही होने से पहले string array rotate किया जाता था
- Malware execute किए बिना भी नीचे दिए क्रम में obfuscation हटाई जा सकी
- string array extract करना
- expected checksum तक पहुंचने के लिए array rotation reproduce करना
- decoder functions को reimplement करना
b(0x214),c(0x2f1, "key")जैसी calls को असली strings से replace करना- wrapper objects और helper functions को simplify करके execution intent सामने लाना
Stage-1 dropper का behavior
- Deobfuscated code
child_process,os,fs,path,cryptoimport करता है और temporary directory मेंaxiosऔरsocket.io-clientinstall करता है - Process-level
uncaughtExceptionऔरunhandledRejectionhandlers errors को ignore करने के लिए configured थे - Remote payload execution flow इस प्रकार था
- UID
59e605dd78fb2aafccd1b622f06a00caहै http://45.146.252.17/api/service/59e605dd78fb2aafccd1b622f06a00caसे data fetch करता है- UID और string
saltकोcrypto.scryptSyncमें डालकर 32-byte key derive करता है - Response को
base64_iv:base64_ciphertextformat में split करता है औरaes-256-cbcसे decrypt करता है - Plaintext को temporary directory की
packfile में लिखता है child_process.execSync("node pack", { windowsHide: true, cwd: os.tmpdir() })से execute करता है
- UID
- यह खुद कोई feature perform करने के बजाय दूसरा malicious software download करके run करने वाला malware dropper है
- Download किए गए code में signature verification, hash allowlist, origin pinning, path restrictions या execution-prevention guard नहीं थे, इसलिए remote endpoint Tailwind config load करने वाले OS account के privileges से code execute कर सकता है
Isolated VM में किया गया dynamic analysis
- Host system को expose न करने के लिए UTM से disposable Windows 11 ARM VM configure किया गया
- Memory
4096 MiB - Disk
64 GiB shared/NATnetworking- Shared folders disabled
- Memory
- Malware behavior को कई angles से collect करने के लिए tools install किए गए
- Wireshark: packets और C2/exfiltration traffic collect करना
- Sysinternals Sysmon: persistent Windows event telemetry
- Procmon: running processes, registry और filesystem activity collect करना
- Malware किन चीज़ों को collect करता है यह verify करने के लिए decoy data रखा गया
- SSH key pair
- Private GitHub repository
- Cryptocurrency wallet
- Browser data
- Information stealer जिन अन्य files को target कर सकता है
- VM में
yarn startrun किया गया, करीब 10 मिनट तक observe किया गया, फिरrun1-full.pcapng,run1-sysmon.evtx,stage2-pack.binहासिल किए गए
Network में दिखा infection flow
45.146.252.17पर जाने वाले HTTP requests में port के हिसाब से roles बंटे हुए थे- Port
80: stage-1 payload fetch, host registration, log transmission - Port
7641: Socket.IO command-and-control backdoor - Port
7646: file uploads 2,588 requests - Port
7649: बड़े लेकिन कम संख्या वाले browser data uploads के 3 requests
- Port
- पहला request
GET /api/service/59e605dd78fb2aafccd1b622f06a00caथा, और responseContent-Length: 150897वालाbase64_iv:base64_ciphertextformat था tailwind.config.jsresponse को AES-256-CBC से decrypt करता है, plaintext को%TEMP%\packमें लिखता है और फिरnode packसे execute करता है- हासिल किए गए stage-2 payload की properties ये थीं
- SHA-256:
68a64d8c015c06fd70bcb8c5878c1e430da827dd00b62f8e6ef69e76bb94de5b - Size:
113136bytes - Format: single-line ASCII JavaScript
- SHA-256:
- Decrypted
packभी फिर से obfuscated था, लेकिन first stage जैसी technique का इस्तेमाल कर उसी प्रक्रिया से deobfuscate किया जा सका
चार प्रोग्राम से बना चरण-2 payload
packकोई एकल script नहीं था, बल्कि एक छोटा process tree था जो ये चार प्रोग्राम चलाता थाscdatacommand-and-control backdoor को temporary directory में लिखकर execute करता थाldatabrowser और wallet stealer को temporary directory में लिखकर execute करता था- recursive file scanner को
node -eके जरिए सीधे memory में चलाता था - clipboard monitor को
node -eके जरिए सीधे memory में चलाता था
- मुख्य configuration में UID
59e605dd78fb2aafccd1b622f06a00ca, user key308, host45.146.252.17, Socket.IO port7641, key port7648, browser upload port7649, file upload port7646शामिल थे
scdata: interactive remote-control backdoor
scdataको%TEMP%में file के रूप में लिखा गया औरnpm i axios socket.io-client ... && node scdataसे चलाया गया, और यह लंबे समय तक चलने वाले child process के रूप में बना रहा- चलने के बाद उसने खुद को सामान्य process जैसा दिखाने के लिए configure किया
- process title:
vhost.ctl - single-instance marker file:
%TEMP%\.npm\vhost.ctl - host registration:
http://45.146.252.17/api/service/… - log transmission:
http://45.146.252.17/api/service/makelog - Socket.IO C2:
http://45.146.252.17:7641
- process title:
- remote-control functions के लिए जरूरी अतिरिक्त packages भी install किए
socket.io-client,ssh2,node-pty: terminal और SSH जैसी functionalitysharp,screenshot-desktop,clipboardy,@nut-tree-fork/nut-js: screenshot, clipboard, mouse movement/click/scroll, keyboard input
- Socket.IO events remote-control scope को सीधे दिखाते हैं
- terminal:
start-terminal,terminal-input,terminal-resize,stop-terminal,command - host check और capture:
whour,capture - input control:
mouseMove,mouseClick,mouseScroll,keyTap,keyCombo - clipboard:
copyText,pasteText - SSH और termination:
start_ssh,ssh_input,kill
- terminal:
- PCAP में port
7641पर polling/WebSocket handshake और पहला server eventwhourconfirm हुआ, और Sysmon में क्रम सेnode.exe scdata, system information query PowerShell, और npm package installation के दो groups पकड़े गए - यह सिर्फ जानकारी चुराने से आगे बढ़कर attacker को shell और desktop control functionality तक देता था
ldata: browser और wallet data stealer
ldataको%TEMP%में लिखा गया औरnpm i axios && node ldataसे चलाया गया, और process titlenpm-cacheथा- यह browser profiles और wallet extension stores को collect करके
http://45.146.252.17:7649/uploadपर भेजता था, और LevelDB status को/cldbsपर check करता था - target browsers operating system के हिसाब से काफी व्यापक रूप से set थे
- Windows: Chrome, Edge, Brave, LT Browser
- macOS: Chrome, Brave, Opera, LT Browser, Edge और local login keychain
- Linux: corresponding Chromium-based profile folders
DefaultयाProfile*directories से ये Chromium databases upload किए गएLogin DataLogin Data For AccountWeb Data
- इसके बाद यह
Local Extension Settings/<extension-id>को scan करता था, और hardcoded wallet extension IDs में MetaMask काnkbihfbeogaeaoehlefnkodbefgpgknnभी शामिल था - पहले 8 wallet extension paths के लिए LevelDB directory को temporary folder में copy करके individual files upload की जाती थीं, और server के
cldbsresponse के आधार पर completion या retry तय किया जाता था - port
7649पर confirm हुए तीन uploads ये databases थेLogin_Data.sqlite: 51,200 bytesLogin_Data_For_Account.sqlite: 51,200 bytesWeb_Data.sqlite: 262,144 bytes
- test data में saved passwords या card rows नहीं थे, लेकिन 6 autocomplete values और browser metadata शामिल थे
- Chrome-based browsers कुछ fields को locally encrypt करते हैं, इसलिए सिर्फ database से हमेशा plaintext secrets recover नहीं किए जा सकते
- हालांकि OS secrets, cookies, extension storage और unlocked browser के साथ combine होने पर यह credential-theft pipeline का हिस्सा बन जाता है
- जरूरी browser data और LevelDB upload करने के बाद, या server द्वारा complete mark किए जाने पर यह exit हो जाता था, और operator के अलग command का इंतजार नहीं करता था
recursive file scanner और clipboard monitor
- recursive file scanner अलग file बनाए बिना
node -eसे run होता था और user home directory से scan शुरू करता था- Windows पर यह
Get-CimInstance Win32_LogicalDiskसे drive letters enumerate करता और हर drive root को भी check करता था - collected file patterns में
*.env*,*.md,*.pem,*.ini,*.secret,*.json,*.js,*.ts,*.csv,*.txt,*.doc,*.docx,*.pdf,*.xlsx,.zsh_history,.bash_historyशामिल थे ~/.ssh,~/.aws,~/.azure,~/.config,~/.foundryको अपने-आप interested folders माना जाता थाmetamask,bitcoin,btc,solana,secret phrase,private keyजैसे नाम भी खोजे जाते थे- results
http://45.146.252.17:7646/uploadपर भेजे जाते थे
- Windows पर यह
- decoy environment में
id_ed25519,id_ed25519.pub,History.txt,seed.js,password.js,tokens.js,ConnectWalletButton.js,ExportWallet.js,RegisterWallet.js,tailwind.config.js,aptos-cli.jsonआदि वास्तव में upload हुए - जहां
ldatabrowser और wallet storage का जिम्मा लेता था, वहीं file scanner SSH keys, configuration, source code, local secrets, shell history और project files को व्यापक रूप से collect करता था - clipboard monitor भी
node -eसे run होता था और process titlenpm-compiler.logथा- कुछ seconds इंतजार करने के बाद यह बार-बार clipboard पढ़ता था
- macOS पर
pbpaste, Windows परpowershell -NoProfile -NonInteractive Get-Clipboardइस्तेमाल करता था - बदली हुई values
http://45.146.252.17/api/service/makelogपर भेजी जाती थीं
- format interpret किए बिना भी यह user द्वारा copy किए गए passwords, recovery phrases, private keys, API tokens, one-time codes, GitHub URLs, wallet addresses और deployment secrets को जस का तस पकड़ सकता था
recruitment assignment चलाने से पहले पालन करने वाले सिद्धांत
- किसी अजनबी द्वारा भेजे गए assignment repository को safety verify होने तक untrusted executable code मानना चाहिए
yarn install,npm install,yarn build,yarn startसे पहले नीचे की चीजें review करनी चाहिएpackage.json- lifecycle scripts
- configuration files
- obvious dependency hooks
- इस case में malware
tailwind.config.jsमें छिपा था, जिसे लोग अक्सर नजरअंदाज कर देते हैं, और configuration files, dependencies और build tools भी सभी code के रूप में execute हो सकते हैं - interview project को ऐसे throwaway VM या container में run करना चाहिए जिसमें असली secrets mounted न हों
- personal browser profile
- password manager
- SSH keys
- cryptocurrency wallet
- GitHub token
- cloud credentials
- banking session
- primary email account
- जिन assignments में account या wallet चाहिए, उनके लिए ऐसा नया test identity इस्तेमाल करना चाहिए जिसमें funds न हों और जिसे दूसरी services में reuse न किया गया हो
- Web3 assignment हो तो सिर्फ testnet का इस्तेमाल करें, और भले ही project harmless लगे, अपने real wallet को किसी unknown project से connect न करें
संक्रमण का पता लगाने के संकेतक
- macOS·Linux पर पहले ये चीज़ें जांचें
node,pack,scdata,ldata,npm-compiler,vhost.ctlसे जुड़े चल रहे processes45.146.252.17या ports7641,7646,7649से connections- temporary directory, Downloads, Desktop, Documents, Library के तहत
pack,scdata,ldata,vhost.ctl */.npm/vhost.ctlmarker file- डाउनलोड किए गए project में IP, UID,
/api/service/makelog,node scdata,node ldata,node packstrings
- Windows पर ये चीज़ें जांचें
node,npm,cmd,powershellprocesses में वे entries जिनकी command line मेंpack,scdata,ldata,node -e, IP address,Get-Clipboardहों45.146.252.17या remote ports7641,7646,7649पर खुले TCP connections%TEMP%के तहतpack,scdata,ldata,vhost.ctl,.npm\vhost.ctl- interview repository clone की गई directory के अंदर ज्ञात C2 strings
- अगर live Node process, उस IP से connection, या
pack·scdata·ldataartifacts में से कुछ भी मिले, तो सिस्टम को exposed माना जाना चाहिए - ये indicators विश्लेषित sample के लिए खास शुरुआती जांच बिंदु हैं, पूरी forensic प्रक्रिया नहीं
संक्रमित सिस्टम की सफाई और secrets बदलना
- सबसे पहले कंप्यूटर को network से अलग करें, और संक्रमित environment में आगे explore या debug न करें, न ही नए secrets copy करें
- अगर evidence की जरूरत हो, तो delete करने से पहले ये data सुरक्षित रखें
- process list
- network connections
- संदिग्ध files
- browser history
- malicious repository
- इसके बाद
node pack,node scdata,node ldata,node -e,npm-compiler,vhost.ctlसे जुड़े processes बंद करें और temporary directory सेpack,scdata,ldata,.npm/vhost.ctlहटाएं - अगर यह disposable VM है और वैध Node काम को सुरक्षित रखने की जरूरत नहीं है, तो macOS·Linux पर
pkill nodeया Windows पर सभीnodeprocesses को force terminate किया जा सकता है - malicious repository और
node_modulesdelete करें, लेकिन अगर आगे analysis चाहिए तो ZIP copy offline सुरक्षित रखें - सिर्फ files delete करना काफी नहीं है; नीचे दी गई secret जानकारी को rotate या revoke करना होगा
- SSH keys
- GitHub·npm tokens
- cloud keys और API keys
- deployment secrets
- browser में saved passwords
- active login sessions
- अगर wallet seed या private key के संक्रमित सिस्टम के संपर्क में आने की संभावना है, तो किसी clean device पर नया wallet बनाकर funds transfer करें
development tools की trust boundary का दुरुपयोग करने वाला हमला
- traditional antivirus products ने इस repository को detect नहीं किया, और assignment हल करने में इस्तेमाल किए गए लोकप्रिय AI coding agents भी project में छिपे malware की पहचान नहीं कर पाए
- Tailwind JavaScript config file को Node module की तरह evaluate करता है, इसलिए जैसे ही development tools, build scripts, editor integrations, Tailwind CLI, bundlers या CI jobs config load करते हैं, line 95 का IIFE execute हो जाता है
- वैध Tailwind config line 94 तक था, और उसके बाद लगभग 27KB का obfuscated code जोड़ा गया था
- downloaded payload उसी operating system privileges के साथ चलता है जो config load करने वाले user के पास होते हैं
- यह local files, browser profiles, saved credentials, wallet extension data, SSH keys, environment variables, package tokens, cloud credentials, source code और clipboard तक पहुंच सकता है
- अगर CI में run हो, तो deployment secrets, build artifacts, registry credentials और production access tokens भी expose हो सकते हैं
- जरूरी fix है
tailwind.config.jsसे obfuscated JavaScript blob को पूरी तरह हटाना
अभी कोई टिप्पणी नहीं है.