- Un développeur canadien a été visé par une attaque par porte dérobée déguisée en faux entretien avec un VC, et le déroulé de l’attaque semblait si bien adapté au travail d’un développeur qu’il est soupçonné d’avoir ciblé le gestionnaire de paquets crates.io
- Le dépôt leurre semblait être une application TypeScript nommée « Ticket Harbor », mais
patch-packageettypescript+5.9.2.patchy cachaient du code malveillant dans le chemin d’exécution de TypeScript - Le stub injecté déchiffre une obfuscation en base64 et XOR, l’exécute via
new Function(...), puis passe par un chunk caché dansoperators/3.pnget un stub WASM pour lancer une charge utile de deuxième étape de 1,68 Mo dans un processus Node séparé - La charge finale, « PinpinRAT », génère une paire de clés RSA-2048 et une clé de session AES-256-CBC, et prend en charge la collecte d’empreintes de l’hôte, l’upload et le download de fichiers, l’exécution de processus, la manipulation du système de fichiers, les requêtes DNS et l’auto-suppression
- Si le dépôt a été exécuté, il faut immédiatement couper le réseau et remplacer les identifiants depuis un autre appareil, en partant du principe que des cookies et secrets protégés par mot de passe ont pu être exfiltrés
Une attaque ciblant des développeurs, déclenchée par un faux entretien
- Les attaquants ont pris contact en se faisant passer pour une fausse personne prétendument liée à « Lua Ventures »
- Lua Ventures était présenté comme un VC singapourien spécialisé dans la DeFi, mais il s’agissait en réalité d’une structure déjà inactive
- Le nom de la personne n’est pas publié, car il pourrait être confondu avec de véritables homonymes
- L’e-mail paraissait crédible et contenait aussi un lien vers un profil LinkedIn banal, mais apparemment légitime
- Comme sociétés d’investissement à la recherche de conseils, ils mentionnaient Lyrasing et Roadpay
- Les deux entreprises avaient une présence web minimale, donnant davantage l’impression de sociétés en phase initiale que de faux complets
- Il existe même une capture archive.org du site de Roadpay
- Après quelques échanges par e-mail, l’affaire est allée jusqu’à un appel Google Meet
- L’interlocuteur au téléphone était un homme avec un accent allemand, disant être en déplacement
- L’appel lui-même n’avait rien de manifestement anormal
Un déclencheur d’exécution déguisé en « test technique »
- Après l’appel, les attaquants ont proposé un « test » et envoyé un dépôt
- Le dépôt était présenté comme une application de billetterie pour ferries appelée « Ticket Harbor »
- Le fichier
task.txtcontenait une liste de tâches ennuyeuse mais crédible, avec à la fin une instruction d’exécution- Il demandait d’exécuter le typecheck du dépôt, la suite de tests, ainsi que des commandes de build desktop/server associées
- Cette instruction constituait le véritable déclencheur de l’infection
- Dès qu’une commande comme
npm run typecheck,buildoudevexécutait TypeScript ou importaittypescript.js, la charge utile pouvait être lancée
- Dès qu’une commande comme
Une chaîne d’exécution cachée dans un patch TypeScript
- Le premier signal d’alerte était que le dépôt ressemblait à un exercice TypeScript
- La demande évoquait davantage un test de recrutement TypeScript qu’une analyse d’architecture
- Une vérification rapide du dépôt avec Claude a révélé des anomalies liées à
patch-package
- Le répertoire
patches/était anormalement fourni- Certains patchs semblaient légitimes et servaient de bruit pour masquer la vraie charge utile
- On y trouvait par exemple
sumchecker+3.0.1.patch,@electron+get+2.0.3.patchetextract-zip+2.0.1.patch
- Le code malveillant principal se trouvait dans
typescript+5.9.2.patch- Il injectait un stub à exécution immédiate en tête de
typescript.jset_tsc.js - Le stub décodait une chaîne base64, déchiffrait chaque octet avec une clé XOR
73, puis exécutait le résultat vianew Function(...) require,Buffer,WebAssembly,processet__dirnameétaient passés à la fonction exécutée
- Il injectait un stub à exécution immédiate en tête de
- La chaîne d’exécution passait par plusieurs étapes
- Quatre hooks
postinstallexécutaientpatch-package - L’un d’eux appliquait
git update-index --skip-worktreeau fichier patch pour le masquer dansgit status - Le loader lisait un chunk caché ajouté à la fin du fichier
operators/3.png - Il exécutait un petit stub WASM dans un chunk
wAsmpersonnalisé - Il lançait ensuite une charge utile de deuxième étape obfusquée de 1,68 Mo dans un processus Node séparé et discret
- Quatre hooks
- Le code d’attaque était conçu pour limiter ses traces après exécution
- Le patch était masqué via
git skip-worktree - Après le premier lancement, le dropper supprimait des lignes qu’il avait lui-même injectées dans le fichier patch
- Le répertoire temporaire de la deuxième étape s’auto-supprimait à l’exécution
- Le patch était masqué via
Les capacités de PinpinRAT
- La charge finale est désignée sous le nom de « PinpinRAT »
- Ce nom vient de chaînes internes, sans exclure qu’elle soit connue sous une autre appellation
- Aucune autre référence en ligne n’a été trouvée
- La charge utile était empaquetée sous plusieurs couches d’obfuscation
- obfuscator.io
- deux couches supplémentaires de base64
- Au démarrage, le RAT collecte et exfiltre une empreinte de l’hôte
- l’adresse IP principale et la liste complète des IP
- le nom d’utilisateur issu de
os.userInfo().username - le nom d’hôte
- le type, la version, la plateforme et l’architecture de l’OS
- le PID du processus et l’intégralité de
process.argv - la version de Node
- Il intègre aussi une architecture de chiffrement
- génération locale d’une paire de clés RSA-2048
- génération d’une clé de session AES-256 aléatoire
aes_psk - le trafic suivant est chiffré en AES-256-CBC avec un tag d’intégrité HMAC-SHA256
- Les commandes prises en charge offrent des capacités de cheval de Troie d’accès à distance
env: sérialiseprocess.enven JSON et l’envoieupload: lit un chemin de fichier arbitraire et l’exfiltredownload: écrit des octets fournis par l’attaquant vers un chemin accessible en écriturespawn: exécute un processus arbitraire avec extension shell optionnellels,cd,pwd,cp,mv: manipulation classique du système de fichiersdns: résout un nom arbitraire via le resolver indiquédismantle: auto-suppression
Indicateurs de compromission et réponse immédiate
- L’image contenant la charge utile n’était détectée par aucun moteur AV sur VirusTotal
- En cas d’exécution, il faut immédiatement isoler le système du réseau
- Les identifiants doivent être remplacés depuis un autre appareil
- Il faut considérer comme compromis les cookies et secrets protégés par mot de passe
- Les indicateurs de compromission liés à PinpinRAT sont les suivants
- C2 :
89.124.107.161:80 - tâche planifiée Windows :
PinpinWrappedJs - camouflage de processus sur macOS :
com.apple.WebKit.Networking - variables d’environnement :
NODT_PAYLOAD_PATH,NODT_PAYLOAD_ARGS - garde de chunk PNG :
WASMPACK(wAsm) PINPIN_NO_AUTOSTART=1: désactive la persistance- cron job incluant
mutex.js: peut n’exister que si le RAT dispose de privilèges, et peut être absent sur macOS - chaînes d’ancrage dans
typescript.js:12ff4b51,ticket-harbor-tsc-shim-anchor typescript+5.9.2.patchcontenant la charge utile- répertoires d’artefacts :
- macOS :
~/Library/Caches/runtime-cache/.cache-<randomhex>/ - Linux :
/tmp/.cache-<randomhex>/ - Windows :
%TEMP%\\.cache-<randomhex>\\ - contenant
payload.jsetmutex.js
- macOS :
- C2 :
Des signaux d’alerte visibles après coup
- Les messages contenaient, à y regarder de près, des formulations ressemblant à des traces d’LLM
- Le profil LinkedIn semblait normal au premier regard, mais l’énumération des diplômes et qualifications était maladroite, et aucune activité réelle n’y apparaissait
- Les liens de réseaux sociaux du site avaient bien un historique réel, mais le nom avait changé en novembre 2025
- Les publications restaient vagues, plus proches d’éloges flous sur des entreprises que de contenu concret
- Les sites d’entreprise étaient soignés, mais quasiment sans présence réelle
- Les attaquants n’ont pas envoyé d’invitation calendrier formelle, seulement une heure et un lien Google Meet
- Pendant l’appel, la caméra est restée coupée et l’interlocuteur disait être en déplacement
- On retrouvait ensemble un VC basé à Singapour, une activité en fuseau CEST, un contact ciblant un développeur canadien et un domaine
.ccvisant des clients américains- Il était donc plus difficile de vérifier la crédibilité d’une organisation lointaine
- Pris isolément, chaque signal n’était pas décisif, mais l’accumulation de plusieurs voyants jaunes dessinait un vrai voyant rouge
Attribution et portée de l’attaque
- Il est impossible de confirmer l’attribution
- L’attaque visait des développeurs et combinait une fausse identité, une histoire de couverture crédible, plusieurs faux sites web, une planification patiente et des pièges
gitsophistiqués - Elle s’inscrit dans la continuité des campagnes de « fausses interviews » utilisées par plusieurs acteurs en 2026
- Un témoignage similaire de ciblage a aussi été mentionné sur Reddit dans la communauté Rust
- La méthode était si proche des workflows des développeurs qu’elle aurait pu fonctionner si le même piège avait été monté dans un script
build.rspiégé d’un dépôt Rust
1 commentaires
Commentaires sur Lobste.rs
Je trouve déroutant que le titre suggère qu’il pourrait s’agir d’un attaquant soutenu par un État. Rien ici ne semble vraiment nécessiter ce niveau de préparation ou de complexité.
On peut imaginer cette possibilité, mais elle ne paraît plausible qu’à peu près autant que d’autres scénarios.
Malgré tout, je pense qu’il ne s’agit presque certainement pas d’un attaquant soutenu par un État. Ce type d’attaque n’est plus si difficile aujourd’hui.
C’est vraiment une coïncidence si cette attaque ressemble au cas hypothétique que j’ai décrit dans mon billet de blog il y a une semaine : the hypothetical I describe in my blog post from a week ago
J’avais simplement choisi l’une de plusieurs attaques plausibles pour montrer que même des experts à l’aise avec la tech peuvent se faire piéger. J’avais bien vu la montée de diverses arnaques sophistiquées visant des personnes, mais je ne savais pas qu’une tendance aux arnaques à l’entretien d’embauche était en cours. Du coup, découvrir cette attaque m’a fait un peu froid dans le dos.
La semaine dernière, j’ai reçu exactement le même type de proposition d’entretien de la part de D____ S_____ de Lua Ventures. Je l’ai ignorée comme la plupart des spams de recruteurs, et j’ai bien fait.
Il me semble qu’il y a eu une soumission de ce genre il y a quelques jours ou quelques semaines.
J’ai l’impression qu’il y a eu plusieurs articles similaires.
Je suis surpris par le « ça ressemblait à un vrai e-mail ». Le texte sent tellement clairement la phrase générée par LLM que j’aurais eu des soupçons dès la deuxième phrase.