Skip to content

Cet outil n'est ni affilié à GitHub, Inc. ou à Microsoft Corporation, ni approuvé ou sponsorisé par elles. GitHub et GitHub Actions sont des marques de GitHub, Inc. Les autres noms sont des marques de leurs propriétaires respectifs.

Runner auto-hébergé GitHub : sécurité et forensique

Runner auto-hébergé GitHub malveillant ou compromis : les événements du journal d'audit à vérifier, les preuves dans _diag, le périmètre et la reconstruction.

Publié le 6 min de lecture

En bref. Les runners auto-hébergés sont un risque GitHub qui se trouve à l'intérieur de votre réseau. Deux scénarios se présentent. Un runner malveillant : un attaquant enregistre sa propre machine (org.register_self_hosted_runner / repo.register_self_hosted_runner) et reçoit vos jobs ainsi que leurs secrets. Un runner compromis : du code non fiable s'exécute sur votre hôte persistant et s'y installe durablement. Le journal d'audit vous indique quand les runners et les groupes ont changé. Les logs _diag/Runner_* et Worker_* de l'hôte vous indiquent ce qui s'est exécuté. Supprimez les runners inconnus, reconstruisez tout hôte ayant exécuté des jobs non fiables et passez à des runners éphémères placés dans des groupes restreints.

Les runners hébergés par GitHub sont des machines virtuelles neuves, détruites après chaque job. Les runners auto-hébergés sont ce que vous leur fournissez : une VM dans votre VPC, un pod dans votre cluster ou un Mac mini sous un bureau. Ils disposent souvent d'un accès réseau aux systèmes internes et aux endpoints de métadonnées cloud, ce qui explique précisément pourquoi les attaquants les apprécient.

Pourquoi les runners intéressent un attaquant

La référence d'utilisation sécurisée de GitHub est sans ambiguïté. Rien ne garantit qu'un runner auto-hébergé s'exécute sur une machine éphémère propre, et il peut être compromis de façon persistante par du code non fiable présent dans un workflow. Ces runners ne devraient pratiquement jamais être utilisés pour des dépôts publics. Sur des dépôts privés, toute personne capable d'ouvrir une pull request depuis un fork peut potentiellement y exécuter du code.

ScénarioCe que l'attaquant obtientATT&CK
Runner malveillant enregistré sur l'organisation ou un dépôtDes jobs routés vers sa machine, avec le code récupéré, les secrets et le GITHUB_TOKENT1072 Software Deployment Tools
Workflow non fiable sur un runner persistantExécution de code dans votre réseau, persistance entre les jobs, accès aux secrets des jobs suivantsT1677 Poisoned Pipeline Execution
Groupe de runners élargiDes runners sensibles (avec accès au réseau de production) désormais accessibles à davantage de dépôtsn/a, il s'agit d'un changement de configuration

Ce que le journal d'audit enregistre

Les événements du journal d'audit de l'organisation couvrent tout le cycle de vie des runners :

ActionSignification
org.register_self_hosted_runner, repo.register_self_hosted_runnerUn runner a été enregistré
org.configure_self_hosted_jit_runner, repo.configure_self_hosted_jit_runnerUn runner just-in-time (limité à un seul job) a été configuré via l'API
org.remove_self_hosted_runner, repo.remove_self_hosted_runnerUn runner a été supprimé
org.self_hosted_runner_online / _offline, repo.…L'application runner a démarré ou s'est arrêtée
org.self_hosted_runner_updatedL'application runner s'est mise à jour
org.runner_group_created, org.runner_group_updated, org.runner_group_runners_added, org.runner_group_visiblity_updatedLes groupes de runners et leurs accès ont changé
org.update_repo_self_hosted_runners_policyLa liste des dépôts autorisés à créer des runners de niveau dépôt a changé

L'analyseur lève self-hosted-runner-registered (gravité moyenne) pour org., repo. et enterprise.register_self_hosted_runner. Les autres actions ci-dessus ne font pas l'objet de règles. Elles apparaissent dans la table des événements et méritent un filtrage (runner dans le champ de recherche) autour de tout enregistrement que vous ne savez pas expliquer.

Analyser un enregistrement

L'enregistrement d'un runner exige un jeton d'enregistrement qui expire au bout d'une heure, obtenu par une personne disposant des droits d'administration sur le dépôt ou l'organisation, ou d'un jeton équivalent. Face à un enregistrement suspect, posez-vous donc ces questions :

  • Qui est l'acteur de l'événement ? Recherchez d'autres constats sur ce compte (jeton utilisé depuis un nouveau pays, droits de propriétaire accordés récemment).
  • Depuis où ? Un enregistrement depuis une adresse IP qui n'apparaît jamais dans votre infrastructure de CI est un signal d'alerte.
  • Quel nom et quels labels ? Les runners malveillants réutilisent souvent des labels comme self-hosted, linux et x64, afin que les workflows existants avec runs-on: [self-hosted, linux] les sélectionnent sans que personne ne modifie le moindre fichier YAML.
  • Quel groupe ? Un runner placé dans le groupe par défaut d'une organisation est disponible pour tous les dépôts que ce groupe autorise.

