
Octoscan é um scanner de vulnerabilidades estático para fluxos de trabalho de ação do GitHub.
$ go mod tidy
$ go build
Ou com docker:
$ docker pull ghcr.io/synacktiv/octoscan:latest
O Octoscan pode ser executado contra um repositório git local, ou você pode baixar todos os workflows com a ação dl:
$ octoscan dl -h
Octoscan.
Usage:
octoscan dl [options] --org <org> [--repo <repo> --token <pat> --default-branch --max-branches <num> --path <path> --output-dir <dir> --include-archives]
Options:
-h, --help Show help
-d, --debug Debug output
--verbose Verbose output
--org <org> Organizations to target
--repo <repo> Repository to target
--token <pat> GHP to authenticate to GitHub
--default-branch Only download workflows from the default branch
--max-branches <num> Limit the number of branches to download
--path <path> GitHub file path to download [default: .github/workflows]
--output-dir <dir> Output dir where to download files [default: octoscan-output]
--include-archives Also download archived repositories
./octoscan dl --token ghp_<token> --org apache --repo incubator-answer
Se você não souber o que executar, basta executar isto:
./octoscan scan path/to/repos/ --disable-rules shellcheck,local-action --filter-triggers external
Isso reduzirá os falsos positivos e trará os resultados mais interessantes.
Se você baixou os workflows com o comando dl, pode ter workflows duplicados, pois, por padrão, o octoscan baixa todos os workflows de todos os branches. Para excluir workflows duplicados e acelerar a análise, você pode usar o comando fdupes antes de executar a análise:
fdupes -n -r -N -d path/to/repo
$ octoscan scan -h
octoscan
Usage:
octoscan scan [options] --list-rules
octoscan scan [options] <target>
octoscan scan [options] <target> [--debug-rules --filter-triggers=<triggers> --filter-run --ignore=<pattern> ((--disable-rules | --enable-rules ) <rules>) --config-file <config>]
Options:
-h, --help
-v, --version
-d, --debug
--verbose
--format <format> Output format, json, sarif or custom template to format error messages in Go template syntax. See https://github.com/rhysd/actionlint/tree/main/docs/usage.md#format
--oneline Use one line per one error. Useful for reading error messages from programs
Args:
<target> Target File or directory to scan
--filter-triggers <triggers> Scan workflows with specific triggers (comma separated list: "push,pull_request_target" or pre-configured: external/allnopr)
--filter-run Search for expression injection only in run shell scripts.
--ignore <pattern> Regular expression matching to error messages you want to ignore.
--disable-rules <rules> Disable specific rules. Split on ","
--enable-rules <rules> Enable specific rules, this will disable all other rules. Split on ","
--debug-rules Enable debug rules.
--config-file <config> Config file.
Examples:
$ octoscan scan ci.yml --disable-rules shellcheck,local-action --filter-triggers external
Esta ferramenta também pode ser usada diretamente como uma GitHub Action para escanear seu repositório em eventos push/pull_request. Para mais informações, consulte este repositório.
A lista completa de regras pode ser encontrada com este comando:
$ octoscan scan --list-rules
2024/08/07 16:50:48 [INFO] Available rules
- shellcheck
Checks for shell script sources in "run:" using shellcheck
- credentials
Checks for credentials in "services:" configuration
- dangerous-action
Check for dangerous actions.
- dangerous-checkout
Check for dangerous checkout.
- expression-injection
Check for expression injection.
- dangerous-write
Check for dangerous write operation on $GITHUB_OUTPUT or $GITHUB_ENV.
- local-action
Check for local actions.
- runner-label
Checks for GitHub-hosted and preset self-hosted runner labels in "runs-on:"
- unsecure-commands
Check 'ACTIONS_ALLOW_UNSECURE_COMMANDS' env variable.
- known-vulnerability
Check for known vulnerabilities.
- bot-check
Check for if statements that are based on a bot identity.
- dangerous-artefact
Check for workflow that upload artefacts containing sensitive files.
- debug-external-trigger
Check for workflow that can be externally triggered.
- debug-artefacts
Check for workflow that upload artefacts.
- debug-js-exec
Check for workflow that execute system commands in JS scripts.
- debug-oidc-action
Check for OIDC actions.
- repo-jacking
Verify that external actions are pointing to a valid GitHub user or organization.
Gatilhos como workflow_run ou pull_request_target são executados em um contexto privilegiado, pois têm acesso de leitura aos segredos e potencialmente acesso de escrita no repositório alvo. Realizar um checkout explícito do código não confiável resultará no download do código do invasor nesse contexto.

Esta regra alerta o usuário se uma action perigosa for usada. Ela é focada principalmente em artefatos não confiáveis.
É prática comum usar artefatos para transmitir dados entre diferentes workflows. Frequentemente encontramos isso com o gatilho workflow_run, em que o workflow acionador prepara alguns dados que serão enviados ao workflow acionado. Dada a natureza não confiável desses dados de artefato, é crucial tratá-los com cautela e reconhecê-los como uma ameaça potencial. A vulnerabilidade surge do fato de que entidades externas, como agentes maliciosos, podem influenciar o conteúdo dos dados do artefato.

O GitHub cria variáveis de ambiente padrão que podem ser usadas em cada etapa de um workflow. As variáveis GITHUB_ENV e GITHUB_OUTPUT são particularmente interessantes. É possível definir uma variável de ambiente em uma etapa e usar essa variável em outra. Isso pode ser feito gravando-a na variável associada. Se um usuário puder controlar o conteúdo da variável que está sendo definida, isso pode levar à execução arbitrária de código.

