Écrit le 2026-10-23
Lors de notre webcast consacré à ctiscan l’an dernier (la rediffusion est sur YouTube), nous avions montré une requête qui recherche les listeners Cobalt Strike se faisant passer pour légitime. Sur une semaine de données, elle remontait sept documents répartis sur trois hôtes, tous arborant un nom Microsoft ou Google.
Trois hôtes, c’est un point de départ, pas un résultat. Nous avons donc confié la requête à Claude Code, avec notre plugin onyphe-ai-skills installé, en lui demandant de chasser à partir de là. À l’arrivée : onze hôtes, dont deux partagent une clé privée, et pas un seul honeypot dans le lot.
Voici comment cela s’est déroulé, avec quelques conseils à reprendre pour vos propres chasses. Le plugin est gratuit, sous licence BSD 3-Clause, et son seul rôle est d’apprendre à Claude Code à se servir d’ONYPHE comme le ferait un analyste expérimenté.
La requête d’origine
onyphe -search 'category:ctiscan http.header.data.sha256:"aa182c6f2cdfa5aed16b6d2dfe68c54fcc9656d9477e5a7db41785d92545f07b" http.header.contentlength:0 app.tls:true ( -orregexp:cert.domain,".*microsoft.*" -orregexp:cert.domain,".*google.*" )
-since:1w | uniq cert.domain,ip.dest,ip.country,ip.asn'
(À exécuter sur une seule ligne : le retour à la ligne ci-dessus n’est là que pour tenir dans la page.)
Décortiquons-la :
http.header.data.sha256est le hash de l’ensemble du bloc d’en-têtes de la réponse HTTP. Celui-ci correspond au404vide qu’un listener Cobalt Strike renvoie à tout ce qui n’est pas un beacon. ONYPHE conserve également le MD5 du même bloc d’en-têtes,5293315563ba2448348295a4e1571a82, et c’est celui que vous verrez à partir de l’étape 1. Même en-tête, hash plus court.http.header.contentlength:0etapp.tls:truedemandent un corps de réponse vide servi en HTTPS, c’est-à-dire le mode de déploiement habituel du listener ; au passage, le certificat TLS nous donne de quoi pivoter.- Le
-orregexp:surcert.domainne retient que les certificats dont le domaine contient microsoft ou google. C’est le filtre d’usurpation, et c’est lui qui fait le travail intéressant. | uniq …est une étape d’OPP, l’ONYPHE Processing Pipeline, qui réduit les documents à une ligne par domaine et par hôte.
Tout cela tient en une seule requête parce que ctiscan range les en-têtes HTTP, le certificat TLS et le contexte réseau dans le même document. Aucune corrélation à faire après coup.
On voit les candidats potentiels s’effondrer à mesure que les filtres s’ajoutent, sur la même semaine :
| Requête | Documents |
|---|---|
| Hash d’en-tête seul | 443 |
| + corps vide | 401 |
| + TLS | 198 |
| + certificat Microsoft/Google | 7 |
C’est la dernière ligne qui fait basculer la statistique en piste. 198 listeners Cobalt Strike en HTTPS sur une semaine, c’est une foule ; sept documents qui se réclament de Microsoft ou de Google, c’est une piste. Trois hôtes, pour être précis :
googleapi2[.]com 107.172.43[.]189 US AS36352
microsoft-server[.]top 192.3.139[.]18 US AS36352
mailmicrosoft[.]com 193.235.207[.]69 CZ AS174
Deux des trois sont chez le même hébergeur, AS36352, qu’ONYPHE étiquette HostPapa et que le whois appelle encore ColoCrossing. C’est à noter, mais cela ne va pas bien loin en soi. Le certificat, lui, est autrement plus parlant : un opérateur qui prend la peine de baptiser son listener du nom de Microsoft ou de Google fait un choix délibéré, et ce sont les choix délibérés qui méritent qu’on pivote dessus. C’est ce fil que nous avons tiré.
On passe la main à Claude Code
Le plugin s’installe directement depuis Claude Code :
/plugin install onyphe --marketplace onyphe/onyphe-ai-skills
Ou bien clonez-le et lancez d’abord la vérification des prérequis :
git clone https://github.com/onyphe/onyphe-ai-skills.git
cd onyphe-ai-skills
./prerequisites.sh
claude plugin marketplace add ./
claude plugin install onyphe
Votre clé d’API reste dans ~/.onyphe.ini, là où le CLI va déjà la chercher.
Le plugin se contente d’interroger les données qu’ONYPHE possède déjà : il ne scanne jamais rien par lui-même.
Collez ensuite la requête et demandez :
Exécute cette requête onyphe, puis chasse les hôtes qu’elle renvoie. Trouve l’infrastructure associée.

