Abusing Github Actions
Last updated
Last updated
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
In this page you will find:
A summary of all the impacts of an attacker managing to access a Github Action
Different ways to get access to an action:
Having permissions to create the action
Abusing pull request related triggers
Abusing other external access techniques
Pivoting from an already compromised repo
Finally, a section about post-exploitation techniques to abuse an action from inside (cause the mentioned impacts)
For an introduction about Github Actions check the basic information.
If you can exécuter du code arbitraire dans GitHub Actions within a repository, you may be able to:
Voler des secrets mounted to the pipeline and abuser des privilèges de la pipeline to gain unauthorized access to external platforms, such as AWS and GCP.
Compromettre des déploiements and other artifacts.
If the pipeline deploys or stores assets, you could alter the final product, enabling a supply chain attack.
Exécuter du code dans des workers personnalisés to abuse computing power and pivot to other systems.
Écraser le code du repository, depending on the permissions associated with the GITHUB_TOKEN
.
This "secret" (coming from ${{ secrets.GITHUB_TOKEN }}
and ${{ github.token }}
) is given when the admin enables this option:
This token is the same one a Github Application will use, so it can access the same endpoints: https://docs.github.com/en/rest/overview/endpoints-available-for-github-apps
Github should release a flow that allows cross-repository access within GitHub, so a repo can access other internal repos using the GITHUB_TOKEN
.
You can see the possible permissions of this token in: https://docs.github.com/en/actions/security-guides/automatic-token-authentication#permissions-for-the-github_token
Note that the token expires after the job has completed.
These tokens looks like this: ghs_veaxARUji7EXszBMbhkr4Nz2dYz0sqkeiur7
Some interesting things you can do with this token:
Notez qu'à plusieurs reprises, vous pourrez trouver des jetons d'utilisateur github dans les environnements 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 permissions accordées à un Github Token dans les dépôts d'autres utilisateurs en vérifiant les logs des actions :
Ce serait le moyen le plus simple de compromettre les actions Github, car ce cas suppose que vous avez accès à créer un nouveau dépôt dans l'organisation, ou que vous avez des privilèges d'écriture sur un dépôt.
Si vous êtes dans ce scénario, vous pouvez simplement consulter les techniques de post-exploitation.
Dans le cas où des 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.
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'un PR est créé ou lorsque du code est poussé (selon le niveau de discrétion que vous souhaitez avoir) :
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 être en mesure de les compromettre.
pull_request
Le déclencheur de workflow pull_request
exécutera le workflow chaque fois qu'une demande de tirage 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 limitation par défaut est pour les contributeurs de première fois, vous pourriez contribuer en corrigeant un bug/typo valide et ensuite envoyer d'autres PRs pour abuser de vos nouveaux privilèges pull_request
.
J'ai testé cela et ça 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, cela empêche les permissions d'écriture et l'accès aux secrets du dépôt cible comme mentionné dans les docs:
À l'exception de
GITHUB_TOKEN
, les secrets ne sont pas transmis au runner lorsqu'un workflow est déclenché depuis un dépôt forké. LeGITHUB_TOKEN
a des permissions en lecture seule dans les demandes de tirage provenant 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 des secrets ou écraser le dépôt en raison des limitations mentionnées.
Oui, si l'attaquant change 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 exécuté, même s'il n'y a pas de secrets ou de permissions d'écriture sur le GITHUB_TOKEN
, un attaquant pourrait par exemple télécharger des artefacts malveillants.
pull_request_target
Le déclencheur de workflow pull_request_target
a des permissions d'écriture sur le dépôt cible et accès aux secrets (et ne demande pas de permission).
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'infos sur pull_request_target
, consultez les docs.
De plus, pour plus d'infos sur cet usage dangereux spécifique, consultez ce post de blog github.
Cela peut sembler parce que le workflow exécuté est celui défini dans la base et non dans la PR, qu'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
Le déclencheur workflow_run permet d'exécuter un workflow à partir d'un autre lorsqu'il est complété
, demandé
ou en cours
.
Dans cet exemple, un workflow est configuré pour s'exécuter après que le workflow séparé "Exécuter des tests" soit terminé :
Moreover, according to the docs: Le workflow démarré par l'événement workflow_run
est capable d'accéder aux secrets et d'écrire des tokens, même si le workflow précédent ne l'était pas.
Ce type de workflow pourrait être attaqué s'il dépend d'un workflow qui peut être déclenché par un utilisateur externe via pull_request
ou pull_request_target
. Quelques exemples vulnérables peuvent être trouvés dans ce blog. Le premier consiste à ce que le workflow déclenché par workflow_run
télécharge le code des attaquants : ${{ github.event.pull_request.head.sha }}
Le second consiste à passer un artifact du code non fiable au workflow workflow_run
et à utiliser le contenu de cet artifact d'une manière qui le rend vulnérable à RCE.
workflow_call
TODO
TODO : Vérifiez si, lorsqu'il est exécuté à partir d'un pull_request, le code utilisé/téléchargé est celui de l'origine ou de la PR forkée.
Nous avons mentionné toutes les façons dont un attaquant externe pourrait réussir à faire exécuter un workflow github, maintenant examinons comment ces exécutions, si mal configurées, pourraient être abusées :
Dans le cas de pull_request
, le workflow va être exécuté dans le contexte de la PR (il exécutera donc le code malveillant de la PR), mais quelqu'un doit l'autoriser d'abord et il s'exécutera avec certaines limitations.
Dans le cas d'un workflow utilisant pull_request_target
ou workflow_run
qui dépend d'un workflow pouvant être déclenché à partir de pull_request_target
ou pull_request
, le code du dépôt original sera exécuté, donc l'attaquant ne peut pas contrôler le code exécuté.
Cependant, si l'action a un checkout PR explicite qui récupère le code de la PR (et non de la base), elle utilisera le code contrôlé par les attaquants. Par exemple (voir 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 packages 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 jobs pour être exécutés en toute sécurité même si l'action est configurée de manière non sécurisée (comme l'utilisation de conditionnelles sur qui est l'acteur générant la PR).
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 quoi que ce soit, cela pourrait conduire à l'exécution de code arbitraire :
Gh Actions - Context Script InjectionsD'après les docs : Vous pouvez rendre une variable d'environnement disponible pour toutes les étapes suivantes dans un job de workflow 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 à l'intérieur de 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 ceci), imaginez un workflow qui fait confiance à un artifact téléchargé pour stocker son contenu à l'intérieur de la variable d'environnement GITHUB_ENV
. Un attaquant pourrait télécharger quelque chose comme ceci pour le compromettre :
Comme mentionné dans cet article de blog, cette action Github permet d'accéder à des artifacts provenant de différents workflows et même de dépôts.
Le problème est que si le paramètre path
n'est pas défini, l'artifact est extrait dans le répertoire actuel et peut écraser des fichiers qui pourraient être utilisés ou même exécutés dans le workflow. Par conséquent, si l'artifact est vulnérable, un attaquant pourrait en abuser pour compromettre d'autres workflows faisant confiance à l'artifact.
Exemple de workflow vulnérable :
Cela pourrait être attaqué avec ce flux de travail :
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é.
Donc, si une action utilise un dépôt d'un compte inexistant, il est toujours possible qu'un attaquant puisse créer ce compte et compromettre 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/
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 au premier (voir la section précédente).
Un cache est maintenu entre les exécutions de workflow dans la même branche. Ce qui signifie que si un attaquant compromet un package qui est ensuite stocké dans le cache et téléchargé et exécuté par un workflow plus privilégié, il pourra également compromettre ce workflow.
GH Actions - Cache PoisoningLes workflows pourraient utiliser des artifacts d'autres workflows et même de dépôts, si un attaquant parvient à compromettre l'Action Github qui télécharge un artifact qui est ensuite utilisé par un autre workflow, il pourrait compromettre les autres workflows :
Gh Actions - Artifact PoisoningConsultez les pages suivantes :
AWS - Federation AbuseGCP - Federation AbuseSi vous injectez du contenu dans un script, il est intéressant de savoir comment vous pouvez accéder aux secrets :
Si le secret ou le token est défini comme une variable d'environnement, il peut être directement accessible via l'environnement en utilisant printenv
.
Si le secret est utilisé directement dans une expression, le script shell généré est stocké sur 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 qu'il a obtenu de l'argument :
La façon de trouver quelles Github Actions sont exécutées dans 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 peuvent 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'il est isolé et détruit, plus d'une action peut être exécutée en même temps et la malveillante pourrait voler les secrets de l'autre.
Dans 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.
Il est possible de créer des actions Github qui construiront et stockeront une image Docker à l'intérieur de Github. Un exemple peut être trouvé dans le suivant :
Apprenez et pratiquez le Hacking AWS :HackTricks Training AWS Red Team Expert (ARTE) Apprenez et pratiquez le Hacking GCP : HackTricks Training GCP Red Team Expert (GRTE)