1 points par GN⁺ 5 시간 전 | 1 commentaires | Partager sur WhatsApp
  • 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-package et typescript+5.9.2.patch y 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é dans operators/3.png et 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.txt contenait 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, build ou dev exécutait TypeScript ou importait typescript.js, la charge utile pouvait être lancée

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.patch et extract-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.js et _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 via new Function(...)
    • require, Buffer, WebAssembly, process et __dirname étaient passés à la fonction exécutée
  • La chaîne d’exécution passait par plusieurs étapes
    • Quatre hooks postinstall exécutaient patch-package
    • L’un d’eux appliquait git update-index --skip-worktree au fichier patch pour le masquer dans git 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 wAsm personnalisé
    • 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
  • 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

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érialise process.env en JSON et l’envoie
    • upload : lit un chemin de fichier arbitraire et l’exfiltre
    • download : écrit des octets fournis par l’attaquant vers un chemin accessible en écriture
    • spawn : exécute un processus arbitraire avec extension shell optionnelle
    • ls, cd, pwd, cp, mv : manipulation classique du système de fichiers
    • dns : 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.patch contenant la charge utile
    • répertoires d’artefacts :
      • macOS : ~/Library/Caches/runtime-cache/.cache-<randomhex>/
      • Linux : /tmp/.cache-<randomhex>/
      • Windows : %TEMP%\\.cache-<randomhex>\\
      • contenant payload.js et mutex.js

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 .cc visant 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 git sophistiqué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.rs piégé d’un dépôt Rust

1 commentaires

 
GN⁺ 5 시간 전
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.

    • C’est sans doute parce que ces arnaques sophistiquées demandent beaucoup de ressources et sont donc assez rares. Quand on voit une arnaque sophistiquée, il est facile de se dire qu’elle pourrait être soutenue par un État.
      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.

    • Je me demande si c’est quelqu’un du côté Rust. Des figures importantes de la communauté Rust ont été ciblées par Lua, et j’aimerais savoir si cela se limite à Rust ou si c’est plus large.
  • Il me semble qu’il y a eu une soumission de ce genre il y a quelques jours ou quelques semaines.

  • 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.

    • Pour moi, ce n’était pas si évident. Ça m’a juste donné une impression de style LinkedIn. Cela aussi sonne souvent comme écrit par un LLM, mais l’odeur est tellement proche que je ne suis pas sûr d’être capable de distinguer les deux.