Abusing Github Actions
Informations de base
Sur cette page, vous trouverez :
Un résumé de tous les impacts d'un attaquant parvenant à accéder à une action Github.
Différentes façons d'accéder à une action :
Avoir des permissions pour créer l'action.
Abuser des déclencheurs liés aux pull requests.
Abuser d'autres techniques d'accès externe.
Pivoter à partir d'un dépôt déjà compromis.
Enfin, une section sur les techniques de post-exploitation pour abuser d'une action de l'intérieur (causer les impacts mentionnés).
Résumé des impacts
Pour une introduction sur les Actions Github, consultez les informations de base.
Dans le cas où vous pouvez exécuter des actions Github arbitraires/injecter du code dans un dépôt, vous pourriez être en mesure de :
Voler les secrets de ce dépôt/organisation.
Si vous ne pouvez que injecter, vous pouvez voler ce qui est déjà présent dans le flux de travail.
Abuser des privilèges du dépôt pour accéder à d'autres plateformes telles que AWS et GCP.
Exécuter du code dans des travailleurs personnalisés (si des travailleurs personnalisés sont utilisés) et essayer de pivoter à partir de là.
Écraser le code du dépôt.
Cela dépend des privilèges du
GITHUB_TOKEN
(s'il y en a).Compromettre les déploiements et autres artefacts.
Si le code déploie ou stocke quelque chose, vous pourriez le modifier et obtenir un accès supplémentaire.
GITHUB_TOKEN
Ce "secret" (provenant de ${{ secrets.GITHUB_TOKEN }}
et ${{ github.token }}
) est donné lorsque l'administrateur active cette option :
Ce jeton est le même qu'un Application Github utilisera, donc il peut accéder aux mêmes points de terminaison : https://docs.github.com/en/rest/overview/endpoints-available-for-github-apps
Github devrait publier un flux qui autorise l'accès entre dépôts au sein de GitHub, afin qu'un dépôt puisse accéder à d'autres dépôts internes en utilisant le GITHUB_TOKEN
.
Vous pouvez voir les permissions possibles de ce jeton dans : https://docs.github.com/en/actions/security-guides/automatic-token-authentication#permissions-for-the-github_token
Notez que le jeton expire après que le travail est terminé.
Ces jetons ressemblent à ceci : ghs_veaxARUji7EXszBMbhkr4Nz2dYz0sqkeiur7
Quelques choses intéressantes que vous pouvez faire avec ce jeton :
Notez que dans plusieurs occasions, vous pourrez trouver des jetons d'utilisateur GitHub à l'intérieur des variables d'environnement de Github Actions ou dans les secrets. Ces jetons peuvent vous donner plus de privilèges sur le dépôt et l'organisation.
Il est possible de vérifier les autorisations accordées à un jeton Github dans les dépôts d'autres utilisateurs en vérifiant les journaux des actions :
Exécution Autorisée
Ce serait la manière la plus simple de compromettre les actions Github, car dans ce cas, il est supposé que vous avez accès pour créer un nouveau dépôt dans l'organisation, ou avez des privilèges d'écriture sur un dépôt.
Si vous êtes dans ce scénario, vous pouvez simplement vérifier les techniques de post-exploitation.
Exécution depuis la Création du Dépôt
Dans le cas où les membres d'une organisation peuvent créer de nouveaux dépôts et que vous pouvez exécuter des actions github, vous pouvez créer un nouveau dépôt et voler les secrets définis au niveau de l'organisation.
Exécution depuis une Nouvelle Branche
Si vous pouvez créer une nouvelle branche dans un dépôt qui contient déjà une Action Github configurée, vous pouvez la modifier, télécharger le contenu, puis exécuter cette action depuis la nouvelle branche. De cette manière, vous pouvez exfiltrer les secrets au niveau du dépôt et de l'organisation (mais vous devez savoir comment ils sont appelés).
Vous pouvez rendre l'action modifiée exécutable manuellement, lorsqu'une PR est créée ou lorsque du code est poussé (selon le niveau de bruit que vous souhaitez générer) :
Exécution Forked
Il existe différents déclencheurs qui pourraient permettre à un attaquant d'exécuter une action Github d'un autre dépôt. Si ces actions déclenchables sont mal configurées, un attaquant pourrait les compromettre.
pull_request
pull_request
Le déclencheur de workflow pull_request
exécutera le workflow à chaque fois qu'une pull request est reçue avec quelques exceptions : par défaut, si c'est la première fois que vous collaborez, un mainteneur devra approuver l'exécution du workflow :
Comme la limite par défaut est pour les contributeurs de première fois, vous pourriez contribuer en corrigant un bug/une faute de frappe valide, puis envoyer d'autres PR pour abuser de vos nouveaux privilèges pull_request
.
J'ai testé cela et cela ne fonctionne pas : Une autre option serait de créer un compte avec le nom de quelqu'un qui a contribué au projet et a supprimé son compte.
De plus, par défaut, empêche les autorisations d'écriture et l'accès aux secrets du dépôt cible comme mentionné dans la documentation :
À l'exception de
GITHUB_TOKEN
, les secrets ne sont pas transmis au runner lorsqu'un workflow est déclenché à partir d'un dépôt forké. LeGITHUB_TOKEN
a des autorisations en lecture seule dans les pull requests à partir de dépôts forkés.
Un attaquant pourrait modifier la définition de l'action Github afin d'exécuter des choses arbitraires et d'ajouter des actions arbitraires. Cependant, il ne pourra pas voler de secrets ou écraser le dépôt en raison des limitations mentionnées.
Oui, si l'attaquant modifie dans la PR l'action Github qui sera déclenchée, son action Github sera celle utilisée et non celle du dépôt d'origine !
Comme l'attaquant contrôle également le code en cours d'exécution, même s'il n'y a pas de secrets ou d'autorisations d'écriture sur le GITHUB_TOKEN
, un attaquant pourrait par exemple téléverser des artefacts malveillants.
pull_request_target
pull_request_target
Le déclencheur de workflow pull_request_target
a des autorisations d'écriture sur le dépôt cible et accès aux secrets (et ne demande pas d'autorisation).
Notez que le déclencheur de workflow pull_request_target
s'exécute dans le contexte de base et non dans celui donné par la PR (pour ne pas exécuter de code non fiable). Pour plus d'informations sur pull_request_target
consultez la documentation.
De plus, pour plus d'informations sur cet usage spécifique dangereux, consultez ce billet de blog Github.
Il pourrait sembler que parce que le workflow exécuté est celui défini dans le base et non dans la PR, il est sécurisé d'utiliser pull_request_target
, mais il y a quelques cas où ce n'est pas le cas.
Et celui-ci aura accès aux secrets.
workflow_run
workflow_run
Le déclencheur workflow_run permet d'exécuter un workflow à partir d'un autre lorsque celui-ci est terminé
, demandé
ou en cours
.
Dans cet exemple, un workflow est configuré pour s'exécuter après que le workflow "Run Tests" séparé soit terminé :
De plus, selon la documentation : Le flux de travail démarré par l'événement workflow_run
est capable d'accéder à des secrets et d'écrire des jetons, même si le flux de travail précédent ne l'était pas.
Ce type de flux de travail pourrait être attaqué s'il dépend d'un flux de travail qui peut être déclenché par un utilisateur externe via pull_request
ou pull_request_target
. Quelques exemples de vulnérabilités peuvent être trouvés dans ce blog. Le premier consiste en ce que le flux de travail déclenché par workflow_run
télécharge le code des attaquants : ${{ github.event.pull_request.head.sha }}
Le deuxième consiste à transmettre un artefact du code non fiable au flux de travail workflow_run
et à utiliser le contenu de cet artefact d'une manière qui le rend vulnérable à une exécution de code à distance (RCE).
workflow_call
workflow_call
À FAIRE
À FAIRE : Vérifier si lorsqu'il est exécuté à partir d'une pull_request
, le code utilisé/téléchargé est celui de l'origine ou de la PR forkée
Abus de l'exécution forkée
Nous avons mentionné toutes les façons dont un attaquant externe pourrait parvenir à faire exécuter un flux de travail GitHub, voyons maintenant comment ces exécutions, si mal configurées, pourraient être abusées :
Exécution de vérification non fiable
Dans le cas de pull_request
, le flux de travail va être exécuté dans le contexte de la PR (il exécutera donc le code malveillant des PR), mais quelqu'un doit l'autoriser en premier lieu et il s'exécutera avec certaines limitations.
Dans le cas d'un flux de travail utilisant pull_request_target
ou workflow_run
qui dépend d'un flux de travail pouvant être déclenché à partir de pull_request_target
ou pull_request
, le code du dépôt d'origine sera exécuté, donc l'attaquant ne peut pas contrôler le code exécuté.
Cependant, si l'action a une vérification PR explicite qui récupérera le code de la PR (et non de la base), elle utilisera le code contrôlé par l'attaquant. Par exemple (vérifiez la ligne 12 où le code de la PR est téléchargé) :
Le code potentiellement non fiable est exécuté pendant npm install
ou npm build
car les scripts de construction et les paquets référencés sont contrôlés par l'auteur de la PR.
Un dork GitHub pour rechercher des actions vulnérables est : event.pull_request pull_request_target extension:yml
cependant, il existe différentes façons de configurer les tâches à exécuter de manière sécurisée même si l'action est configurée de manière non sécurisée (comme utiliser des conditionnels sur l'acteur générant la PR).
Injections de scripts de contexte
Notez qu'il existe certains contextes GitHub dont les valeurs sont contrôlées par l'utilisateur créant la PR. Si l'action GitHub utilise ces données pour exécuter quelque chose, cela pourrait entraîner une exécution de code arbitraire :
pageGh Actions - Context Script InjectionsInjection de script GITHUB_ENV
Selon la documentation : Vous pouvez rendre une variable d'environnement disponible pour toutes les étapes suivantes dans une tâche de flux de travail en définissant ou en mettant à jour la variable d'environnement et en l'écrivant dans le fichier d'environnement GITHUB_ENV
.
Si un attaquant pouvait injecter n'importe quelle valeur dans cette variable env, il pourrait injecter des variables d'environnement qui pourraient exécuter du code dans les étapes suivantes telles que LD_PRELOAD ou NODE_OPTIONS.
Par exemple (ceci et cela), imaginez un flux de travail qui fait confiance à un artefact téléchargé pour stocker son contenu dans la variable d'environnement GITHUB_ENV
. Un attaquant pourrait télécharger quelque chose comme ceci pour le compromettre :
Actions GitHub tierces vulnérables
Comme mentionné dans cet article de blog, cette Action GitHub permet d'accéder à des artefacts provenant de différents flux de travail et même de dépôts différents.
Le problème est que si le paramètre path
n'est pas défini, l'artefact est extrait dans le répertoire actuel et peut remplacer des fichiers qui pourraient être utilisés ultérieurement ou même exécutés dans le flux de travail. Par conséquent, si l'artefact est vulnérable, un attaquant pourrait en abuser pour compromettre d'autres flux de travail faisant confiance à l'artefact.
Exemple de flux de travail vulnérable :
Cela pourrait être attaqué avec ce flux de travail :
Autre accès externe
Détournement de dépôt de namespace supprimé
Si un compte change de nom, un autre utilisateur pourrait enregistrer un compte avec ce nom après un certain temps. Si un dépôt avait moins de 100 étoiles avant le changement de nom, Github permettra au nouvel utilisateur enregistré avec le même nom de créer un dépôt avec le même nom que celui supprimé.
Ainsi, si une action utilise un dépôt d'un compte inexistant, il est toujours possible qu'un attaquant crée ce compte et compromette l'action.
Si d'autres dépôts utilisaient des dépendances de ces dépôts d'utilisateur, un attaquant pourra les détourner. Voici une explication plus complète : https://blog.nietaanraken.nl/posts/gitub-popular-repository-namespace-retirement-bypass/
Pivotement de dépôt
Dans cette section, nous parlerons des techniques qui permettraient de pivoter d'un dépôt à un autre en supposant que nous avons un certain type d'accès sur le premier (vérifiez la section précédente).
Empoisonnement de cache
Un cache est maintenu entre les exécutions de flux de travail dans la même branche. Cela signifie que si un attaquant compromet un paquet qui est ensuite stocké dans le cache et téléchargé et exécuté par un flux de travail plus privilégié, il pourra également compromettre ce flux de travail.
pageGH Actions - Cache PoisoningEmpoisonnement d'artefacts
Les flux de travail pourraient utiliser des artefacts d'autres flux de travail et même de dépôts, si un attaquant parvient à compromettre l'action Github qui télécharge un artefact qui est ensuite utilisé par un autre flux de travail, il pourrait compromettre les autres flux de travail :
pageGh Actions - Artifact PoisoningPost-exploitation à partir d'une action
Accès à AWS et GCP via OIDC
Consultez les pages suivantes :
pageAWS - Federation AbusepageGCP - Federation AbuseAccès aux secrets
Si vous injectez du contenu dans un script, il est intéressant de savoir comment accéder aux secrets :
Si le secret ou le jeton est défini comme une variable d'environnement, il peut être directement accédé via l'environnement en utilisant
printenv
.
Si le secret est utilisé directement dans une expression, le script shell généré est stocké sur le disque et est accessible.
cat /home/runner/work/_temp/*
Pour une action personnalisée, le risque peut varier en fonction de la manière dont un programme utilise le secret obtenu à partir de l'argument :
Abus des runners auto-hébergés
La façon de trouver quelles Actions Github sont exécutées sur une infrastructure non-Github est de rechercher runs-on: self-hosted
dans la configuration yaml de l'Action Github.
Les runners auto-hébergés pourraient avoir accès à des informations extra sensibles, à d'autres systèmes réseau (points d'extrémité vulnérables dans le réseau ? service de métadonnées ?) ou, même s'ils sont isolés et détruits, plus d'une action pourrait être exécutée en même temps et l'action malveillante pourrait voler les secrets de l'autre.
Sur les runners auto-hébergés, il est également possible d'obtenir les secrets du processus _Runner.Listener qui contiendra tous les secrets des workflows à n'importe quelle étape en vidant sa mémoire :
Consultez cet article pour plus d'informations.
Registre d'images Docker Github
Il est possible de créer des actions Github qui vont construire et stocker une image Docker à l'intérieur de Github. Un exemple peut être trouvé dans l'encadré suivant :
Dernière mise à jour