{"id":1302,"date":"2026-11-08T15:00:00","date_gmt":"2026-11-08T14:00:00","guid":{"rendered":"https:\/\/remivernier.com\/?p=1302"},"modified":"2026-11-08T15:00:00","modified_gmt":"2026-11-08T14:00:00","slug":"agent-skills-claude-skill-analyse-kerberos","status":"publish","type":"post","link":"https:\/\/remivernier.com\/index.php\/2026\/11\/08\/agent-skills-claude-skill-analyse-kerberos\/","title":{"rendered":"Agent Skills Claude: un skill d&rsquo;analyse Kerberos"},"content":{"rendered":"<p>Nous allons \u00e9crire sur notre maquette test.local un skill Claude capable de lire la sortie de \u00ab klist \u00bb d&rsquo;un poste, de rep\u00e9rer le TGT et les tickets de service, puis de signaler ce qui pose probl\u00e8me: chiffrement RC4, d\u00e9l\u00e9gation, flags inattendus, etc\u2026<\/p>\n<p>Pour le m\u00eame travail, nous aurions aussi pu \u00e9crire un long prompt syst\u00e8me qui embarque tout: la proc\u00e9dure, la table des types de chiffrement, les r\u00e8gles de d\u00e9tection. Le skill d\u00e9coupe ce contenu et ne le charge qu&rsquo;au moment o\u00f9 l&rsquo;agent en a besoin, et c&rsquo;est ce d\u00e9coupage qui nous int\u00e9resse ici.<\/p>\n<h2>Pr\u00e9sentation de la maquette<\/h2>\n<p>Nom du domaine: test.local (TESTLOCAL)<\/p>\n<p>Contr\u00f4leur de domaine: DC01.test.local<\/p>\n<p>Serveur web: srv01, site monsite.test.local ex\u00e9cut\u00e9 par le compte svc.monsite@test.local<\/p>\n<p>Utilisateur: alice@test.local<\/p>\n<p>C&rsquo;est la maquette de l&rsquo;article sur IIS et Kerberos, avec le m\u00eame compte de service. Depuis le poste d&rsquo;alice, apr\u00e8s un acc\u00e8s au site, nous r\u00e9cup\u00e9rons la sortie de \u00ab klist \u00bb:<\/p>\n<pre class=\"wp-block-code\"><code>Current LogonId is 0:0x3e7a1\n\nCached Tickets: (2)\n\n#0&gt;\tClient: alice @ TEST.LOCAL\n\tServer: krbtgt\/TEST.LOCAL @ TEST.LOCAL\n\tKerbTicket Encryption Type: AES-256-CTS-HMAC-SHA1-96\n\tTicket Flags 0x40e10000 -&gt; forwardable renewable initial pre_authent name_canonicalize\n\tStart Time: 11\/8\/2026 9:02:11 (local)\n\tEnd Time:   11\/8\/2026 19:02:11 (local)\n\tRenew Time: 11\/15\/2026 9:02:11 (local)\n\tSession Key Type: AES-256-CTS-HMAC-SHA1-96\n\tCache Flags: 0x1 -&gt; PRIMARY\n\tKdc Called: DC01.test.local\n\n#1&gt;\tClient: alice @ TEST.LOCAL\n\tServer: HTTP\/monsite.test.local @ TEST.LOCAL\n\tKerbTicket Encryption Type: RSADSI RC4-HMAC(NT)\n\tTicket Flags 0x40a10000 -&gt; forwardable renewable pre_authent name_canonicalize\n\tStart Time: 11\/8\/2026 9:05:43 (local)\n\tEnd Time:   11\/8\/2026 19:02:11 (local)\n\tRenew Time: 11\/15\/2026 9:02:11 (local)\n\tSession Key Type: RSADSI RC4-HMAC(NT)\n\tCache Flags: 0\n\tKdc Called: DC01.test.local<\/code><\/pre>\n<p>Nous avions d\u00e9j\u00e0 lu ce type de sortie \u00e0 la main dans l&rsquo;article <a href=\"https:\/\/remivernier.com\/index.php\/2026\/10\/27\/kerberos-lire-ticket-service-klist-wireshark-tgs-req-pac\/\">Kerberos: lire un ticket de service avec klist et Wireshark<\/a>. Cette fois, nous allons confier la lecture \u00e0 Claude, en lui fournissant une m\u00e9thode fixe plut\u00f4t que de le laisser improviser.<\/p>\n<h2>Structure du skill<\/h2>\n<p>Un skill est un simple r\u00e9pertoire. Seul le fichier SKILL.md est obligatoire, le reste d\u00e9pend de ce que nous voulons y mettre. Voici l&rsquo;arborescence de notre skill:<\/p>\n<pre class=\"wp-block-code\"><code>analyse-kerberos\/\n\u251c\u2500\u2500 SKILL.md\n\u251c\u2500\u2500 scripts\/\n\u2502   \u2514\u2500\u2500 parse_klist.py\n\u2514\u2500\u2500 references\/\n    \u251c\u2500\u2500 etypes.md\n    \u2514\u2500\u2500 detection.md<\/code><\/pre>\n<h3>1. Le fichier SKILL.md<\/h3>\n<p>Le fichier commence par un en-t\u00eate YAML avec deux champs obligatoires, \u00ab name \u00bb et \u00ab description \u00bb. Le nom est limit\u00e9 \u00e0 64 caract\u00e8res (minuscules, chiffres et tirets) et doit correspondre au nom du r\u00e9pertoire. La description peut aller jusqu&rsquo;\u00e0 1024 caract\u00e8res. Microsoft documente ce m\u00eame format pour son <a href=\"https:\/\/learn.microsoft.com\/en-us\/agent-framework\/agents\/skills\">Agent Framework<\/a>: un skill \u00e9crit pour Claude n&rsquo;est donc pas enferm\u00e9 chez un seul \u00e9diteur.<\/p>\n<pre class=\"wp-block-code\"><code>---\nname: analyse-kerberos\ndescription: Analyse une sortie klist Windows (tickets Kerberos en cache) ou des champs Kerberos extraits avec tshark. Identifie TGT et tickets de service, types de chiffrement, flags et dur\u00e9es, et signale les configurations \u00e0 risque (RC4, DES, ok-as-delegate). \u00c0 utiliser d\u00e8s qu'une sortie klist, un ticket Kerberos ou une erreur KRB5 est fournie.\n---\n\n# Analyse Kerberos\n\n## D\u00e9marche\n1. Enregistrer la sortie fournie dans \/tmp\/klist.txt puis lancer\n   python scripts\/parse_klist.py &lt; \/tmp\/klist.txt\n   Ne jamais d\u00e9coder les flags ou les etypes \u00e0 la main.\n2. Travailler \u00e0 partir du JSON produit: une entr\u00e9e par ticket, avec ses alertes.\n3. Pour un type de chiffrement ou un flag inconnu, lire references\/etypes.md.\n4. Si un ticket de service est en RC4 ou DES, lire references\/detection.md.\n\n## Format de r\u00e9ponse\n- Un tableau: serveur, etype du ticket, etype de session, flags, alertes.\n- Les constats, du plus grave au moins grave, chacun avec l'attribut AD\n  ou le param\u00e8tre \u00e0 v\u00e9rifier.\n\n## R\u00e8gles\n- Si l'entr\u00e9e contient un ticket complet (blob base64, KRB_CRED, .kirbi, keytab),\n  ne pas l'analyser et demander la sortie klist ou les champs tshark.\n- Ne jamais proposer de m\u00e9thode pour casser ou rejouer un ticket.<\/code><\/pre>\n<p>La description est la partie la plus travaill\u00e9e du skill: c&rsquo;est la seule que l&rsquo;agent voit en permanence, c&rsquo;est donc elle qui d\u00e9cide si le skill sera ouvert. Une description vague du type \u00ab outils Kerberos \u00bb laissera Claude r\u00e9pondre de m\u00e9moire sans jamais charger la m\u00e9thode.<\/p>\n<h3>2. Le script<\/h3>\n<p>Le d\u00e9codage d&rsquo;un champ \u00ab Ticket Flags \u00bb en hexad\u00e9cimal est une op\u00e9ration d\u00e9terministe. Le mod\u00e8le sait la faire, mais rien ne garantit qu&rsquo;il la fasse bien \u00e0 chaque fois. Nous la confions donc \u00e0 un script:<\/p>\n<pre class=\"wp-block-code\"><code>#!\/usr\/bin\/env python3\n\"\"\"Analyse une sortie klist Windows et produit un JSON.\"\"\"\nimport json, re, sys\n\nFLAGS = {\n    0x40000000: \"forwardable\", 0x20000000: \"forwarded\",\n    0x10000000: \"proxiable\",   0x08000000: \"proxy\",\n    0x00800000: \"renewable\",   0x00400000: \"initial\",\n    0x00200000: \"pre_authent\", 0x00040000: \"ok_as_delegate\",\n    0x00010000: \"name_canonicalize\",\n}\nFAIBLES = (\"RC4\", \"DES\")\n\ndef champ(bloc, nom):\n    m = re.search(rf\"{nom}:\\s*(.+)\", bloc)\n    return m.group(1).strip() if m else \"\"\n\ndef analyse(texte):\n    tickets = []\n    for bloc in re.split(r\"#\\d+&gt;\", texte)[1:]:\n        m = re.search(r\"Ticket Flags\\s+(0x[0-9a-fA-F]+)\", bloc)\n        f = int(m.group(1), 16) if m else 0\n        t = {\n            \"client\": champ(bloc, \"Client\"),\n            \"serveur\": champ(bloc, \"Server\"),\n            \"etype_ticket\": champ(bloc, \"KerbTicket Encryption Type\"),\n            \"etype_session\": champ(bloc, \"Session Key Type\"),\n            \"flags\": [n for v, n in FLAGS.items() if f &amp; v],\n            \"kdc\": champ(bloc, \"Kdc Called\"),\n            \"alertes\": [],\n        }\n        if any(x in t[\"etype_ticket\"] for x in FAIBLES):\n            t[\"alertes\"].append(\"ticket chiffr\u00e9 avec un etype faible\")\n        if \"ok_as_delegate\" in t[\"flags\"] and not t[\"serveur\"].startswith(\"krbtgt\/\"):\n            t[\"alertes\"].append(\"service approuv\u00e9 pour la d\u00e9l\u00e9gation (ok-as-delegate)\")\n        tickets.append(t)\n    return tickets\n\nif __name__ == \"__main__\":\n    print(json.dumps(analyse(sys.stdin.read()), ensure_ascii=False, indent=2))<\/code><\/pre>\n<p>Sur notre sortie, le script renvoie pour le ticket #1:<\/p>\n<pre class=\"wp-block-code\"><code>{\n  \"client\": \"alice @ TEST.LOCAL\",\n  \"serveur\": \"HTTP\/monsite.test.local @ TEST.LOCAL\",\n  \"etype_ticket\": \"RSADSI RC4-HMAC(NT)\",\n  \"etype_session\": \"RSADSI RC4-HMAC(NT)\",\n  \"flags\": [\"forwardable\", \"renewable\", \"pre_authent\", \"name_canonicalize\"],\n  \"kdc\": \"DC01.test.local\",\n  \"alertes\": [\"ticket chiffr\u00e9 avec un etype faible\"]\n}<\/code><\/pre>\n<p>Attention: le script attend les libell\u00e9s anglais de \u00ab klist \u00bb. Si vos postes renvoient une sortie localis\u00e9e, il faudra adapter les expressions r\u00e9guli\u00e8res.<\/p>\n<h3>3. Les r\u00e9f\u00e9rences<\/h3>\n<p>Le fichier etypes.md contient la table des types de chiffrement (1 et 3 pour DES, 17 pour aes128-cts-hmac-sha1-96, 18 pour aes256-cts-hmac-sha1-96, 23 pour rc4-hmac) et les bits de l&rsquo;attribut <code>msDS-SupportedEncryptionTypes<\/code> (0x4 pour RC4, 0x8 pour AES128, 0x10 pour AES256). Le fichier detection.md d\u00e9crit ce qu&rsquo;il faut chercher c\u00f4t\u00e9 contr\u00f4leur de domaine. Nous y reviendrons plus bas.<\/p>\n<h2>Chargement progressif ou prompt syst\u00e8me?<\/h2>\n<p>Le skill est charg\u00e9 en trois niveaux. Au d\u00e9marrage, seuls le nom et la description de chaque skill sont inject\u00e9s dans le contexte, de l&rsquo;ordre d&rsquo;une centaine de tokens par skill. Quand une demande correspond \u00e0 la description, Claude lit le corps de SKILL.md. Les r\u00e9f\u00e9rences et les scripts ne viennent qu&rsquo;ensuite, et seulement si la d\u00e9marche les appelle.<\/p>\n<figure class=\"wp-block-image\">\n<svg viewBox=\"0 0 720 300\" width=\"100%\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" font-family=\"sans-serif\" font-size=\"14\">\n<defs><marker id=\"fl\" markerWidth=\"10\" markerHeight=\"10\" refX=\"9\" refY=\"5\" orient=\"auto\"><path d=\"M0,0 L10,5 L0,10 z\" fill=\"#333\"\/><\/marker><\/defs>\n<rect x=\"20\" y=\"30\" width=\"200\" height=\"90\" rx=\"8\" fill=\"#e8f0fe\" stroke=\"#333\"\/>\n<text x=\"120\" y=\"60\" text-anchor=\"middle\" font-weight=\"bold\">Niveau 1<\/text>\n<text x=\"120\" y=\"82\" text-anchor=\"middle\">name + description<\/text>\n<text x=\"120\" y=\"102\" text-anchor=\"middle\" font-size=\"13\">toujours dans le contexte<\/text>\n<rect x=\"260\" y=\"30\" width=\"200\" height=\"90\" rx=\"8\" fill=\"#fdf3e1\" stroke=\"#333\"\/>\n<text x=\"360\" y=\"60\" text-anchor=\"middle\" font-weight=\"bold\">Niveau 2<\/text>\n<text x=\"360\" y=\"82\" text-anchor=\"middle\">corps de SKILL.md<\/text>\n<text x=\"360\" y=\"102\" text-anchor=\"middle\" font-size=\"13\">lu si la demande correspond<\/text>\n<rect x=\"500\" y=\"30\" width=\"200\" height=\"90\" rx=\"8\" fill=\"#e6f4ea\" stroke=\"#333\"\/>\n<text x=\"600\" y=\"60\" text-anchor=\"middle\" font-weight=\"bold\">Niveau 3<\/text>\n<text x=\"600\" y=\"82\" text-anchor=\"middle\">references\/ et scripts\/<\/text>\n<text x=\"600\" y=\"102\" text-anchor=\"middle\" font-size=\"13\">lus ou ex\u00e9cut\u00e9s au besoin<\/text>\n<line x1=\"220\" y1=\"75\" x2=\"256\" y2=\"75\" stroke=\"#333\" stroke-width=\"1.5\" marker-end=\"url(#fl)\"\/>\n<line x1=\"460\" y1=\"75\" x2=\"496\" y2=\"75\" stroke=\"#333\" stroke-width=\"1.5\" marker-end=\"url(#fl)\"\/>\n<rect x=\"500\" y=\"180\" width=\"200\" height=\"80\" rx=\"8\" fill=\"#fff\" stroke=\"#333\"\/>\n<text x=\"600\" y=\"210\" text-anchor=\"middle\">parse_klist.py<\/text>\n<text x=\"600\" y=\"232\" text-anchor=\"middle\" font-size=\"13\">seul le JSON revient<\/text>\n<text x=\"600\" y=\"250\" text-anchor=\"middle\" font-size=\"13\">dans le contexte<\/text>\n<line x1=\"600\" y1=\"120\" x2=\"600\" y2=\"176\" stroke=\"#333\" stroke-width=\"1.5\" marker-end=\"url(#fl)\"\/>\n<rect x=\"20\" y=\"180\" width=\"440\" height=\"80\" rx=\"8\" fill=\"#fff\" stroke=\"#333\" stroke-dasharray=\"5,4\"\/>\n<text x=\"240\" y=\"212\" text-anchor=\"middle\">Prompt syst\u00e8me monolithique<\/text>\n<text x=\"240\" y=\"236\" text-anchor=\"middle\" font-size=\"13\">proc\u00e9dure + tables + r\u00e8gles envoy\u00e9es \u00e0 chaque requ\u00eate<\/text>\n<\/svg><figcaption>Chargement progressif du skill analyse-kerberos<\/figcaption><\/figure>\n<p>La documentation d&rsquo;Anthropic insiste sur un point pour les <a href=\"https:\/\/platform.claude.com\/docs\/en\/agents-and-tools\/agent-skills\/overview\">scripts<\/a>: Claude les ex\u00e9cute avec bash, ce qui donne des op\u00e9rations d\u00e9terministes sans charger leur code dans le contexte. Notre parseur ne co\u00fbte donc que la taille de sa sortie JSON.<\/p>\n<p>Avec un prompt monolithique, la proc\u00e9dure, la table des etypes et les r\u00e8gles de d\u00e9tection partent \u00e0 chaque requ\u00eate, m\u00eame pour une question qui n&rsquo;a rien \u00e0 voir avec Kerberos, et c&rsquo;est le mod\u00e8le lui-m\u00eame qui convertit 0x40a10000 en liste de flags.<\/p>\n<p>Le skill a lui aussi un co\u00fbt: l&rsquo;outil d&rsquo;ex\u00e9cution de code ajoute sa d\u00e9finition et les \u00e9changes bash au contexte, et le corps de SKILL.md est relu \u00e0 chaque d\u00e9clenchement. Sur une seule question, le gain en tokens n&rsquo;est donc pas acquis d&rsquo;avance. Pour le mesurer, il suffit de passer le m\u00eame jeu de sorties \u00ab klist \u00bb dans les deux configurations et de comparer <code>usage.input_tokens<\/code> et <code>usage.output_tokens<\/code> dans les r\u00e9ponses de l&rsquo;API. Pour la fiabilit\u00e9, nous comparons les tableaux produits \u00e0 la sortie du script, qui sert de r\u00e9f\u00e9rence.<\/p>\n<h2>D\u00e9poser le skill et l&rsquo;appeler<\/h2>\n<p>\u00c0 l&rsquo;heure o\u00f9 j&rsquo;\u00e9cris ces lignes (novembre 2026), <a href=\"https:\/\/platform.claude.com\/docs\/en\/build-with-claude\/skills-guide\">l&rsquo;API Skills<\/a> est sortie de b\u00eata et ne demande plus d&rsquo;en-t\u00eate beta. L&rsquo;ancien en-t\u00eate <code>anthropic-beta: skills-2025-10-02<\/code> fonctionne toujours mais renvoie les anciennes structures de r\u00e9ponse. C\u00f4t\u00e9 SDK Python, nous passons par <code>client.skills<\/code> au lieu de <code>client.beta.skills<\/code>.<\/p>\n<h3>1. Envoi du skill<\/h3>\n<pre class=\"wp-block-code\"><code>curl https:\/\/api.anthropic.com\/v1\/skills \\\n  -H \"x-api-key: $ANTHROPIC_API_KEY\" \\\n  -H \"anthropic-version: 2023-06-01\" \\\n  -F \"display_title=Analyse Kerberos\" \\\n  -F \"files[]=@analyse-kerberos\/SKILL.md;filename=analyse-kerberos\/SKILL.md\" \\\n  -F \"files[]=@analyse-kerberos\/scripts\/parse_klist.py;filename=analyse-kerberos\/scripts\/parse_klist.py\" \\\n  -F \"files[]=@analyse-kerberos\/references\/etypes.md;filename=analyse-kerberos\/references\/etypes.md\" \\\n  -F \"files[]=@analyse-kerberos\/references\/detection.md;filename=analyse-kerberos\/references\/detection.md\"<\/code><\/pre>\n<p>La r\u00e9ponse contient l&rsquo;identifiant du skill (pr\u00e9fixe <code>skill_<\/code>) et sa version (pr\u00e9fixe <code>skver_<\/code> sans l&rsquo;en-t\u00eate beta). Attention, v\u00e9rifiez la forme exacte de la requ\u00eate multipart dans la documentation correspondant \u00e0 votre version d&rsquo;API.<\/p>\n<h3>2. Appel de l&rsquo;API Messages<\/h3>\n<p>Pour que Claude utilise le skill, nous listons son skill_id dans le param\u00e8tre container et nous ajoutons l&rsquo;outil d&rsquo;ex\u00e9cution de code, puisque c&rsquo;est son conteneur qui h\u00e9berge les skills. D&rsquo;apr\u00e8s la page de l&rsquo;<a href=\"https:\/\/platform.claude.com\/docs\/en\/agents-and-tools\/tool-use\/code-execution-tool\">outil d&rsquo;ex\u00e9cution de code<\/a>, aucune des trois versions actuelles ne demande d&rsquo;en-t\u00eate anthropic-beta.<\/p>\n<pre class=\"wp-block-code\"><code>import anthropic\n\nclient = anthropic.Anthropic()\nklist = open(\"klist_alice.txt\", encoding=\"utf-8\").read()\n\nr = client.messages.create(\n    model=\"claude-opus-5-5\",\n    max_tokens=4096,\n    container={\"skills\": [\n        {\"type\": \"custom\", \"skill_id\": \"skill_01...\", \"version\": \"latest\"}\n    ]},\n    tools=[{\"type\": \"code_execution_20260521\", \"name\": \"code_execution\"}],\n    messages=[{\"role\": \"user\",\n               \"content\": \"Analyse cette sortie klist du poste d'alice:\\n\\n\" + klist}],\n)\n\nprint(r.usage.input_tokens, r.usage.output_tokens)\nfor bloc in r.content:\n    print(bloc.type)<\/code><\/pre>\n<p>En parcourant <code>r.content<\/code>, nous voyons la d\u00e9marche de l&rsquo;agent bloc par bloc:<\/p>\n<p>-&gt; server_tool_use: lecture de SKILL.md dans le conteneur<\/p>\n<p>-&gt; server_tool_use: \u00e9criture de \/tmp\/klist.txt puis lancement de parse_klist.py<\/p>\n<p>-&gt; r\u00e9sultat bash: le JSON du script<\/p>\n<p>-&gt; server_tool_use: lecture de references\/detection.md, d\u00e9clench\u00e9e par l&rsquo;alerte RC4<\/p>\n<p>-&gt; text: le tableau et les constats<\/p>\n<p>Si le bloc text arrive sans aucune lecture de SKILL.md avant lui, la description n&rsquo;a pas d\u00e9clench\u00e9 le skill et c&rsquo;est elle que nous retravaillons.<\/p>\n<p>Attention: \u00ab latest \u00bb convient pour la mise au point. En production, nous fixons un num\u00e9ro de version, sinon une modification du skill change le comportement de l&rsquo;agent sans que l&rsquo;appel ait chang\u00e9.<\/p>\n<h2>Ce que le skill signale, et ce qu&rsquo;il ne doit pas voir<\/h2>\n<p>Le constat principal sur notre maquette porte sur le ticket de service HTTP\/monsite.test.local, chiffr\u00e9 en RC4-HMAC. Nous avions d\u00e9j\u00e0 rencontr\u00e9 le m\u00eame cas en fin d&rsquo;article sur la <a href=\"https:\/\/remivernier.com\/index.php\/2018\/06\/24\/iis-kerberos\/\">configuration de IIS pour Kerberos<\/a>. La partie chiffr\u00e9e de ce ticket l&rsquo;est avec une cl\u00e9 RC4, c&rsquo;est-\u00e0-dire le hash NT du mot de passe de svc.monsite.<\/p>\n<p>N&rsquo;importe quel utilisateur authentifi\u00e9 du domaine peut demander un ticket pour ce SPN, l&#8217;emporter et tenter de retrouver le mot de passe hors ligne, sans plus jamais toucher le contr\u00f4leur de domaine. C&rsquo;est le Kerberoasting, r\u00e9f\u00e9renc\u00e9 T1558.003 dans MITRE ATT&amp;CK. Un compte de service utilisateur a souvent un mot de passe ancien qui n&rsquo;expire pas, et souvent des droits bien au-del\u00e0 du site qu&rsquo;il fait tourner: une fois le mot de passe retrouv\u00e9, l&rsquo;attaquant ouvre des sessions avec ce compte partout o\u00f9 il est autoris\u00e9, et rien n&rsquo;est r\u00e9voqu\u00e9 tant que le mot de passe ne change pas.<\/p>\n<p>Le fichier detection.md donne \u00e0 l&rsquo;agent les \u00e9l\u00e9ments pour orienter la recherche c\u00f4t\u00e9 DC: l&rsquo;\u00e9v\u00e9nement 4769 (demande de ticket de service) avec un \u00ab Ticket Encryption Type \u00bb \u00e0 0x17. La difficult\u00e9, c&rsquo;est qu&rsquo;une demande de ticket est une op\u00e9ration normale. Un 4769 en RC4 isol\u00e9 peut venir d&rsquo;une vieille application l\u00e9gitime. Ce qui doit alerter, c&rsquo;est un m\u00eame compte qui demande des tickets RC4 pour de nombreux SPN diff\u00e9rents en peu de temps, ou une demande RC4 sur un compte dont <code>msDS-SupportedEncryptionTypes<\/code> annonce AES.<\/p>\n<p>C\u00f4t\u00e9 durcissement, le skill renvoie vers les bons leviers: positionner <code>msDS-SupportedEncryptionTypes<\/code> \u00e0 0x18 (AES128 et AES256) sur svc.monsite, changer son mot de passe pour g\u00e9n\u00e9rer les cl\u00e9s AES, ou mieux le remplacer par un gMSA dont le mot de passe est al\u00e9atoire et renouvel\u00e9 automatiquement. Il suffit ensuite d&rsquo;un \u00ab klist purge \u00bb sur le poste, d&rsquo;un nouvel acc\u00e8s au site et d&rsquo;un nouveau passage dans le skill pour v\u00e9rifier que le ticket #1 est en AES-256-CTS-HMAC-SHA1-96.<\/p>\n<p>Reste le skill lui-m\u00eame. C&rsquo;est du code et des instructions que l&rsquo;agent suit: un skill r\u00e9cup\u00e9r\u00e9 sans relecture peut orienter les r\u00e9ponses ou ex\u00e9cuter autre chose que ce qu&rsquo;annonce sa description. Nous le relisons comme n&rsquo;importe quel script avant de le d\u00e9poser. Sur l&rsquo;API, les skills tournent dans un conteneur isol\u00e9 sans acc\u00e8s r\u00e9seau et sans installation de paquets, ce qui limite les d\u00e9g\u00e2ts. Dans Claude Code, un skill pos\u00e9 dans <code>~\/.claude\/skills\/<\/code> ex\u00e9cute ses scripts sur le poste, avec les droits et le r\u00e9seau de l&rsquo;utilisateur.<\/p>\n<p>Il faut aussi faire attention aux donn\u00e9es envoy\u00e9es. Une sortie \u00ab klist \u00bb ne contient pas de secret, mais elle r\u00e9v\u00e8le des noms de comptes, des SPN et le nom des contr\u00f4leurs de domaine. Une capture r\u00e9seau compl\u00e8te, elle, contient les KRB_TGS_REP avec la partie chiffr\u00e9e des tickets: c&rsquo;est la mati\u00e8re premi\u00e8re du Kerberoasting, qui n&rsquo;a rien \u00e0 faire dans une requ\u00eate API. C&rsquo;est pour cela que SKILL.md refuse les tickets complets. Si nous partons d&rsquo;une capture, nous extrayons localement les seuls champs utiles avant de les transmettre:<\/p>\n<pre class=\"wp-block-code\"><code>tshark -r capture.pcapng -Y \"kerberos.msg_type == 13\" -T fields \\\n  -e frame.time -e kerberos.CNameString -e kerberos.SNameString -e kerberos.etype<\/code><\/pre>\n<p>Le champ <code>kerberos.etype<\/code> peut sortir plusieurs valeurs s\u00e9par\u00e9es par des virgules (etype du ticket et etype de la partie chiffr\u00e9e de la r\u00e9ponse), ce que references\/etypes.md explique \u00e0 l&rsquo;agent. Ces quatre colonnes suffisent pour rep\u00e9rer un ticket de service en 23, sans qu&rsquo;aucun octet chiffr\u00e9 ne quitte le poste d&rsquo;analyse.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Nous \u00e9crivons un Agent Skill Claude qui analyse une sortie klist: SKILL.md, script Python, r\u00e9f\u00e9rences, chargement progressif et appel via l&rsquo;API Claude.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[123,4,37],"tags":[124,129,125,126,5,50,127,128],"class_list":["post-1302","post","type-post","status-publish","format-standard","hentry","category-anthropic-claude","category-kerberos","category-securite","tag-agent-skills","tag-api","tag-claude","tag-kerberoasting","tag-kerberos","tag-klist","tag-rc4","tag-skill-md"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.7 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Agent Skills Claude: un skill d&#039;analyse Kerberos - R\u00e9mi VERNIER<\/title>\n<meta name=\"description\" content=\"Nous \u00e9crivons un Agent Skill Claude qui analyse une sortie klist: SKILL.md, script Python, r\u00e9f\u00e9rences, chargement progressif et appel via l&#039;API Claude.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/remivernier.com\/index.php\/2026\/11\/08\/agent-skills-claude-skill-analyse-kerberos\/\" \/>\n<meta property=\"og:locale\" content=\"fr_FR\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Agent Skills Claude: un skill d&#039;analyse Kerberos - R\u00e9mi VERNIER\" \/>\n<meta property=\"og:description\" content=\"Nous \u00e9crivons un Agent Skill Claude qui analyse une sortie klist: SKILL.md, script Python, r\u00e9f\u00e9rences, chargement progressif et appel via l&#039;API Claude.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/remivernier.com\/index.php\/2026\/11\/08\/agent-skills-claude-skill-analyse-kerberos\/\" \/>\n<meta property=\"og:site_name\" content=\"R\u00e9mi VERNIER\" \/>\n<meta property=\"article:published_time\" content=\"2026-11-08T14:00:00+00:00\" \/>\n<meta name=\"author\" content=\"R\u00e9mi\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"\u00c9crit par\" \/>\n\t<meta name=\"twitter:data1\" content=\"R\u00e9mi\" \/>\n\t<meta name=\"twitter:label2\" content=\"Dur\u00e9e de lecture estim\u00e9e\" \/>\n\t<meta name=\"twitter:data2\" content=\"12 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/remivernier.com\\\/index.php\\\/2026\\\/11\\\/08\\\/agent-skills-claude-skill-analyse-kerberos\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/remivernier.com\\\/index.php\\\/2026\\\/11\\\/08\\\/agent-skills-claude-skill-analyse-kerberos\\\/\"},\"author\":{\"name\":\"R\u00e9mi\",\"@id\":\"https:\\\/\\\/remivernier.com\\\/#\\\/schema\\\/person\\\/a4c76c63a5a3d94454484845e42fc906\"},\"headline\":\"Agent Skills Claude: un skill d&rsquo;analyse Kerberos\",\"datePublished\":\"2026-11-08T14:00:00+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/remivernier.com\\\/index.php\\\/2026\\\/11\\\/08\\\/agent-skills-claude-skill-analyse-kerberos\\\/\"},\"wordCount\":1791,\"commentCount\":0,\"keywords\":[\"agent skills\",\"api\",\"claude\",\"kerberoasting\",\"kerberos\",\"klist\",\"rc4\",\"skill.md\"],\"articleSection\":[\"Anthropic \\\/ Claude\",\"Kerberos\",\"S\u00e9curit\u00e9\"],\"inLanguage\":\"fr-FR\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/remivernier.com\\\/index.php\\\/2026\\\/11\\\/08\\\/agent-skills-claude-skill-analyse-kerberos\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/remivernier.com\\\/index.php\\\/2026\\\/11\\\/08\\\/agent-skills-claude-skill-analyse-kerberos\\\/\",\"url\":\"https:\\\/\\\/remivernier.com\\\/index.php\\\/2026\\\/11\\\/08\\\/agent-skills-claude-skill-analyse-kerberos\\\/\",\"name\":\"Agent Skills Claude: un skill d'analyse Kerberos - R\u00e9mi VERNIER\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/remivernier.com\\\/#website\"},\"datePublished\":\"2026-11-08T14:00:00+00:00\",\"author\":{\"@id\":\"https:\\\/\\\/remivernier.com\\\/#\\\/schema\\\/person\\\/a4c76c63a5a3d94454484845e42fc906\"},\"description\":\"Nous \u00e9crivons un Agent Skill Claude qui analyse une sortie klist: SKILL.md, script Python, r\u00e9f\u00e9rences, chargement progressif et appel via l'API Claude.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/remivernier.com\\\/index.php\\\/2026\\\/11\\\/08\\\/agent-skills-claude-skill-analyse-kerberos\\\/#breadcrumb\"},\"inLanguage\":\"fr-FR\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/remivernier.com\\\/index.php\\\/2026\\\/11\\\/08\\\/agent-skills-claude-skill-analyse-kerberos\\\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/remivernier.com\\\/index.php\\\/2026\\\/11\\\/08\\\/agent-skills-claude-skill-analyse-kerberos\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Accueil\",\"item\":\"https:\\\/\\\/remivernier.com\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Agent Skills Claude: un skill d&rsquo;analyse Kerberos\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/remivernier.com\\\/#website\",\"url\":\"https:\\\/\\\/remivernier.com\\\/\",\"name\":\"R\u00e9mi VERNIER\",\"description\":\"Identit\u00e9, s\u00e9curit\u00e9, SAP et IA : Active Directory, Azure &amp; co...\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/remivernier.com\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"fr-FR\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/remivernier.com\\\/#\\\/schema\\\/person\\\/a4c76c63a5a3d94454484845e42fc906\",\"name\":\"R\u00e9mi\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"fr-FR\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/f750448bc07f5d1d9c1189344283777ec0d33275c184599b199fb6b305bc6fba?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/f750448bc07f5d1d9c1189344283777ec0d33275c184599b199fb6b305bc6fba?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/f750448bc07f5d1d9c1189344283777ec0d33275c184599b199fb6b305bc6fba?s=96&d=mm&r=g\",\"caption\":\"R\u00e9mi\"},\"sameAs\":[\"http:\\\/\\\/www.linkedin.com\\\/in\\\/remi-vernier\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Agent Skills Claude: un skill d'analyse Kerberos - R\u00e9mi VERNIER","description":"Nous \u00e9crivons un Agent Skill Claude qui analyse une sortie klist: SKILL.md, script Python, r\u00e9f\u00e9rences, chargement progressif et appel via l'API Claude.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/remivernier.com\/index.php\/2026\/11\/08\/agent-skills-claude-skill-analyse-kerberos\/","og_locale":"fr_FR","og_type":"article","og_title":"Agent Skills Claude: un skill d'analyse Kerberos - R\u00e9mi VERNIER","og_description":"Nous \u00e9crivons un Agent Skill Claude qui analyse une sortie klist: SKILL.md, script Python, r\u00e9f\u00e9rences, chargement progressif et appel via l'API Claude.","og_url":"https:\/\/remivernier.com\/index.php\/2026\/11\/08\/agent-skills-claude-skill-analyse-kerberos\/","og_site_name":"R\u00e9mi VERNIER","article_published_time":"2026-11-08T14:00:00+00:00","author":"R\u00e9mi","twitter_card":"summary_large_image","twitter_misc":{"\u00c9crit par":"R\u00e9mi","Dur\u00e9e de lecture estim\u00e9e":"12 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/remivernier.com\/index.php\/2026\/11\/08\/agent-skills-claude-skill-analyse-kerberos\/#article","isPartOf":{"@id":"https:\/\/remivernier.com\/index.php\/2026\/11\/08\/agent-skills-claude-skill-analyse-kerberos\/"},"author":{"name":"R\u00e9mi","@id":"https:\/\/remivernier.com\/#\/schema\/person\/a4c76c63a5a3d94454484845e42fc906"},"headline":"Agent Skills Claude: un skill d&rsquo;analyse Kerberos","datePublished":"2026-11-08T14:00:00+00:00","mainEntityOfPage":{"@id":"https:\/\/remivernier.com\/index.php\/2026\/11\/08\/agent-skills-claude-skill-analyse-kerberos\/"},"wordCount":1791,"commentCount":0,"keywords":["agent skills","api","claude","kerberoasting","kerberos","klist","rc4","skill.md"],"articleSection":["Anthropic \/ Claude","Kerberos","S\u00e9curit\u00e9"],"inLanguage":"fr-FR","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/remivernier.com\/index.php\/2026\/11\/08\/agent-skills-claude-skill-analyse-kerberos\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/remivernier.com\/index.php\/2026\/11\/08\/agent-skills-claude-skill-analyse-kerberos\/","url":"https:\/\/remivernier.com\/index.php\/2026\/11\/08\/agent-skills-claude-skill-analyse-kerberos\/","name":"Agent Skills Claude: un skill d'analyse Kerberos - R\u00e9mi VERNIER","isPartOf":{"@id":"https:\/\/remivernier.com\/#website"},"datePublished":"2026-11-08T14:00:00+00:00","author":{"@id":"https:\/\/remivernier.com\/#\/schema\/person\/a4c76c63a5a3d94454484845e42fc906"},"description":"Nous \u00e9crivons un Agent Skill Claude qui analyse une sortie klist: SKILL.md, script Python, r\u00e9f\u00e9rences, chargement progressif et appel via l'API Claude.","breadcrumb":{"@id":"https:\/\/remivernier.com\/index.php\/2026\/11\/08\/agent-skills-claude-skill-analyse-kerberos\/#breadcrumb"},"inLanguage":"fr-FR","potentialAction":[{"@type":"ReadAction","target":["https:\/\/remivernier.com\/index.php\/2026\/11\/08\/agent-skills-claude-skill-analyse-kerberos\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/remivernier.com\/index.php\/2026\/11\/08\/agent-skills-claude-skill-analyse-kerberos\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Accueil","item":"https:\/\/remivernier.com\/"},{"@type":"ListItem","position":2,"name":"Agent Skills Claude: un skill d&rsquo;analyse Kerberos"}]},{"@type":"WebSite","@id":"https:\/\/remivernier.com\/#website","url":"https:\/\/remivernier.com\/","name":"R\u00e9mi VERNIER","description":"Identit\u00e9, s\u00e9curit\u00e9, SAP et IA : Active Directory, Azure &amp; co...","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/remivernier.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"fr-FR"},{"@type":"Person","@id":"https:\/\/remivernier.com\/#\/schema\/person\/a4c76c63a5a3d94454484845e42fc906","name":"R\u00e9mi","image":{"@type":"ImageObject","inLanguage":"fr-FR","@id":"https:\/\/secure.gravatar.com\/avatar\/f750448bc07f5d1d9c1189344283777ec0d33275c184599b199fb6b305bc6fba?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/f750448bc07f5d1d9c1189344283777ec0d33275c184599b199fb6b305bc6fba?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/f750448bc07f5d1d9c1189344283777ec0d33275c184599b199fb6b305bc6fba?s=96&d=mm&r=g","caption":"R\u00e9mi"},"sameAs":["http:\/\/www.linkedin.com\/in\/remi-vernier"]}]}},"_links":{"self":[{"href":"https:\/\/remivernier.com\/index.php\/wp-json\/wp\/v2\/posts\/1302","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/remivernier.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/remivernier.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/remivernier.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/remivernier.com\/index.php\/wp-json\/wp\/v2\/comments?post=1302"}],"version-history":[{"count":1,"href":"https:\/\/remivernier.com\/index.php\/wp-json\/wp\/v2\/posts\/1302\/revisions"}],"predecessor-version":[{"id":1305,"href":"https:\/\/remivernier.com\/index.php\/wp-json\/wp\/v2\/posts\/1302\/revisions\/1305"}],"wp:attachment":[{"href":"https:\/\/remivernier.com\/index.php\/wp-json\/wp\/v2\/media?parent=1302"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/remivernier.com\/index.php\/wp-json\/wp\/v2\/categories?post=1302"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/remivernier.com\/index.php\/wp-json\/wp\/v2\/tags?post=1302"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}