Ce que seul l'hôte peut vous apprendre

Le journal d'audit n'indique pas quels jobs se sont exécutés sur quel runner. Pour cela, il vous faut l'hôte du runner :

  • _diag/Runner_*.log : le log de l'application runner. Un fichier par démarrage, nommé avec un horodatage UTC. Il retrace l'enregistrement, les connexions et les affectations de jobs.
  • _diag/Worker_*.log : un log détaillé pour chaque job traité par le runner, qui mentionne le dépôt et le workflow.
  • Le répertoire de travail (_work/) : les dépôts récupérés, les caches d'outils et les restes des jobs précédents. Les attaquants s'en servent pour déposer des fichiers que des jobs ultérieurs exécuteront.
  • La télémétrie classique de l'hôte : création de processus, connexions sortantes, nouvelles tâches cron ou nouveaux services, clés SSH, et accès aux métadonnées d'instance cloud.

Pour les runners éphémères, GitHub prévient que leurs logs doivent être transférés vers un stockage externe, faute de quoi ils disparaissent avec la machine. Si vos runners tournent sur Kubernetes avec Actions Runner Controller, les logs des pods, le journal d'audit Kubernetes et le runtime de conteneurs du nœud font partie des preuves. L'outil voisin Kubernetes Forensics couvre ce volet.

Délimiter le périmètre d'un incident de runner

  1. Listez tous les runners (organisation, dépôts, entreprise) et comparez-les à votre inventaire. Les noms ou adresses IP inconnus sont supprimés immédiatement, après avoir consigné leurs détails.
  2. Corrélez les enregistrements avec le reste de l'activité de l'acteur dans l'analyseur : onglet Entités → Runners, puis pivotez sur l'acteur et l'adresse IP.
  3. Retrouvez les jobs. Pour un runner malveillant, utilisez les événements workflows.completed_workflow_run du journal d'audit concernant des workflows qui ciblent des labels auto-hébergés pendant la période, ainsi que les logs des jobs eux-mêmes : l'étape « Set up job » affiche le nom du runner et le nom de la machine. Pour un hôte compromis, utilisez les logs Worker_*.
  4. Considérez comme exposés les secrets utilisés par ces jobs. Renouvelez-les, y compris les identifiants de déploiement du dépôt et tout rôle cloud que l'identité machine du runner pouvait assumer.
  5. Reconstruisez tout runner persistant ayant exécuté du code non fiable. Ne le nettoyez pas : réinstallez-le.

Durcissement

  • Utilisez des runners éphémères (./config.sh --ephemeral) ou just-in-time. GitHub ne leur attribue qu'un seul job, ce qui limite la persistance entre les jobs. Consultez la référence des runners auto-hébergés.
  • Placez les runners sensibles dans des groupes de runners restreints à des dépôts et workflows précis. Consultez la page sur la gestion des accès par groupes.
  • Interdisez les runners de niveau dépôt sauf raison particulière. Les propriétaires de l'organisation peuvent restreindre les dépôts autorisés à en créer.
  • Ne rattachez jamais de runners auto-hébergés à des dépôts publics.
  • Attribuez aux hôtes de runners des identités cloud au moindre privilège et filtrez leurs flux sortants. Beaucoup de compromissions de runners se transforment en incidents cloud via le rôle de l'instance.
  • Déclenchez une alerte à chaque enregistrement. C'est un événement rare dans une organisation stable.

À lire aussi

Articles liés

Comment les secrets GitHub Actions fuient malgré le masquage *** : workflows piégés, nouvelles branches, sorties encodées, actions tierces. Les preuves à lire.
Attaque supply chain GitHub fictive analysée de bout en bout : PAT volé, 38 dépôts clonés, clés AWS affichées par un workflow, protection de branche retirée.
Clés AWS, Google Cloud ou Azure fuitées depuis GitHub Actions ou un dépôt : désactivez la clé, tracez-la dans les logs d'audit cloud, puis passez à OIDC.

Cet outil n'est ni affilié à GitHub, Inc. ou à Microsoft Corporation, ni approuvé ou sponsorisé par elles. GitHub et GitHub Actions sont des marques de GitHub, Inc. Les autres noms sont des marques de leurs propriétaires respectifs.