Cada gatilho de workflow vem com um contexto GitHub associado, oferecendo informações abrangentes sobre o evento que o iniciou. Isso inclui detalhes sobre o usuário que acionou o evento, o nome do branch e outras informações contextuais relevantes. Certos componentes desses dados do evento, como o nome do repositório base ou o número do pull request, não podem ser manipulados ou explorados para injeção pelo usuário que iniciou o evento (por exemplo, no caso de um pull request). Isso garante um nível de controle e segurança sobre as informações fornecidas pelo contexto GitHub durante a execução do workflow.
No entanto, alguns elementos podem ser controlados por um atacante e devem ser sanitizados antes de serem usados. Aqui está a lista desses elementos:
github.event.issue.titlegithub.event.issue.bodygithub.event.pull_request.titlegithub.event.pull_request.bodygithub.event.comment.bodygithub.event.review.bodygithub.event.pages.*.page_namegithub.event.commits.*.messagegithub.event.head_commit.messagegithub.event.head_commit.author.emailgithub.event.head_commit.author.namegithub.event.commits.*.author.emailgithub.event.commits.*.author.namegithub.event.pull_request.head.refgithub.event.pull_request.head.labelgithub.event.pull_request.head.repo.default_branchgithub.head_refenv.*steps.*.outputs.*needs.*.outputs.*
O GitHub oferece a possibilidade de hospedar seus próprios runners e personalizar o ambiente usado para executar jobs em workflows. Esses runners são chamados de self-hosted.
Existem dois tipos de runners self-hosted: efêmeros e não efêmeros. Por padrão, os runners são não efêmeros, o que significa que o ambiente usado pelo runner não é limpo após a conclusão de um job. Se um atacante conseguir executar código em um runner não efêmero, ele poderá comprometê-lo adicionando um processo em segundo plano e roubando segredos sensíveis. Esses tipos de runners são, portanto, realmente sensíveis.

Runners não efêmeros podem ser identificados observando os logs de execução. Uma ferramenta chamada gato pode ser usada para automatizar esse processo.
A vulnerabilidade de repo jacking foi apresentada na DEFCON 31 por Asi Greenholts. Essa vulnerabilidade ocorre quando uma GitHub Action referencia uma action de uma organização ou usuário do GitHub inexistente.

Observe que esta regra precisa de internet para verificar se o ataque é possível ou não. Todas as outras verificações são realizadas offline.
As actions têm a capacidade de interagir com a máquina do runner, permitindo definir variáveis de ambiente, definir valores de saída para uso por outras actions, incorporar mensagens de depuração nos logs de saída e executar várias outras tarefas. No entanto, antes de 2020, era possível controlar variáveis de ambiente gravando dados no STDOUT assim:
run: |
echo "##[set-env name=ENV_NAME;]value"
# or
echo "echo "::set-env name=ENV_NAME::value"
Os comandos de workflow implementados eram inerentemente inseguros devido à prática comum de registrar logs no STDOUT. Essa vulnerabilidade abriu caminho para possíveis ataques, permitindo que payloads maliciosos fossem facilmente injetados e acionassem o comando set-env. A capacidade de modificar variáveis de ambiente introduziu múltiplos caminhos para execução remota de código, com um payload particularmente óbvio sendo o demonstrado anteriormente. Essa vulnerabilidade foi inicialmente reportada por um pesquisador de segurança do Project Zero.
Embora o comando set-env esteja obsoleto e não possa ser usado por padrão, se um desenvolvedor definir a variável de ambiente ACTIONS_ALLOW_UNSECURE_COMMANDS em um workflow, o comando set-env fica disponível e pode ser usado:

É possível contornar a seguinte verificação:
jobs:
merge-dependabot-pr:
runs-on: ubuntu-latest
if: github.actor == 'dependabot[bot]'
steps:
...
A ideia do ataque é acionar o Dependabot em um repositório bifurcado (fork) de modo que um PR no repositório bifurcado seja feito pelo Dependabot; em seguida, um PR do branch do Dependabot é aberto no repositório vulnerável e, finalmente, o Dependabot é acionado novamente para executar o workflow vulnerável.

Você pode encontrar todos os detalhes de exploração aqui: https://www.synacktiv.com/publications/github-actions-exploitation-dependabot
Procura por actions com vulnerabilidades conhecidas com base em osv.dev.
Verifica workflows que enviam artefatos contendo arquivos sensíveis como .git/config. Esta regra é baseada em este artigo.
Verifica se há credenciais na configuração services:. Esta regra vem do actionlint.

Executa o shellcheck em todas as tarefas bash. Esta regra vem do actionlint.
Levanta um alerta se uma GitHub Action local for usada. Por enquanto, a ferramenta não consegue analisar arquivos de actions locais, então um alerta é levantado, pois eles também podem conter vulnerabilidades.
Detecta actions OIDC. Workflows que usam actions OIDC podem ser um bom alvo para acessar alguns provedores de nuvem. Não há vulnerabilidade associada a esta regra, mas examinar essa action mais de perto pode ser interessante caso exista uma vulnerabilidade que não seja encontrada por esta ferramenta.
💡 Esta agora é uma regra de depuração; você precisa adicionar --debug-rules para procurar por esta.
Esta ferramenta não poderia ter sido desenvolvida sem o actionlint. Muitos agradecimentos a @rhysd.