Gh Actions - Context Script Injections
Reading time: 5 minutes
tip
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)
Apprenez et pratiquez le hacking Azure :
HackTricks Training Azure Red Team Expert (AzRTE)
Soutenir HackTricks
- Vérifiez les plans d'abonnement !
- Rejoignez le đŹ groupe Discord ou le groupe telegram ou suivez-nous sur Twitter đŠ @hacktricks_live.
- Partagez des astuces de hacking en soumettant des PR au HackTricks et HackTricks Cloud dépÎts github.
Comprendre le risque
GitHub Actions évalue les expressions ${{ ... }} avant que l'étape n'exécute. La valeur évaluée est insérée dans le programme de l'étape (pour les étapes run, un script shell). Si vous interpolez des entrées non fiables directement dans run:, l'attaquant contrÎle une partie du script shell et peut exécuter des commandes arbitraires.
Docs: https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions and contexts/functions: https://docs.github.com/en/actions/learn-github-actions/contexts
Points clés :
- L'évaluation a lieu avant l'exécution. Le script run est généré avec toutes les expressions résolues, puis exécuté par le shell.
- De nombreux contexts contiennent des champs contrÎlés par l'utilisateur selon l'événement déclencheur (issues, PRs, comments, discussions, forks, stars, etc.). Voir la référence sur les entrées non fiables : https://securitylab.github.com/resources/github-actions-untrusted-input/
- Le quoting du shell à l'intérieur de run: n'est pas une défense fiable, car l'injection se produit lors de l'étape de rendu du template. Les attaquants peuvent sortir des guillemets ou injecter des opérateurs via des entrées spécialement conçues.
ModĂšle vulnĂ©rable â RCE on runner
Workflow vulnérable (déclenché lorsqu'une personne ouvre une nouvelle issue):
name: New Issue Created
on:
issues:
types: [opened]
jobs:
deploy:
runs-on: ubuntu-latest
permissions:
issues: write
steps:
- name: New issue
run: |
echo "New issue ${{ github.event.issue.title }} created"
- name: Add "new" label to issue
uses: actions-ecosystem/action-add-labels@v1
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
labels: new
Si un attaquant ouvre un issue avec le titre $(id), l'étape rendue devient :
echo "New issue $(id) created"
La substitution de commande exécute id sur le runner. Exemple de sortie :
New issue uid=1001(runner) gid=118(docker) groups=118(docker),4(adm),100(users),999(systemd-journal) created
Pourquoi les guillemets ne suffisent pas :
- Les expressions sont évaluées en premier, puis le script résultant s'exécute. Si la valeur non fiable contient $(...),
;,"/', ou des retours à la ligne, elle peut modifier la structure du programme malgré vos guillemets.
ModÚle sûr (shell variables via env)
Mitigation correcte : copiez l'entrée non fiable dans une variable d'environnement, puis utilisez l'expansion native du shell ($VAR) dans le script d'exécution. Ne la réinjectez pas avec ${{ ... }} dans la commande.
# safe
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: New issue
env:
TITLE: ${{ github.event.issue.title }}
run: |
echo "New issue $TITLE created"
Remarques:
- Ăvitez d'utiliser ${{ env.TITLE }} dans run:. Cela rĂ©introduit le rendu du template dans la commande et entraĂźne le mĂȘme risque d'injection.
- Privilégiez le passage d'entrées non fiables via le mapping env: et référencez-les avec $VAR dans run:.
Surfaces déclenchables par un lecteur (à traiter comme non fiables)
Les comptes avec seulement la permission de lecture sur les dĂ©pĂŽts publics peuvent quand mĂȘme dĂ©clencher de nombreux Ă©vĂ©nements. Tout champ des contextes dĂ©rivĂ©s de ces Ă©vĂ©nements doit ĂȘtre considĂ©rĂ© comme contrĂŽlĂ© par un attaquant sauf preuve du contraire. Exemples:
- issues, issue_comment
- discussion, discussion_comment (les organisations peuvent restreindre les discussions)
- pull_request, pull_request_review, pull_request_review_comment
- pull_request_target (dangereux s'il est mal utilisé, s'exécute dans le contexte du dépÎt de base)
- fork (n'importe qui peut forker des dépÎts publics)
- watch (le fait d'ajouter une étoile à un dépÎt)
- Indirectement via des chaĂźnes workflow_run/workflow_call
Les champs spécifiques contrÎlés par un attaquant dépendent de l'événement. Consultez le guide de GitHub Security Lab sur les entrées non fiables : https://securitylab.github.com/resources/github-actions-untrusted-input/
Conseils pratiques
- Minimisez l'utilisation d'expressions dans run:. Privilégiez le mapping env: + $VAR.
- Si vous devez transformer une entrée, faites-le dans le shell en utilisant des outils sûrs (printf %q, jq -r, etc.), en partant toujours d'une variable shell.
- Soyez particuliĂšrement prudent lors de l'interpolation de branch names, PR titles, usernames, labels, discussion titles et PR head refs dans des scripts, des options en ligne de commande ou des chemins de fichiers.
- Pour les reusable workflows et composite actions, appliquez le mĂȘme schĂ©ma : mappez vers env puis rĂ©fĂ©rencez $VAR.
Références
- GitHub Actions: A Cloudy Day for Security - Part 1
- GitHub workflow syntax
- Contexts and expression syntax
- Untrusted input reference for GitHub Actions
tip
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)
Apprenez et pratiquez le hacking Azure :
HackTricks Training Azure Red Team Expert (AzRTE)
Soutenir HackTricks
- Vérifiez les plans d'abonnement !
- Rejoignez le đŹ groupe Discord ou le groupe telegram ou suivez-nous sur Twitter đŠ @hacktricks_live.
- Partagez des astuces de hacking en soumettant des PR au HackTricks et HackTricks Cloud dépÎts github.
HackTricks Cloud