Files
CoM-c2itall/providers/Linode/attack_box.yml
T
Operator 0799bfbae8 Initial public portfolio release
Sanitized version of red team infrastructure automation platform.
Operational content (implant pipelines, lures, credential capture)
replaced with documented stubs. Architecture and infrastructure
automation code intact.
2026-06-23 16:12:14 -04:00

252 lines
9.2 KiB
YAML

---
# Linode Attack Box Deployment Playbook
# Based on attk-box-setup but optimized for headless server deployment
- name: Deploy Attack Box on Linode
hosts: localhost
connection: local
gather_facts: false
vars:
ansible_python_interpreter: "{{ ansible_playbook_python }}"
deployment_type: "attack_box"
attack_box_name: "{{ attack_box_name | default('a-' + deployment_id) }}"
attack_box_type: "{{ attack_box_type | default('kali') }}"
linode_instance_type: "{{ linode_instance_type | default('g6-standard-4') }}"
linode_region: "{{ linode_region | default('us-east') }}"
ssh_key_name: "{{ ssh_key_path | default('c2deploy_' + attack_box_name) | basename | regex_replace('\\.pub$', '') }}"
# Attack box image mapping (headless versions)
attack_box_images:
kali: "linode/kali"
custom: "linode/kali" # Use Kali as base for custom builds
quick_recon: "linode/kali" # Kali Linux for easy tool expansion
tasks:
- name: Debug attack box deployment
debug:
msg: "Deploying {{ attack_box_type }} attack box on Linode in {{ linode_region }}"
- name: Set attack box image
set_fact:
attack_box_image: "{{ attack_box_images[attack_box_type] | default('linode/kali') }}"
- name: Check if SSH key exists (should be pre-generated)
stat:
path: "~/.ssh/{{ ssh_key_name }}"
register: ssh_key_check
- name: Generate SSH key pair for attack box (if not exists)
openssh_keypair:
path: "~/.ssh/{{ ssh_key_name }}"
type: rsa
size: 2048
force: no
register: ssh_key_result
when: not ssh_key_check.stat.exists
- name: Read public key content
slurp:
src: "~/.ssh/{{ ssh_key_name }}.pub"
register: public_key_content
- name: Add SSH key to Linode
uri:
url: "https://api.linode.com/v4/profile/sshkeys"
method: POST
headers:
Authorization: "Bearer {{ linode_token }}"
Content-Type: "application/json"
body_format: json
body:
label: "{{ ssh_key_name }}"
ssh_key: "{{ public_key_content.content | b64decode | trim }}"
status_code: [200, 201]
register: linode_ssh_key
ignore_errors: yes
- name: Generate strong root password
set_fact:
root_password: "{{ lookup('password', '/dev/null chars=ascii_letters,digits,!@#$%^&*-_=+ length=32') }}"
when: ansible_password is not defined
- name: Set ansible_password if not defined
set_fact:
ansible_password: "{{ root_password }}"
when: ansible_password is not defined and root_password is defined
- name: Create Linode instance for attack box
uri:
url: "https://api.linode.com/v4/linode/instances"
method: POST
headers:
Authorization: "Bearer {{ linode_token }}"
Content-Type: "application/json"
body_format: json
body:
label: "{{ attack_box_name }}"
type: "{{ linode_instance_type }}"
region: "{{ linode_region }}"
image: "{{ attack_box_image }}"
root_pass: "{{ ansible_password | default(root_password) }}"
authorized_keys:
- "{{ public_key_content.content | b64decode | trim }}"
booted: true
backups_enabled: false
private_ip: false
tags:
- "attack-box"
- "c2itall"
- "{{ deployment_id }}"
status_code: [200, 201]
register: linode_instance
- name: Get current timestamp
setup:
gather_subset: min
delegate_to: localhost
- name: Ensure logs directory exists
file:
path: "{{ playbook_dir }}/logs"
state: directory
mode: '0755'
delegate_to: localhost
- name: Save attack box credentials to local file
copy:
content: |
Attack Box: {{ attack_box_name }}
Deployment ID: {{ deployment_id }}
Instance IP: {{ linode_instance.json.ipv4[0] if linode_instance.json.ipv4 else 'Pending' }}
SSH Key: ~/.ssh/{{ ssh_key_name }}
Root Password: {{ ansible_password | default(root_password) }}
SSH Command: ssh -i ~/.ssh/{{ ssh_key_name }} root@{{ linode_instance.json.ipv4[0] if linode_instance.json.ipv4 else 'IP_ADDRESS' }}
Generated at: {{ ansible_date_time.iso8601 }}
dest: "{{ playbook_dir }}/logs/deployment_info_{{ deployment_id }}.txt"
mode: '0600'
when: linode_instance is succeeded
delegate_to: localhost
- name: Save instance information
set_fact:
attack_box_ip: "{{ linode_instance.json.ipv4[0] }}"
attack_box_id: "{{ linode_instance.json.id }}"
- name: Display attack box information
debug:
msg:
- "Attack Box Created Successfully!"
- "Name: {{ attack_box_name }}"
- "IP Address: {{ attack_box_ip }}"
- "Instance ID: {{ attack_box_id }}"
- "Type: {{ attack_box_type }}"
- "SSH Key: ~/.ssh/{{ ssh_key_name }}"
- name: Wait for instance to be fully booted
wait_for:
host: "{{ attack_box_ip }}"
port: 22
delay: 30
timeout: 300
ignore_errors: yes
- name: Test SSH connectivity
command: ssh -o ConnectTimeout=10 -o StrictHostKeyChecking=no -i ~/.ssh/{{ ssh_key_name }} root@{{ attack_box_ip }} echo "SSH connection successful"
register: ssh_test
retries: 5
delay: 30
until: ssh_test.rc == 0
ignore_errors: yes
- name: Create dynamic inventory for attack box configuration
add_host:
name: "{{ attack_box_ip }}"
groups: attack_boxes
ansible_host: "{{ attack_box_ip }}"
ansible_user: root
ansible_ssh_private_key_file: "~/.ssh/{{ ssh_key_name }}"
ansible_ssh_common_args: "-o StrictHostKeyChecking=no"
attack_box_type: "{{ attack_box_type }}"
deployment_id: "{{ deployment_id }}"
- name: Save deployment information
copy:
content: |
# Attack Box Deployment Information
DEPLOYMENT_ID={{ deployment_id }}
ATTACK_BOX_NAME={{ attack_box_name }}
ATTACK_BOX_IP={{ attack_box_ip }}
ATTACK_BOX_ID={{ attack_box_id }}
ATTACK_BOX_TYPE={{ attack_box_type }}
SSH_KEY_PATH=~/.ssh/{{ ssh_key_name }}
PROVIDER=linode
REGION={{ linode_region }}
INSTANCE_TYPE={{ linode_instance_type }}
DEPLOYED_DATE={{ ansible_date_time.iso8601 }}
dest: "{{ playbook_dir }}/logs/attack_box_{{ deployment_id }}.env"
- name: Configure Attack Box
hosts: attack_boxes
gather_facts: yes
become: yes
vars:
setup_workspace: "{{ setup_workspace | default(true) }}"
setup_vpn: "{{ setup_vpn | default(false) }}"
setup_tor: "{{ setup_tor | default(false) }}"
tasks:
- name: Wait for system to be ready
wait_for_connection:
delay: 30
timeout: 300
- name: Update package cache only (avoid grub-pc issues)
apt:
update_cache: yes
cache_valid_time: 3600
when: ansible_os_family == "Debian"
retries: 3
delay: 10
- name: Include attack box configuration tasks
include_tasks: "{{ playbook_dir }}/../../modules/attack-box/tasks/configure_attack_box.yml"
when: deployment_type != "quick_recon_box"
- name: Include quick recon configuration tasks
include_tasks: "{{ playbook_dir }}/../../modules/attack-box/tasks/configure_quick_recon.yml"
when: deployment_type == "quick_recon_box"
- name: Display final setup information (Full Attack Box)
debug:
msg:
- "🎯 Attack Box Configuration Complete!"
- "📦 Instance: {{ attack_box_name }}"
- "🔑 SSH Command: ssh -i ~/.ssh/a-{{ deployment_id }} root@{{ ansible_host }}"
- "🔒 Root Password: {{ ansible_password | default('Check deployment_info_' + deployment_id + '.txt') }}"
- "📁 Credentials saved to: logs/deployment_info_{{ deployment_id }}.txt"
- ""
- "🛠️ Available Commands:"
- " recon <target> - Run reconnaissance automation"
- " portscan <target> - Run port scan automation"
- " webenum <target> - Run web enumeration automation"
when: deployment_type != "quick_recon_box"
- name: Display final setup information (Quick Recon Box)
debug:
msg:
- "🎯 Quick Recon Box Configuration Complete!"
- "📦 Instance: {{ attack_box_name }}"
- "🔑 SSH Command: ssh -i ~/.ssh/qr-{{ deployment_id }} root@{{ ansible_host }}"
- "🔒 Root Password: {{ ansible_password | default('Check deployment_info_' + deployment_id + '.txt') }}"
- "📁 Credentials saved to: logs/deployment_info_{{ deployment_id }}.txt"
- ""
- "🎯 Quick Recon Commands:"
- " qr - Go to working directory"
- " toolkit - Show available tools"
- " portscan <target> - Port scan"
- " subfind <domain> - Subdomain enumeration"
- " webscan <url> - Web application scan"
- " tor-recon <target> - Anonymous reconnaissance"
when: deployment_type == "quick_recon_box"