0799bfbae8
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.
634 lines
19 KiB
YAML
634 lines
19 KiB
YAML
---
|
|
# FlokiNET full deployment playbook (C2 + Redirector)
|
|
|
|
- name: Prepare FlokiNET infrastructure deployment
|
|
hosts: localhost
|
|
gather_facts: false
|
|
connection: local
|
|
vars_files:
|
|
- vars.yaml
|
|
vars:
|
|
# Generate random shell handler port if not provided
|
|
shell_handler_port: "{{ shell_handler_port | default(4000 + 60000 | random) }}"
|
|
redirector_subdomain: "{{ redirector_subdomain | default('cdn') }}"
|
|
c2_subdomain: "{{ c2_subdomain | default('mail') }}"
|
|
|
|
tasks:
|
|
- name: Validate required FlokiNET configuration
|
|
assert:
|
|
that:
|
|
- redirector_ip is defined and redirector_ip != ""
|
|
- c2_ip is defined and c2_ip != ""
|
|
fail_msg: "FlokiNET requires both redirector_ip and c2_ip. Set these values in vars.yaml or via command line arguments."
|
|
|
|
- name: Add redirector to inventory
|
|
add_host:
|
|
name: "redirector"
|
|
groups: "redirectors"
|
|
ansible_host: "{{ redirector_ip }}"
|
|
ansible_user: "{{ ssh_user | default('root') }}"
|
|
ansible_ssh_private_key_file: "{{ ssh_key_path | replace('.pub', '') }}"
|
|
ansible_ssh_port: "{{ ssh_port | default(22) }}"
|
|
ansible_ssh_common_args: "-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null"
|
|
|
|
- name: Add C2 server to inventory
|
|
add_host:
|
|
name: "c2"
|
|
groups: "c2servers"
|
|
ansible_host: "{{ c2_ip }}"
|
|
ansible_user: "{{ ssh_user | default('root') }}"
|
|
ansible_ssh_private_key_file: "{{ ssh_key_path | replace('.pub', '') }}"
|
|
ansible_ssh_port: "{{ ssh_port | default(22) }}"
|
|
ansible_ssh_common_args: "-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null"
|
|
|
|
- name: Verify SSH connection to redirector
|
|
wait_for:
|
|
host: "{{ redirector_ip }}"
|
|
port: "{{ ssh_port | default(22) }}"
|
|
delay: 10
|
|
timeout: 60
|
|
state: started
|
|
ignore_errors: true
|
|
|
|
- name: Verify SSH connection to C2 server
|
|
wait_for:
|
|
host: "{{ c2_ip }}"
|
|
port: "{{ ssh_port | default(22) }}"
|
|
delay: 10
|
|
timeout: 60
|
|
state: started
|
|
ignore_errors: true
|
|
|
|
- name: Configure FlokiNET redirector
|
|
hosts: redirectors
|
|
become: true
|
|
gather_facts: true
|
|
vars_files:
|
|
- vars.yaml
|
|
tasks:
|
|
- name: Wait for apt to be available
|
|
apt:
|
|
update_cache: yes
|
|
register: apt_result
|
|
until: apt_result is success
|
|
retries: 5
|
|
delay: 10
|
|
|
|
- name: Set hostname
|
|
hostname:
|
|
name: "redirector"
|
|
|
|
- name: Update apt cache
|
|
apt:
|
|
update_cache: yes
|
|
|
|
- name: Upgrade all packages
|
|
apt:
|
|
upgrade: dist
|
|
|
|
- name: Install base utilities and tools via apt
|
|
apt:
|
|
name:
|
|
- git
|
|
- wget
|
|
- curl
|
|
- unzip
|
|
- python3-pip
|
|
- python3-virtualenv
|
|
- tmux
|
|
- pipx
|
|
- nmap
|
|
- tcpdump
|
|
- nginx
|
|
- certbot
|
|
- python3-certbot-nginx
|
|
- socat
|
|
- netcat-openbsd
|
|
- secure-delete
|
|
state: present
|
|
|
|
- name: Set a custom MOTD
|
|
template:
|
|
src: motd-flokinet.j2
|
|
dest: /etc/motd
|
|
owner: root
|
|
group: root
|
|
mode: '0644'
|
|
vars:
|
|
letsencrypt_email: "{{ letsencrypt_email }}"
|
|
domain: "{{ domain }}"
|
|
redirector_subdomain: "{{ redirector_subdomain }}"
|
|
|
|
- name: Create directories for operational scripts
|
|
file:
|
|
path: "{{ item }}"
|
|
state: directory
|
|
mode: '0700'
|
|
owner: root
|
|
group: root
|
|
with_items:
|
|
- /opt/c2
|
|
- /opt/shell-handler
|
|
|
|
- name: Copy clean-logs.sh script
|
|
copy:
|
|
src: "../../common/files/clean-logs.sh"
|
|
dest: /opt/c2/clean-logs.sh
|
|
mode: '0700'
|
|
owner: root
|
|
group: root
|
|
|
|
- name: Copy secure-exit.sh script
|
|
copy:
|
|
src: "../../common/files/secure-exit.sh"
|
|
dest: /opt/c2/secure-exit.sh
|
|
mode: '0700'
|
|
owner: root
|
|
group: root
|
|
|
|
- name: Copy shell handler script
|
|
copy:
|
|
src: "../../common/files/persistent-listener.sh"
|
|
dest: /opt/shell-handler/persistent-listener.sh
|
|
mode: '0700'
|
|
owner: root
|
|
group: root
|
|
|
|
- name: Configure shell handler script with C2 IP
|
|
replace:
|
|
path: /opt/shell-handler/persistent-listener.sh
|
|
regexp: 'C2_HOST="127.0.0.1"'
|
|
replace: 'C2_HOST="{{ c2_ip }}"'
|
|
|
|
- name: Configure shell handler script with listening port
|
|
replace:
|
|
path: /opt/shell-handler/persistent-listener.sh
|
|
regexp: 'LISTEN_PORT=4444'
|
|
replace: 'LISTEN_PORT={{ shell_handler_port }}'
|
|
|
|
- name: Create shell handler service
|
|
template:
|
|
src: shell-handler.service.j2
|
|
dest: /etc/systemd/system/shell-handler.service
|
|
mode: '0644'
|
|
owner: root
|
|
group: root
|
|
|
|
- name: Configure NGINX for zero-logging if enabled
|
|
template:
|
|
src: nginx.conf.j2
|
|
dest: /etc/nginx/nginx.conf
|
|
mode: '0644'
|
|
owner: root
|
|
group: root
|
|
when: zero_logs | bool
|
|
|
|
- name: Configure NGINX for C2 redirection
|
|
template:
|
|
src: redirector-site.conf.j2
|
|
dest: /etc/nginx/sites-available/default
|
|
mode: '0644'
|
|
owner: root
|
|
group: root
|
|
|
|
- name: Create legitimate-looking index.html
|
|
template:
|
|
src: redirector-index.html.j2
|
|
dest: /var/www/html/index.html
|
|
mode: '0644'
|
|
owner: www-data
|
|
group: www-data
|
|
|
|
- name: Start and enable shell handler service
|
|
systemd:
|
|
name: shell-handler
|
|
state: started
|
|
enabled: yes
|
|
daemon_reload: yes
|
|
|
|
- name: Set up cron job for log cleaning if zero-logs enabled
|
|
cron:
|
|
name: "Clean logs"
|
|
minute: "0"
|
|
hour: "*/6"
|
|
job: "/opt/c2/clean-logs.sh > /dev/null 2>&1"
|
|
when: zero_logs | bool
|
|
|
|
- name: Install Let's Encrypt certificate if domain specified
|
|
shell: |
|
|
certbot --nginx -d {{ redirector_subdomain }}.{{ domain }} --non-interactive --agree-tos -m {{ letsencrypt_email }}
|
|
args:
|
|
creates: /etc/letsencrypt/live/{{ redirector_subdomain }}.{{ domain }}/fullchain.pem
|
|
when: domain != "example.com"
|
|
|
|
- name: Restart NGINX
|
|
systemd:
|
|
name: nginx
|
|
state: restarted
|
|
|
|
- name: FlokiNET-specific security configurations
|
|
include_tasks: flokinet-security.yml
|
|
when: enable_hardened_security | default(true)
|
|
|
|
- name: Configure FlokiNET C2 server
|
|
hosts: c2servers
|
|
become: true
|
|
gather_facts: true
|
|
vars_files:
|
|
- vars.yaml
|
|
tasks:
|
|
- name: Wait for apt to be available
|
|
apt:
|
|
update_cache: yes
|
|
register: apt_result
|
|
until: apt_result is success
|
|
retries: 5
|
|
delay: 10
|
|
|
|
- name: Set hostname
|
|
hostname:
|
|
name: "c2"
|
|
|
|
- name: Update apt cache
|
|
apt:
|
|
update_cache: yes
|
|
|
|
- name: Upgrade all packages
|
|
apt:
|
|
upgrade: dist
|
|
|
|
- name: Set a custom MOTD
|
|
template:
|
|
src: motd-flokinet.j2
|
|
dest: /etc/motd
|
|
owner: root
|
|
group: root
|
|
mode: '0644'
|
|
vars:
|
|
letsencrypt_email: "{{ letsencrypt_email }}"
|
|
domain: "{{ domain }}"
|
|
c2_subdomain: "{{ c2_subdomain }}"
|
|
|
|
- name: Install base utilities and tools via apt
|
|
apt:
|
|
name:
|
|
- git
|
|
- wget
|
|
- curl
|
|
- unzip
|
|
- python3-pip
|
|
- python3-virtualenv
|
|
- tmux
|
|
- pipx
|
|
- nmap
|
|
- tcpdump
|
|
- hydra
|
|
- john
|
|
- hashcat
|
|
- sqlmap
|
|
- gobuster
|
|
- dirb
|
|
- enum4linux
|
|
- dnsenum
|
|
- seclists
|
|
- responder
|
|
- golang
|
|
- proxychains
|
|
- tor
|
|
- crackmapexec
|
|
- jq
|
|
- unzip
|
|
- postfix
|
|
- certbot
|
|
- opendkim
|
|
- opendkim-tools
|
|
- dovecot-core
|
|
- dovecot-imapd
|
|
- dovecot-pop3d
|
|
- dovecot-sieve
|
|
- dovecot-managesieved
|
|
- yq
|
|
state: present
|
|
|
|
- name: Create Tools directory
|
|
file:
|
|
path: /root/Tools
|
|
state: directory
|
|
owner: root
|
|
group: root
|
|
mode: '0755'
|
|
|
|
- name: Ensure pipx path is configured
|
|
shell: |
|
|
pipx ensurepath
|
|
args:
|
|
executable: /bin/bash
|
|
|
|
- name: Install tools via pipx
|
|
shell: |
|
|
export PATH=$PATH:/root/.local/bin
|
|
pipx ensurepath
|
|
pipx install git+https://github.com/Pennyw0rth/NetExec
|
|
pipx install git+https://github.com/blacklanternsecurity/TREVORspray
|
|
pipx install impacket
|
|
args:
|
|
executable: /bin/bash
|
|
|
|
- name: Download Kerbrute
|
|
shell: |
|
|
mkdir -p ~/Tools/Kerbrute
|
|
wget https://github.com/ropnop/kerbrute/releases/latest/download/kerbrute_linux_amd64 -O ~/Tools/Kerbrute/kerbrute
|
|
chmod +x ~/Tools/Kerbrute/kerbrute
|
|
args:
|
|
executable: /bin/bash
|
|
creates: /root/Tools/Kerbrute/kerbrute
|
|
|
|
- name: Clone SharpCollection nightly builds
|
|
git:
|
|
repo: https://github.com/Flangvik/SharpCollection.git
|
|
dest: ~/Tools/SharpCollection
|
|
version: master
|
|
ignore_errors: yes
|
|
|
|
- name: Clone PEASS-ng
|
|
git:
|
|
repo: https://github.com/carlospolop/PEASS-ng.git
|
|
dest: ~/Tools/PEASS-ng
|
|
ignore_errors: yes
|
|
|
|
- name: Clone MailSniper
|
|
git:
|
|
repo: https://github.com/dafthack/MailSniper.git
|
|
dest: ~/Tools/MailSniper
|
|
ignore_errors: yes
|
|
|
|
- name: Clone Inveigh
|
|
git:
|
|
repo: https://github.com/Kevin-Robertson/Inveigh.git
|
|
dest: ~/Tools/Inveigh
|
|
ignore_errors: yes
|
|
|
|
- name: Install Sliver C2 server
|
|
shell: |
|
|
curl https://sliver.sh/install | bash
|
|
systemctl enable sliver
|
|
systemctl start sliver
|
|
|
|
- name: Install Metasploit Framework (Nightly Build)
|
|
shell: |
|
|
curl https://raw.githubusercontent.com/rapid7/metasploit-omnibus/master/config/templates/metasploit-framework-wrappers/msfupdate.erb > ~/Tools/msfinstall
|
|
chmod 755 ~/Tools/msfinstall
|
|
~/Tools/msfinstall
|
|
args:
|
|
executable: /bin/bash
|
|
creates: /usr/bin/msfconsole
|
|
|
|
- name: Grab GoPhish
|
|
shell: |
|
|
curl -L "$(curl -s https://api.github.com/repos/gophish/gophish/releases/latest | jq -r '.assets[] | select(.browser_download_url | contains("linux-64bit.zip")) | .browser_download_url')" -o ~/Tools/gophish.zip
|
|
unzip ~/Tools/gophish.zip -d ~/Tools/gophish
|
|
rm -rf ~/Tools/gophish.zip
|
|
chmod +x ~/Tools/gophish/gophish
|
|
args:
|
|
creates: /root/Tools/gophish/gophish
|
|
|
|
- name: Deploy Gophish config.json with custom admin port
|
|
template:
|
|
src: gophish-config.j2
|
|
dest: ~/Tools/gophish/config.json
|
|
owner: root
|
|
group: root
|
|
mode: '0644'
|
|
vars:
|
|
gophish_admin_port: "{{ gophish_admin_port }}"
|
|
domain: "{{ domain }}"
|
|
|
|
- name: Configure Postfix main.cf
|
|
lineinfile:
|
|
path: /etc/postfix/main.cf
|
|
regexp: "{{ item.regexp }}"
|
|
line: "{{ item.line }}"
|
|
with_items:
|
|
- { regexp: '^myhostname', line: "myhostname = mail.{{ domain }}" }
|
|
- { regexp: '^mydomain', line: "mydomain = {{ domain }}" }
|
|
- { regexp: '^myorigin', line: "myorigin = $mydomain" }
|
|
- { regexp: '^inet_interfaces', line: "inet_interfaces = all" }
|
|
- { regexp: '^inet_protocols', line: "inet_protocols = ipv4" }
|
|
- { regexp: '^smtpd_banner', line: "smtpd_banner = $myhostname ESMTP $mail_name" }
|
|
- { regexp: '^mynetworks', line: "mynetworks = 127.0.0.0/8 [::1]/128" }
|
|
- { regexp: '^relay_domains', line: "relay_domains = $mydestination" }
|
|
- { regexp: '^smtpd_tls_cert_file', line: "smtpd_tls_cert_file = /etc/letsencrypt/live/{{ domain }}/fullchain.pem" }
|
|
- { regexp: '^smtpd_tls_key_file', line: "smtpd_tls_key_file = /etc/letsencrypt/live/{{ domain }}/privkey.pem" }
|
|
- { regexp: '^smtpd_tls_security_level', line: "smtpd_tls_security_level = encrypt" }
|
|
- { regexp: '^smtpd_tls_session_cache_database', line: "smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache" }
|
|
- { regexp: '^smtp_tls_session_cache_database', line: "smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache" }
|
|
- { regexp: '^smtpd_use_tls', line: "smtpd_use_tls = yes" }
|
|
- { regexp: '^smtpd_tls_auth_only', line: "smtpd_tls_auth_only = yes" }
|
|
- { regexp: '^milter_default_action', line: "milter_default_action = accept" }
|
|
- { regexp: '^milter_protocol', line: "milter_protocol = 6" }
|
|
- { regexp: '^smtpd_milters', line: "smtpd_milters = unix:/var/spool/postfix/opendkim/opendkim.sock" }
|
|
- { regexp: '^non_smtpd_milters', line: "non_smtpd_milters = unix:/var/spool/postfix/opendkim/opendkim.sock" }
|
|
|
|
- name: Configure OpenDKIM
|
|
lineinfile:
|
|
path: /etc/opendkim.conf
|
|
regexp: "{{ item.regexp }}"
|
|
line: "{{ item.line }}"
|
|
with_items:
|
|
- { regexp: '^Domain', line: "Domain {{ domain }}" }
|
|
- { regexp: '^KeyFile', line: "KeyFile /etc/opendkim/keys/{{ domain }}/mail.private" }
|
|
- { regexp: '^Selector', line: "Selector mail" }
|
|
- { regexp: '^Socket', line: "Socket local:/var/spool/postfix/opendkim/opendkim.sock" }
|
|
- { regexp: '^Syslog', line: "Syslog yes" }
|
|
- { regexp: '^UMask', line: "UMask 002" }
|
|
- { regexp: '^Mode', line: "Mode sv" }
|
|
|
|
- name: Create DKIM directory
|
|
file:
|
|
path: /etc/opendkim/keys/{{ domain }}
|
|
state: directory
|
|
owner: opendkim
|
|
group: opendkim
|
|
mode: 0700
|
|
|
|
- name: Generate DKIM keys
|
|
command: >
|
|
opendkim-genkey -D /etc/opendkim/keys/{{ domain }} -d {{ domain }} -s mail
|
|
args:
|
|
creates: /etc/opendkim/keys/{{ domain }}/mail.private
|
|
|
|
- name: Set permissions for DKIM keys
|
|
file:
|
|
path: /etc/opendkim/keys/{{ domain }}/mail.private
|
|
owner: opendkim
|
|
group: opendkim
|
|
mode: 0600
|
|
|
|
- name: Configure OpenDKIM TrustedHosts
|
|
copy:
|
|
content: |
|
|
127.0.0.1
|
|
::1
|
|
localhost
|
|
{{ domain }}
|
|
dest: /etc/opendkim/TrustedHosts
|
|
owner: opendkim
|
|
group: opendkim
|
|
mode: 0644
|
|
|
|
- name: Enable submission port (587) in master.cf
|
|
blockinfile:
|
|
path: /etc/postfix/master.cf
|
|
insertafter: '^#submission'
|
|
block: |
|
|
submission inet n - y - - smtpd
|
|
-o syslog_name=postfix/submission
|
|
-o smtpd_tls_security_level=encrypt
|
|
-o smtpd_sasl_auth_enable=yes
|
|
-o smtpd_recipient_restrictions=permit_sasl_authenticated,reject
|
|
-o smtpd_relay_restrictions=permit_sasl_authenticated,reject
|
|
|
|
- name: Configure Dovecot for Postfix SASL
|
|
blockinfile:
|
|
path: /etc/dovecot/conf.d/10-master.conf
|
|
insertafter: '^service auth {'
|
|
block: |
|
|
# Postfix smtp-auth
|
|
unix_listener /var/spool/postfix/private/auth {
|
|
mode = 0660
|
|
user = postfix
|
|
group = postfix
|
|
}
|
|
|
|
- name: Set Dovecot auth_mechanisms
|
|
lineinfile:
|
|
path: /etc/dovecot/conf.d/10-auth.conf
|
|
regexp: '^auth_mechanisms'
|
|
line: 'auth_mechanisms = plain login'
|
|
|
|
- name: Create Dovecot password file for SASL authentication
|
|
file:
|
|
path: /etc/dovecot/passwd
|
|
state: touch
|
|
mode: '0600'
|
|
owner: dovecot
|
|
group: dovecot
|
|
|
|
- name: Add SMTP auth user to Dovecot
|
|
lineinfile:
|
|
path: /etc/dovecot/passwd
|
|
line: "{{ smtp_auth_user }}:{{ smtp_auth_pass | password_hash('sha512_crypt') }}"
|
|
|
|
- name: Disable system auth and use passwd-file
|
|
lineinfile:
|
|
path: /etc/dovecot/conf.d/10-auth.conf
|
|
regexp: '^!include auth-system.conf.ext'
|
|
line: '#!include auth-system.conf.ext'
|
|
|
|
- name: Add auth-passwdfile configuration
|
|
blockinfile:
|
|
path: /etc/dovecot/conf.d/10-auth.conf
|
|
insertafter: '^auth_mechanisms ='
|
|
block: |
|
|
passdb {
|
|
driver = passwd-file
|
|
args = scheme=sha512_crypt /etc/dovecot/passwd
|
|
}
|
|
userdb {
|
|
driver = static
|
|
args = uid=vmail gid=vmail home=/var/vmail/%u
|
|
}
|
|
|
|
- name: Create vmail user/group
|
|
group:
|
|
name: vmail
|
|
gid: 5000
|
|
state: present
|
|
|
|
- name: Create vmail user
|
|
user:
|
|
name: vmail
|
|
uid: 5000
|
|
group: vmail
|
|
create_home: no
|
|
|
|
- name: Create directories for operational scripts
|
|
file:
|
|
path: "{{ item }}"
|
|
state: directory
|
|
mode: '0700'
|
|
owner: root
|
|
group: root
|
|
with_items:
|
|
- /opt/c2
|
|
- /opt/beacons
|
|
|
|
- name: Copy clean-logs.sh script
|
|
copy:
|
|
src: "../../common/files/clean-logs.sh"
|
|
dest: /opt/c2/clean-logs.sh
|
|
mode: '0700'
|
|
owner: root
|
|
group: root
|
|
|
|
- name: Copy secure-exit.sh script
|
|
copy:
|
|
src: "../../common/files/secure-exit.sh"
|
|
dest: /opt/c2/secure-exit.sh
|
|
mode: '0700'
|
|
owner: root
|
|
group: root
|
|
|
|
- name: Copy serve-beacons.sh script
|
|
copy:
|
|
src: "../../common/files/serve-beacons.sh"
|
|
dest: /opt/c2/serve-beacons.sh
|
|
mode: '0700'
|
|
owner: root
|
|
group: root
|
|
|
|
- name: Configure serve-beacons.sh with C2 IP
|
|
replace:
|
|
path: /opt/c2/serve-beacons.sh
|
|
regexp: 'C2_HOST=.*'
|
|
replace: 'C2_HOST="{{ c2_ip }}"'
|
|
|
|
- name: Set up cron job for log cleaning if zero-logs enabled
|
|
cron:
|
|
name: "Clean logs"
|
|
minute: "0"
|
|
hour: "*/6"
|
|
job: "/opt/c2/clean-logs.sh > /dev/null 2>&1"
|
|
when: zero_logs | bool
|
|
|
|
- name: Install Let's Encrypt certificate if domain specified
|
|
shell: |
|
|
certbot certonly --standalone -d {{ c2_subdomain }}.{{ domain }} --non-interactive --agree-tos -m {{ letsencrypt_email }}
|
|
args:
|
|
creates: /etc/letsencrypt/live/{{ c2_subdomain }}.{{ domain }}/fullchain.pem
|
|
when: domain != "example.com"
|
|
|
|
- name: Restart Postfix
|
|
service:
|
|
name: postfix
|
|
state: restarted
|
|
|
|
- name: Restart Dovecot
|
|
service:
|
|
name: dovecot
|
|
state: restarted
|
|
|
|
- name: FlokiNET-specific security configurations
|
|
include_tasks: flokinet-security.yml
|
|
when: enable_hardened_security | default(true)
|
|
|
|
- name: Print deployment summary
|
|
debug:
|
|
msg:
|
|
- "FlokiNET Deployment Complete!"
|
|
- "-------------------------------"
|
|
- "C2 Server Domain: {{ c2_subdomain }}.{{ domain }} (Update DNS A record)"
|
|
- "Redirector Domain: {{ redirector_subdomain }}.{{ domain }} (Update DNS A record)"
|
|
- "Shell Handler Port: {{ shell_handler_port }}"
|
|
- "GoPhish Admin Port: {{ gophish_admin_port }}"
|
|
when: not disable_summary | default(false) |