La skill onyphe-hunt fait valider le périmètre avec vous avant de lancer la moindre requête, puis déroule une séquence fixe : vérifier ce que votre licence autorise réellement, prendre une capture de référence de chaque hôte, classer les attributs de cet hôte par rareté, soumettre chaque indicateur candidat au contrôle honeypot, pivoter, puis construire une chronologie. Tout atterrit dans un répertoire de chasse daté (le NDJSON brut, les comptages et un rapport de conclusions), de sorte que vous pouvez rejouer n’importe quelle étape que vous auriez envie de contester.
La chasse décrite ci-dessous a coûté environ 90 requêtes d’API.
Étape 1 : laisser la rareté choisir le pivot
Avec trois hôtes suspects sous les yeux, la tentation est d’attraper l’élément qui paraît le plus distinctif et de le rechercher tel quel. L’agent ne procède pas ainsi. Pour chaque hôte, il commence par compter combien d’autres documents partagent chacun de ses attributs. Voici une partie de la table pour le faux Google :
3 cert.fingerprint.md5 a28b6cefc38065d88d322da4e2fd8503
473 http.header.data.md5 5293315563ba2448348295a4e1571a82
18125 hhhash.fingerprint.md5 81e4f0fa6bb0edb65367494e6c364c9a
1255418 cert.subject.cn CloudFlare Origin Certificate
166932904 ja3s.fingerprint.md5 15af977ce25de452b96affa2addb1036
Ce qui tranche assez vite la question. L’empreinte JA3S est partagée par 167 millions de documents, parce qu’elle identifie une bibliothèque TLS et rien d’autre. Le hash d’en-tête, à 473, identifie l’outil et non l’opérateur qui s’en sert. À l’autre extrémité, l’empreinte du certificat n’apparaît que sur trois documents, tous rattachés à ce même hôte : parfait pour le suivre, inutile pour trouver ses camarades.
(Si vous vous demandez pourquoi 473 ici et 443 dans l’entonnoir : la requête de départ compte sur sept jours glissants, -since:1w, alors que l’agent compte sur la dernière semaine calendaire, -weekago:1. Tous les comptages qui suivent sont en semaine calendaire.)
La ligne intéressante, c’est le sujet du certificat. Il s’agit d’un certificat Cloudflare Origin : ce listener est donc placé derrière Cloudflare, et de fait googleapi2[.]com ne résout que vers des adresses de bordure Cloudflare. Prise isolément, cette ligne ne vaut rien, 1,25 million de documents représentant à peu près toute la clientèle de Cloudflare. Mise à côté du hash d’en-tête, en revanche, elle décrit quelque chose de très précis : un listener Cobalt Strike que quelqu’un a pris la peine de dissimuler derrière Cloudflare.
Les deux faux Microsoft n’ont rien donné d’équivalent. Leurs tables de rareté sont dominées par des certificats auto-signés que personne d’autre ne porte, ce qui est commode pour suivre ces deux hôtes mais d’aucun secours pour en trouver de nouveaux ; en dessous, on retrouve le même en-tête Cobalt Strike et la même pile TLS que tout le monde. Ils attendront donc la chronologie, et nous tirons sur le fil Google.
Nous tenons donc un pivot : l’en-tête Cobalt Strike et un certificat Cloudflare Origin, ensemble.
Étape 2 : le pivot
onyphe-count.sh 'category:ctiscan
http.header.data.md5:5293315563ba2448348295a4e1571a82
cert.subject.cn:"CloudFlare Origin Certificate" -weekago:1'
Vingt documents, huit hôtes. Tous font tourner un listener Cobalt Strike derrière Cloudflare, et chaque certificat origin nomme le domaine de l’opérateur lui-même :
| Hôte | Port | Hébergeur | Certificat origin pour |
|---|---|---|---|
| 107.172.43[.]189 | 443 | HostPapa, US | googleapi2[.]com |
| 192.210.206[.]196 | 443 | HostPapa, US | winboxtoday[.]com |
| 198.46.217[.]168 | 443 | HostPapa, US | viclian[.]com |
| 198.46.226[.]210 | 443 | HostPapa, US | viclian[.]com |
| 119.45.198[.]250 | 2096, 44445, 55555 | Tencent, CN | un domaine en .xyz (nom omis) |
| 154.198.162[.]92 | 8443 | Scloud, HK | prompti[.]top |
| 165.154.225[.]239 | 8443 | Scloud, HK | zhimawithyou[.]top |
| 2602:fa59:10:409::1 | 445 | RouterHosting, US | twnic[.]top |
En y regardant de plus près, 198.46.217[.]168 et 198.46.226[.]210 présentent le même certificat origin, numéro de série compris, et qui dit même certificat dit même clé privée. Deux machines, deux adresses IP, une clé que seul leur opérateur devrait détenir. Ce n’est pas une preuve en soi (un reverse proxy mutualisé ou une clé ayant fuité donneraient exactement la même image vue de l’extérieur), mais les deux hôtes répondent aussi avec le même en-tête Cobalt Strike, et deux indicateurs indépendants qui pointent dans la même direction, c’est à peu près le mieux qu’on puisse obtenir depuis l’extérieur.
Le premier des deux expose également un service TLS sur le port 30999, avec un certificat auto-signé *.google.com dont le sujet est O=Google, L=LA, ST=WA (quelqu’un était pressé). Aucun autre hôte dans ONYPHE ne porte ce certificat ce mois-ci : voilà un identifiant de suivi bien propre pour cet opérateur précis.
Étape 3 : et si c’étaient des honeypots ?
Avant que tout cela ne devienne une conclusion, chaque indicateur passe par onyphe-hpcheck.sh. À chaque chasse, nous y faisons aussi passer un témoin : une bannière SSH que les honeypots aiment beaucoup imiter. La raison est simple : un contrôle qui répond toujours « ce n’est pas un honeypot » ressemble exactement à un contrôle qui ne fonctionne pas.
| Indicateur | Documents | Honeypot |
|---|---|---|
| En-tête Cobalt Strike, corps vide, TLS | 211 | 0 % |
| En-tête + certificat Cloudflare Origin | 20 | 0 % |
Certificat *.googleapi2[.]com | 3 | 0 % |
Témoin : bannière SSH-2.0-Paramiko | 422 | 99,8 % |
(La première ligne affiche 211 et non les 198 de l’entonnoir, pour la raison déjà évoquée : semaine calendaire et non sept jours glissants.)
Cette dernière ligne justifie à elle seule l’existence du témoin. Sur ces 422 documents Paramiko, 222 seulement portent le tag honeypot d’ONYPHE : en filtrant sur le tag seul, il vous en resterait 200 qui ressemblent à d’honnêtes serveurs SSH. Le contrôle du plugin, qui rattrape aussi les non tagués grâce à leur signe distinctif (exposer exactement 199 services), en signale 421. Le contrôle fonctionne donc, et nos trois indicateurs Cobalt Strike en ressortent intacts. L’agent le fait pour chaque indicateur, à chaque chasse, que vous pensiez à le demander ou non.
Étape 4 : depuis combien de temps sont-ils là ?
L’agent cherche la date de première observation de chaque hôte et, quand la fenêtre de ctiscan s’épuise, il poursuit dans l’historique de datascan :
| Hôte | Première observation | Dernière observation |
|---|---|---|
| 192.3.139[.]18 | 2026-09-23 | 2026-10-21 |
| 198.46.226[.]210 | 2026-09-24 | 2026-10-22 |
| 192.210.206[.]196 | 2026-09-25 | 2026-10-20 |
| 107.172.43[.]189 | 2026-09-27 | 2026-10-21 |
| 193.235.207[.]69 | 2026-09-29 | 2026-10-20 |
| 198.46.217[.]168 | 2026-09-30 | 2026-10-20 |
Il s’agit des trois hôtes de départ et des hôtes HostPapa issus du pivot ; nous n’avons pas remonté l’historique des quatre machines situées en Asie et en IPv6 cette fois-ci. ONYPHE les a tous découverts dans un intervalle de huit jours, et tous les six répondaient encore cette semaine. Les certificats, eux, sont nettement plus anciens que les hôtes, et c’est en général la moitié la plus instructive de l’histoire : le certificat origin de googleapi2[.]com date de mai 2025, et celui de viclian[.]com du 2026-09-03, soit trois semaines avant que l’un ou l’autre de ses deux hôtes n’apparaisse.
Élargissez la requête de départ à un mois complet et un quatrième imitateur apparaît : 2.59.217[.]108, sur le port 1443, avec un certificat google.com. Celui-là s’est tu depuis.
Quelques conseils pour vos propres chasses
- Partez de l’outil, puis resserrez sur l’intention. Un hash d’en-tête vous trouvera l’outil, mais c’est le
-orregexp:surcert.domainqui met la main sur les opérateurs cherchant à se faire passer pour quelqu’un d’autre. Remplacez par.*apple.*,.*okta.*, ou par votre propre marque, et voyez qui porte votre nom cette semaine. - Demandez des hôtes, pas des documents. Chaque hôte est scanné plusieurs fois par semaine : un nombre de documents sera toujours supérieur à ce que vous voulez réellement mettre dans un rapport. Terminez la requête par
| uniq ip.dest, ou demandez simplement à l’agent combien d’hôtes distincts il a trouvés. - Laissez la table de rareté choisir le pivot plutôt que de le choisir vous-même. Posez la question : « qu’est-ce qui est rare sur cet hôte ? » La table compte des documents et non des hôtes, alors convertissez le chiffre en hôtes avant de vous enthousiasmer ; mais tout ce qui retombe entre deux et vingt-cinq hôtes mérite en général qu’on pivote dessus. Ce qui est partagé par des milliers de documents désigne une bibliothèque ou un hébergeur et ne vous apprendra rien sur un opérateur, même si, comme l’a montré le certificat Cloudflare, cela peut encore gagner sa place en deuxième terme d’une requête.
- Regardez le certificat avant toute chose. Domaines sosies, champs de sujet remplis à la va-vite, certificats origin réutilisés, sujets
*.google.comrecopiés : chacun de ces éléments est un choix humain, exactement ce qu’on attend d’un pivot. Le logiciel serveur, lui, vous dit surtout quel est le logiciel serveur. - Confirmez sur deux indicateurs. Un hash d’en-tête partagé place deux hôtes dans le même outillage ; un numéro de série de certificat partagé les place dans les mêmes mains. Ce ne sont pas les mêmes affirmations : demandez à l’agent de confirmer chaque membre d’un cluster sur deux indicateurs indépendants avant d’écrire quoi que ce soit.
- Demandez la chronologie. « Quand chacun de ces hôtes a-t-il été vu pour la première fois ? » L’agent remonte l’historique dans datascan dès que la fenêtre de ctiscan est épuisée, et les dates de certificat précèdent souvent les hôtes de plusieurs semaines.
- Transformez une bonne requête en alerte. Une fois qu’elle est assez serrée pour qu’on puisse lui faire confiance, la skill
onyphe-alertl’enregistre et vous envoie un courriel dès qu’un nouvel hôte correspond. - Profitez-en pour le pointer vers votre propre périmètre. Le même plugin gère la découverte et la gestion de surface d’attaque :
onyphe-asdconstruit un inventaire à partir de quelques domaines de départ, etonyphe-asmconfronte cet inventaire à riskscan et vulnscan.
onyphe -alert-add -alert-name "CS behind Cloudflare" -alert-email "you@example.org" \
'category:ctiscan http.header.data.md5:5293315563ba2448348295a4e1571a82 cert.subject.cn:"CloudFlare Origin Certificate"'
Indicateurs
| Indicateur | Type | Remarque |
|---|---|---|
| 192.3.139[.]18 | IPv4 | microsoft-server[.]top, auto-signé |
| 193.235.207[.]69 | IPv4 | mailmicrosoft[.]com, auto-signé O=Microsoft, OU=Digicert |
| 107.172.43[.]189 | IPv4 | googleapi2[.]com derrière Cloudflare |
| 198.46.217[.]168 | IPv4 | viclian[.]com derrière Cloudflare ; faux *.google.com sur le port 30999 |
| 198.46.226[.]210 | IPv4 | viclian[.]com derrière Cloudflare (même certificat) |
| 192.210.206[.]196 | IPv4 | winboxtoday[.]com derrière Cloudflare |
| 119.45.198[.]250 | IPv4 | domaine en .xyz derrière Cloudflare |
| 154.198.162[.]92 | IPv4 | prompti[.]top derrière Cloudflare |
| 165.154.225[.]239 | IPv4 | zhimawithyou[.]top derrière Cloudflare |
| 2602:fa59:10:409::1 | IPv6 | twnic[.]top derrière Cloudflare |
| 2.59.217[.]108 | IPv4 | certificat google[.]com, port 1443, vu le mois dernier |
| aa182c6f2cdfa5aed16b6d2dfe68c54fcc 9656d9477e5a7db41785d92545f07b | SHA-256 d’en-tête | 404 vide de Cobalt Strike |
| 5293315563ba2448348295a4e1571a82 | MD5 d’en-tête | 404 vide de Cobalt Strike (même en-tête) |
| 26:55:ba:70:66:71:93:d0:23:d3:17:06:38:c7:ea:99:91:15:25:bc | numéro de série de certificat | certificat origin de viclian[.]com |
| 739919d043fa817fe6174487c632e729 | MD5 de certificat | faux *.google.com, port 30999 |
Tous observés dans ctiscan et datascan d’ONYPHE entre le 2026-09-23 et le 2026-10-23.
Pour l’essayer
/plugin install onyphe --marketplace onyphe/onyphe-ai-skills
Le plugin est gratuit et open source (BSD 3-Clause), et il fonctionne avec votre propre clé d’API ONYPHE. Apportez une requête en laquelle vous avez déjà confiance, et demandez à Claude Code de chasser à partir de là.

