From 25e08aa8f4ab2aa9f794e29585100ceb3cae7af0 Mon Sep 17 00:00:00 2001 From: n0mad1k Date: Tue, 13 May 2025 21:29:42 -0400 Subject: [PATCH] fixing post deployment bugs --- AWS/c2.yml | 91 +++++++++++++++++++++++++---- AWS/redirector.yml | 107 ++++++++++++++++++++++++++++------- deploy.py | 2 +- tasks/security_hardening.yml | 48 +++++++++++++++- 4 files changed, 215 insertions(+), 33 deletions(-) diff --git a/AWS/c2.yml b/AWS/c2.yml index 14a52ad..e43f171 100644 --- a/AWS/c2.yml +++ b/AWS/c2.yml @@ -197,12 +197,10 @@ # Management access only from operator IP - proto: tcp ports: 22 - cidr_ip: "{{ operator_ip }}" - proto: tcp + cidr_ip: "{{ operator_ip }}/32" - proto: tcp ports: "{{ havoc_teamserver_port | default(40056) }}" - cidr_ip: "{{ operator_ip }}" - proto: tcp + cidr_ip: "{{ operator_ip }}/32" # Allow traffic only from redirector - proto: tcp ports: @@ -212,24 +210,37 @@ - "{{ havoc_https_port | default(443) }}" - "{{ gophish_admin_port }}" cidr_ip: "{{ redirector_ip }}/32" - proto: tcp rules_egress: - proto: -1 cidr_ip: 0.0.0.0/0 state: present register: security_group - # Generate or import SSH key for the deployment + # Generate or import SSH key for the deployment - FIXED KEY HANDLING - name: Check if deployment SSH key already exists locally stat: path: "~/.ssh/c2deploy_{{ deployment_id }}.pem" register: ssh_key_file + - name: Generate key pair if it doesn't exist + block: + - name: Create SSH key pair + command: ssh-keygen -t rsa -b 2048 -f ~/.ssh/c2deploy_{{ deployment_id }} -N "" + args: + creates: "~/.ssh/c2deploy_{{ deployment_id }}" + + - name: Rename private key to .pem format + command: mv ~/.ssh/c2deploy_{{ deployment_id }} ~/.ssh/c2deploy_{{ deployment_id }}.pem + args: + creates: "~/.ssh/c2deploy_{{ deployment_id }}.pem" + removes: "~/.ssh/c2deploy_{{ deployment_id }}" + when: not ssh_key_file.stat.exists + - name: Ensure proper permissions on SSH key file: - path: "~/.ssh/c2deploy_{{ deployment_id }}" + path: "~/.ssh/c2deploy_{{ deployment_id }}.pem" mode: '0600' - when: not ssh_key_file.stat.exists + state: file - name: Check if key pair exists in AWS amazon.aws.ec2_key_info: @@ -244,7 +255,7 @@ key_material: "{{ lookup('file', '~/.ssh/c2deploy_{{ deployment_id }}.pub') }}" region: "{{ aws_c2_region }}" state: present - when: existing_key_pair.key_pairs | length == 0 + when: existing_key_pair.keypairs | length == 0 # Launch the C2 server - use the consistent key pair name - name: Launch C2 instance @@ -431,7 +442,67 @@ - name: Include common mail server configuration tasks include_tasks: "../tasks/configure_mail.yml" - + + - name: Set up SSH access to redirector + block: + - name: Ensure /root/.ssh directory exists on C2 server + file: + path: /root/.ssh + state: directory + mode: '0700' + owner: root + group: root + + - name: Copy private SSH key to C2 server for redirector access + copy: + src: "{{ playbook_dir }}/../.ssh/c2deploy_{{ hostvars['localhost']['deployment_id'] }}.pem" + dest: "/root/.ssh/c2deploy_{{ hostvars['localhost']['deployment_id'] }}.pem" + mode: '0600' + owner: root + group: root + register: key_copy + ignore_errors: yes + + - name: If direct path fails, try home directory location + copy: + src: "~/.ssh/c2deploy_{{ hostvars['localhost']['deployment_id'] }}.pem" + dest: "/root/.ssh/c2deploy_{{ hostvars['localhost']['deployment_id'] }}.pem" + mode: '0600' + owner: root + group: root + when: key_copy is failed + + - name: Create SSH config file to use key automatically + copy: + dest: "/root/.ssh/config" + content: | + Host redirector + HostName {{ hostvars['localhost']['redirector_ip'] }} + User ubuntu + IdentityFile /root/.ssh/c2deploy_{{ hostvars['localhost']['deployment_id'] }}.pem + StrictHostKeyChecking no + UserKnownHostsFile /dev/null + mode: '0600' + owner: root + group: root + + - name: Create alias for easy redirector access + lineinfile: + path: /root/.bashrc + line: 'alias redirector="ssh -i /root/.ssh/c2deploy_{{ hostvars["localhost"]["deployment_id"] }}.pem ubuntu@{{ hostvars["localhost"]["redirector_ip"] }}"' + state: present + + - name: Test SSH from C2 to redirector + shell: | + ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i /root/.ssh/c2deploy_{{ hostvars['localhost']['deployment_id'] }}.pem ubuntu@{{ hostvars['localhost']['redirector_ip'] }} "echo 'SSH CONNECTION SUCCESSFUL FROM C2'" + register: ssh_test_result + changed_when: false + ignore_errors: yes + + - name: Display SSH test result + debug: + msg: "{{ ssh_test_result.stdout if ssh_test_result.rc == 0 else 'SSH connection failed: ' + ssh_test_result.stderr }}" + - name: Print deployment summary debug: msg: diff --git a/AWS/redirector.yml b/AWS/redirector.yml index 6e95d6c..fddda99 100644 --- a/AWS/redirector.yml +++ b/AWS/redirector.yml @@ -158,6 +158,39 @@ redirector_vpc_id: "{{ vpc_result.vpc.id }}" # Store for cleanup reference when: not (use_shared_infra | bool and infra_state_file.stat.exists | default(false)) + - name: Set default c2_ip for redirector-only deployments + set_fact: + c2_ip: "{{ operator_ip }}" + when: redirector_only | default(false) | bool and c2_ip is not defined + + - name: Load c2_ip from infrastructure state + block: + - name: Check if infrastructure state file exists + stat: + path: "infrastructure_state_{{ deployment_id }}.json" + register: infra_state_check + + - name: Load infrastructure state + include_vars: + file: "infrastructure_state_{{ deployment_id }}.json" + name: infra_state + when: infra_state_check.stat.exists + + - name: Set c2 IP from infrastructure state + set_fact: + c2_ip: "{{ infra_state.c2_ip | default(operator_ip) }}" + when: infra_state_check.stat.exists and infra_state.c2_ip is defined + + - name: Debug c2 IP + debug: + msg: "Using c2 IP: {{ c2_ip | default('undefined') }}" + when: c2_ip is undefined + + - name: Default to operator IP if c2 IP is still undefined + set_fact: + c2_ip: "{{ operator_ip }}" + when: c2_ip is undefined + - name: Create security group for redirector amazon.aws.ec2_security_group: name: "{{ redirector_name }}-sg" @@ -196,61 +229,85 @@ dest: "infrastructure_state_{{ deployment_id }}.json" when: not (use_shared_infra | bool and infra_state_file.stat.exists | default(false)) - # Generate or import SSH key for the deployment + # Generate or import SSH key for the deployment - FIXED KEY HANDLING - name: Check if deployment SSH key already exists locally stat: path: "~/.ssh/c2deploy_{{ deployment_id }}.pem" register: ssh_key_file - - - name: Ensure proper permissions on SSH key - file: - path: "~/.ssh/c2deploy_{{ deployment_id }}" - mode: '0600' + + - name: Generate SSH key pair if it doesn't exist + block: + - name: Create SSH key pair + command: ssh-keygen -t rsa -b 2048 -f ~/.ssh/c2deploy_{{ deployment_id }} -N "" + args: + creates: "~/.ssh/c2deploy_{{ deployment_id }}" + + - name: Rename private key to .pem format + command: mv ~/.ssh/c2deploy_{{ deployment_id }} ~/.ssh/c2deploy_{{ deployment_id }}.pem + args: + creates: "~/.ssh/c2deploy_{{ deployment_id }}.pem" + removes: "~/.ssh/c2deploy_{{ deployment_id }}" when: not ssh_key_file.stat.exists + - name: Ensure proper permissions on SSH key + file: + path: "~/.ssh/c2deploy_{{ deployment_id }}.pem" + mode: '0600' + state: file + + # Check if key pair exists in AWS - name: Check if key pair exists in AWS amazon.aws.ec2_key_info: - region: "{{ aws_c2_region }}" + region: "{{ aws_redirector_region }}" filters: key-name: "c2deploy_{{ deployment_id }}" register: existing_key_pair + # Import SSH key to AWS - FIXED CONDITION - name: Import SSH key to AWS amazon.aws.ec2_key: name: "c2deploy_{{ deployment_id }}" key_material: "{{ lookup('file', '~/.ssh/c2deploy_{{ deployment_id }}.pub') }}" - region: "{{ aws_c2_region }}" + region: "{{ aws_redirector_region }}" state: present - when: existing_key_pair.key_pairs | length == 0 + when: existing_key_pair.keypairs | length == 0 - # Launch the C2 server - use the consistent key pair name - - name: Launch C2 instance + # Launch the redirector instance + - name: Launch redirector instance amazon.aws.ec2_instance: - name: "{{ c2_name }}" - key_name: "c2deploy_{{ deployment_id }}" # Use the imported key - instance_type: "{{ instance_type | default('t2.medium') }}" + name: "{{ redirector_name }}" + key_name: "c2deploy_{{ deployment_id }}" + instance_type: "{{ instance_type | default('t2.micro') }}" vpc_subnet_id: "{{ subnet_id }}" security_groups: - "{{ security_group.group_id }}" image_id: "{{ ami_id }}" - region: "{{ aws_c2_region }}" + region: "{{ aws_redirector_region }}" state: present wait: yes volumes: - device_name: "/dev/xvda" ebs: - volume_size: 100 + volume_size: 20 delete_on_termination: true tags: - Name: "{{ c2_name }}" + Name: "{{ redirector_name }}" deployment_id: "{{ deployment_id }}" - register: c2_instance + register: redirector_instance - name: Set redirector_ip for later use set_fact: redirector_ip: "{{ redirector_instance.instances[0].public_ip_address }}" redirector_instance_id: "{{ redirector_instance.instances[0].instance_id }}" + - name: Display redirector instance details for debugging + debug: + msg: + - "Redirector IP: {{ redirector_ip }}" + - "Redirector Instance ID: {{ redirector_instance_id }}" + - "SSH User to use: {{ ssh_user }}" + - "SSH Key path: ~/.ssh/c2deploy_{{ deployment_id }}.pem" + - name: Wait for instance initialization pause: seconds: 120 @@ -258,7 +315,7 @@ - name: Set correct permissions on SSH key file: - path: "~/.ssh/{{ redirector_name }}.pem" + path: "~/.ssh/c2deploy_{{ deployment_id }}.pem" mode: "0600" - name: Wait for redirector SSH to be available @@ -275,10 +332,18 @@ groups: "redirectors" ansible_host: "{{ redirector_ip }}" ansible_user: "ubuntu" - ansible_ssh_private_key_file: "~/.ssh/{{ redirector_name }}.pem" + ansible_ssh_private_key_file: "~/.ssh/c2deploy_{{ deployment_id }}.pem" ansible_ssh_common_args: "-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o IdentitiesOnly=yes" ansible_python_interpreter: "/usr/bin/python3" shell_handler_port: "{{ effective_listen_port }}" + # Add necessary variables for redirector configuration + c2_ip: "{{ c2_ip }}" + domain: "{{ domain }}" + redirector_subdomain: "{{ redirector_subdomain }}" + havoc_teamserver_port: "{{ havoc_teamserver_port | default(40056) }}" + havoc_http_port: "{{ havoc_http_port | default(8080) }}" + havoc_https_port: "{{ havoc_https_port | default(443) }}" + zero_logs: "{{ zero_logs | default(true) }}" # Rest of the playbook for configuring the redirector - name: Configure redirector @@ -311,5 +376,5 @@ - "-----------------------------" - "Redirector IP: {{ ansible_host }}" - "Redirector Domain: {{ redirector_subdomain | default('cdn') }}.{{ domain }} (Update DNS A record)" - - "SSH Key: ~/.ssh/{{ hostvars['localhost']['redirector_name'] }}.pem" + - "SSH Key: ~/.ssh/c2deploy_{{ hostvars['localhost']['deployment_id'] }}.pem" when: not disable_summary | default(false) \ No newline at end of file diff --git a/deploy.py b/deploy.py index 2a88676..7982d2c 100755 --- a/deploy.py +++ b/deploy.py @@ -2289,7 +2289,7 @@ def generate_deployment_info(config, success=True): # Add correct SSH commands for each server type if not config.get('redirector_only'): - info.append(f"SSH Command for C2: ssh -t -o 'StrictHostKeyChecking=no' -o 'UserKnownHostsFile=/dev/null' -o 'IdentitiesOnly=yes' -i {ssh_key} {ssh_user}@{config.get('c2_ip', 'N/A')}") + info.append(f"SSH Command for C2: ssh -t -o 'StrictHostKeyChecking=no' -o 'UserKnownHostsFile=/dev/null' -o 'IdentitiesOnly=yes' -i {ssh_key} ubuntu@{config.get('c2_ip', 'N/A')}") if not config.get('c2_only'): info.append(f"SSH Command for Redirector: ssh -t -o 'StrictHostKeyChecking=no' -o 'UserKnownHostsFile=/dev/null' -o 'IdentitiesOnly=yes' -i {ssh_key} {ssh_user}@{config.get('redirector_ip', 'N/A')}") diff --git a/tasks/security_hardening.yml b/tasks/security_hardening.yml index a954c2e..ba73573 100644 --- a/tasks/security_hardening.yml +++ b/tasks/security_hardening.yml @@ -241,4 +241,50 @@ service: name: fail2ban state: restarted - when: fail2ban_service_stat.stat.exists and fail2ban_config_updated.changed \ No newline at end of file + when: fail2ban_service_stat.stat.exists and fail2ban_config_updated.changed + +# AWS-specific security updates - Only execute when provider is AWS +- name: Check if we're running on AWS provider + set_fact: + is_aws_provider: "{{ hostvars['localhost']['provider'] | default('') == 'aws' }}" + +- name: AWS-specific security updates + block: + - name: Get redirector security group information + block: + - name: Check if infrastructure state file exists + stat: + path: "{{ playbook_dir }}/../infrastructure_state_{{ hostvars['localhost']['deployment_id'] }}.json" + register: redirector_state_file + + - name: Load redirector state if available + include_vars: + file: "{{ playbook_dir }}/../infrastructure_state_{{ hostvars['localhost']['deployment_id'] }}.json" + name: redirector_state + when: redirector_state_file.stat.exists + + - name: Explicitly confirm we're running on AWS + debug: + msg: "Updating AWS security group for redirector to allow SSH from C2" + + - name: Update redirector security group to allow SSH from C2 + delegate_to: localhost + amazon.aws.ec2_security_group_rule: + security_group_id: "{{ redirector_state.security_group_id }}" + region: "{{ redirector_state.region | default(aws_region) }}" + rule: + proto: tcp + ports: 22 + cidr_ip: "{{ ansible_host }}/32" + state: present + when: redirector_state is defined and redirector_state.security_group_id is defined + register: sg_update + environment: + AWS_ACCESS_KEY_ID: "{{ hostvars['localhost']['aws_access_key'] }}" + AWS_SECRET_ACCESS_KEY: "{{ hostvars['localhost']['aws_secret_key'] }}" + ignore_errors: yes + + - name: Display security group update result + debug: + msg: "{{ 'Redirector security group updated to allow SSH from C2 (' + ansible_host + ')' if sg_update is success else 'Failed to update security group: ' + (sg_update.msg | default('unknown error')) }}" + when: is_aws_provider | bool \ No newline at end of file