├── tools ├── util │ ├── __init__.py │ ├── jinja_templating.py │ ├── infra_logger.py │ └── templates │ │ └── configuration.yml ├── resources │ ├── mutt-logo.png │ ├── nginx-logo.png │ ├── gophish-logo.png │ ├── openvpn-logo.png │ ├── postfix-logo.png │ ├── raspberrypi-logo.png │ ├── webcatcher-logo.png │ ├── cobaltstrike-logo.png │ └── raspberrypi-backend-logo.png └── list-tags.py ├── .gitignore ├── resources ├── .gitignore ├── red_wizard_logo.png ├── osint-infra.drawio.png ├── dropbox-infra.drawio.png ├── phishing-infra.drawio.png ├── webcatcher-infra.drawio.png └── cobaltstrike-infra.drawio.png ├── roles ├── users │ ├── tests │ │ ├── inventory │ │ └── test.yml │ ├── tasks │ │ ├── user-config.yml │ │ ├── main.yml │ │ └── quality-of-life.yml │ ├── defaults │ │ └── main.yml │ ├── vars │ │ └── main.yml │ ├── files │ │ ├── docker-info.sh │ │ └── docker-interact.sh │ ├── handlers │ │ └── main.yml │ └── meta │ │ └── main.yml ├── relay-nginx │ ├── tests │ │ ├── inventory │ │ └── test.yml │ ├── tasks │ │ ├── write-help.yml │ │ ├── get-letsencrypt.yml │ │ ├── ovpn-create-client.yml │ │ ├── os-prep.yml │ │ ├── firewall-config.yml │ │ ├── main.yml │ │ └── nginx-config.yml │ ├── defaults │ │ └── main.yml │ ├── handlers │ │ └── main.yml │ ├── vars │ │ └── main.yml │ ├── templates │ │ ├── bash_help.j2 │ │ ├── revproxy.j2 │ │ ├── readme.md.j2 │ │ └── update-rev-proxy-ip.j2 │ ├── files │ │ └── nginx.logrotate │ └── meta │ │ └── main.yml ├── relay-osint │ ├── tests │ │ ├── inventory │ │ └── test.yml │ ├── tasks │ │ ├── write-help.yml │ │ ├── ip-forwarding.yml │ │ ├── ovpn-create-client.yml │ │ ├── firewall-config.yml │ │ └── main.yml │ ├── defaults │ │ └── main.yml │ ├── handlers │ │ └── main.yml │ ├── vars │ │ └── main.yml │ ├── templates │ │ ├── bash_help.j2 │ │ └── readme.md.j2 │ └── meta │ │ └── main.yml ├── backend-common │ ├── tests │ │ ├── inventory │ │ └── test.yml │ ├── tasks │ │ ├── toolkit.yml │ │ ├── help-prep.yml │ │ ├── main.yml │ │ ├── backend-hardening.yml │ │ ├── full-system-logging.yml │ │ └── os-prep.yml │ ├── files │ │ ├── rc.local │ │ ├── bash_config │ │ └── tcpdumper.sh │ ├── defaults │ │ └── main.yml │ ├── vars │ │ └── main.yml │ ├── templates │ │ ├── create_readme.j2 │ │ ├── tcpdumper.j2 │ │ └── sshd_config.j2 │ ├── handlers │ │ └── main.yml │ └── meta │ │ └── main.yml ├── backend-dropbox │ ├── tests │ │ ├── inventory │ │ └── test.yml │ ├── tasks │ │ ├── write-help.yml │ │ ├── backend-ovpn-clients.yml │ │ └── main.yml │ ├── defaults │ │ └── main.yml │ ├── handlers │ │ └── main.yml │ ├── files │ │ ├── python3-convert-visc-to-ovpn.py │ │ ├── docker │ │ │ ├── files │ │ │ │ └── check_connections.sh │ │ │ ├── .env │ │ │ ├── docker-compose.yml │ │ │ ├── docker-entrypoint.sh │ │ │ └── Dockerfile │ │ └── server.conf │ ├── templates │ │ ├── bash_help.j2 │ │ └── readme.md.j2 │ ├── vars │ │ └── main.yml │ └── meta │ │ └── main.yml ├── backend-gophish │ ├── tests │ │ ├── inventory │ │ └── test.yml │ ├── tasks │ │ ├── write-help.yml │ │ ├── backend-ovpn-clients.yml │ │ ├── main.yml │ │ └── gophish-setup.yml │ ├── defaults │ │ └── main.yml │ ├── handlers │ │ └── main.yml │ ├── templates │ │ ├── bash_help.j2 │ │ └── readme.md.j2 │ ├── files │ │ └── gophish │ │ │ ├── files │ │ │ ├── gophish_goget.sh │ │ │ ├── gophish-config.json │ │ │ ├── gophish.service │ │ │ └── gophish_api.py │ │ │ ├── .env │ │ │ ├── docker-compose.yml │ │ │ ├── Dockerfile │ │ │ └── docker-entrypoint.sh │ ├── vars │ │ └── main.yml │ └── meta │ │ └── main.yml ├── backend-osint │ ├── tests │ │ ├── inventory │ │ └── test.yml │ ├── tasks │ │ ├── toolkit.yml │ │ ├── write-help.yml │ │ ├── backend-ovpn-clients.yml │ │ ├── main.yml │ │ ├── os-prep.yml │ │ ├── ovpn-killswitch.yml │ │ ├── rdp-setup.yml │ │ └── osint-setup.yml │ ├── defaults │ │ └── main.yml │ ├── vars │ │ └── main.yml │ ├── templates │ │ ├── bash_help.j2 │ │ ├── readme.md.j2 │ │ └── startvpn.j2 │ ├── handlers │ │ └── main.yml │ └── meta │ │ └── main.yml ├── relay-dropbox │ ├── tests │ │ ├── inventory │ │ └── test.yml │ ├── tasks │ │ ├── write-help.yml │ │ ├── ip-forwarding.yml │ │ ├── ovpn-create-client.yml │ │ ├── main.yml │ │ ├── firewall-config.yml │ │ └── ovpn-setup.yml │ ├── defaults │ │ └── main.yml │ ├── handlers │ │ └── main.yml │ ├── vars │ │ └── main.yml │ ├── templates │ │ ├── bash_help.j2 │ │ └── readme.md.j2 │ └── meta │ │ └── main.yml ├── relay-phishing │ ├── tests │ │ ├── inventory │ │ └── test.yml │ ├── tasks │ │ ├── write-help.yml │ │ ├── get-letsencrypt.yml │ │ ├── ovpn-create-client.yml │ │ ├── main.yml │ │ ├── firewall-config.yml │ │ └── os-prep.yml │ ├── defaults │ │ └── main.yml │ ├── handlers │ │ └── main.yml │ ├── templates │ │ ├── virtual.j2 │ │ ├── bash_help.j2 │ │ ├── readme.md.j2 │ │ └── dns-config.j2 │ ├── files │ │ ├── header_checks │ │ └── opendkim.conf │ ├── vars │ │ └── main.yml │ └── meta │ │ └── main.yml ├── backend-cobalt-strike │ ├── tests │ │ ├── inventory │ │ └── test.yml │ ├── files │ │ └── docker │ │ │ ├── .gitignore │ │ │ ├── 20-update-teamserver.sh │ │ │ ├── 10-start-openvpn.sh │ │ │ ├── Dockerfile │ │ │ ├── docker-entrypoint.sh │ │ │ └── docker-compose.yml │ ├── tasks │ │ ├── write-help.yml │ │ ├── backend-ovpn-clients.yml │ │ ├── main.yml │ │ └── cobalt-strike-setup.yml │ ├── defaults │ │ └── main.yml │ ├── handlers │ │ └── main.yml │ ├── templates │ │ ├── environment.j2 │ │ ├── bash_help.j2 │ │ ├── browser.profile.j2 │ │ ├── readme.md.j2 │ │ └── listener.service.cna.j2 │ ├── vars │ │ └── main.yml │ └── meta │ │ └── main.yml ├── backend-manual-phish │ ├── tests │ │ ├── inventory │ │ └── test.yml │ ├── tasks │ │ ├── write-help.yml │ │ ├── backend-ovpn-clients.yml │ │ ├── main.yml │ │ └── manual-phish-setup.yml │ ├── defaults │ │ └── main.yml │ ├── handlers │ │ └── main.yml │ ├── files │ │ └── manual-phish │ │ │ ├── files │ │ │ ├── EMAIL-Source-with-attachment.html │ │ │ ├── EMAIL-Source-with-link.html │ │ │ ├── .msmtprc │ │ │ ├── change-sender-name.sh │ │ │ ├── send-all-mails.sh │ │ │ ├── .muttrc │ │ │ ├── bash-instructions │ │ │ ├── send-attachment.sh │ │ │ └── send-link.sh │ │ │ ├── .env │ │ │ ├── docker-compose.yml │ │ │ ├── Dockerfile │ │ │ └── docker-entrypoint.sh │ ├── templates │ │ ├── bash_help.j2 │ │ └── readme.md.j2 │ ├── vars │ │ └── main.yml │ └── meta │ │ └── main.yml ├── backend-webcatcher │ ├── tests │ │ ├── inventory │ │ └── test.yml │ ├── tasks │ │ ├── write-help.yml │ │ ├── backend-ovpn-clients.yml │ │ ├── main.yml │ │ └── catcher-setup.yml │ ├── defaults │ │ └── main.yml │ ├── files │ │ └── web-catcher │ │ │ ├── .env │ │ │ ├── docker-compose.yml │ │ │ ├── Dockerfile │ │ │ ├── docker-entrypoint.sh │ │ │ └── src │ │ │ └── logger.php │ ├── templates │ │ ├── bash_help.j2 │ │ └── readme.md.j2 │ ├── vars │ │ └── main.yml │ ├── handlers │ │ └── main.yml │ └── meta │ │ └── main.yml ├── relay-cobalt-strike │ ├── tests │ │ ├── inventory │ │ └── test.yml │ ├── defaults │ │ └── main.yml │ ├── handlers │ │ └── main.yml │ ├── tasks │ │ ├── write-help.yml │ │ ├── ip-forwarding.yml │ │ ├── main.yml │ │ └── cobaltstrike-config.yml │ ├── vars │ │ └── main.yml │ ├── templates │ │ ├── bash_help.j2 │ │ ├── dns-config.j2 │ │ ├── readme.md.j2 │ │ └── update-dns-forward.j2 │ └── meta │ │ └── main.yml ├── relay-common │ ├── tasks │ │ ├── toolkit.yml │ │ ├── help-prep.yml │ │ ├── prerequisites.yml │ │ ├── user-config.yml │ │ ├── prerequisites-relay.yml │ │ ├── main.yml │ │ ├── os-prep.yml │ │ └── ovpn-setup.yml │ ├── templates │ │ ├── create_readme.j2 │ │ └── sshd_config.j2 │ ├── handlers │ │ └── main.yml │ └── vars │ │ └── main.yml └── common-tasks │ ├── ip-forwarding.yml │ ├── prerequisites.yml │ ├── toolkit.yml │ ├── write-help.yml │ ├── backend-ovpn-clients.yml │ ├── help-prep.yml │ ├── user-config.yml │ └── ovpn-create-client.yml ├── requirements.txt ├── ansible.cfg ├── LICENSE ├── step-0-first-time-setup.sh ├── step-3-deploy-infra.sh └── playbook.yml /tools/util/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | __pycache__ 2 | ansible.log 3 | -------------------------------------------------------------------------------- /resources/.gitignore: -------------------------------------------------------------------------------- 1 | *.bkp 2 | *.dtmp 3 | -------------------------------------------------------------------------------- /roles/users/tests/inventory: -------------------------------------------------------------------------------- 1 | localhost 2 | 3 | -------------------------------------------------------------------------------- /roles/relay-nginx/tests/inventory: -------------------------------------------------------------------------------- 1 | localhost 2 | 3 | -------------------------------------------------------------------------------- /roles/relay-osint/tests/inventory: -------------------------------------------------------------------------------- 1 | localhost 2 | 3 | -------------------------------------------------------------------------------- /roles/backend-common/tests/inventory: -------------------------------------------------------------------------------- 1 | localhost 2 | 3 | -------------------------------------------------------------------------------- /roles/backend-dropbox/tests/inventory: -------------------------------------------------------------------------------- 1 | localhost 2 | 3 | -------------------------------------------------------------------------------- /roles/backend-gophish/tests/inventory: -------------------------------------------------------------------------------- 1 | localhost 2 | 3 | -------------------------------------------------------------------------------- /roles/backend-osint/tests/inventory: -------------------------------------------------------------------------------- 1 | localhost 2 | 3 | -------------------------------------------------------------------------------- /roles/relay-dropbox/tests/inventory: -------------------------------------------------------------------------------- 1 | localhost 2 | 3 | -------------------------------------------------------------------------------- /roles/relay-phishing/tests/inventory: -------------------------------------------------------------------------------- 1 | localhost 2 | 3 | -------------------------------------------------------------------------------- /roles/backend-cobalt-strike/tests/inventory: -------------------------------------------------------------------------------- 1 | localhost 2 | 3 | -------------------------------------------------------------------------------- /roles/backend-manual-phish/tests/inventory: -------------------------------------------------------------------------------- 1 | localhost 2 | 3 | -------------------------------------------------------------------------------- /roles/backend-webcatcher/tests/inventory: -------------------------------------------------------------------------------- 1 | localhost 2 | 3 | -------------------------------------------------------------------------------- /roles/relay-cobalt-strike/tests/inventory: -------------------------------------------------------------------------------- 1 | localhost 2 | 3 | -------------------------------------------------------------------------------- /roles/backend-common/tasks/toolkit.yml: -------------------------------------------------------------------------------- 1 | ../../common-tasks/toolkit.yml -------------------------------------------------------------------------------- /roles/backend-osint/tasks/toolkit.yml: -------------------------------------------------------------------------------- 1 | ../../common-tasks/toolkit.yml -------------------------------------------------------------------------------- /roles/relay-common/tasks/toolkit.yml: -------------------------------------------------------------------------------- 1 | ../../common-tasks/toolkit.yml -------------------------------------------------------------------------------- /roles/users/tasks/user-config.yml: -------------------------------------------------------------------------------- 1 | ../../common-tasks/user-config.yml -------------------------------------------------------------------------------- /roles/backend-common/tasks/help-prep.yml: -------------------------------------------------------------------------------- 1 | ../../common-tasks/help-prep.yml -------------------------------------------------------------------------------- /roles/backend-osint/tasks/write-help.yml: -------------------------------------------------------------------------------- 1 | ../../common-tasks/write-help.yml -------------------------------------------------------------------------------- /roles/relay-common/tasks/help-prep.yml: -------------------------------------------------------------------------------- 1 | ../../common-tasks/help-prep.yml -------------------------------------------------------------------------------- /roles/relay-dropbox/tasks/write-help.yml: -------------------------------------------------------------------------------- 1 | ../../common-tasks/write-help.yml -------------------------------------------------------------------------------- /roles/relay-nginx/tasks/write-help.yml: -------------------------------------------------------------------------------- 1 | ../../common-tasks/write-help.yml -------------------------------------------------------------------------------- /roles/relay-osint/tasks/write-help.yml: -------------------------------------------------------------------------------- 1 | ../../common-tasks/write-help.yml -------------------------------------------------------------------------------- /roles/backend-cobalt-strike/files/docker/.gitignore: -------------------------------------------------------------------------------- 1 | cobaltstrike-dist.tgz 2 | -------------------------------------------------------------------------------- /roles/backend-dropbox/tasks/write-help.yml: -------------------------------------------------------------------------------- 1 | ../../common-tasks/write-help.yml -------------------------------------------------------------------------------- /roles/backend-gophish/tasks/write-help.yml: -------------------------------------------------------------------------------- 1 | ../../common-tasks/write-help.yml -------------------------------------------------------------------------------- /roles/backend-webcatcher/tasks/write-help.yml: -------------------------------------------------------------------------------- 1 | ../../common-tasks/write-help.yml -------------------------------------------------------------------------------- /roles/relay-common/tasks/prerequisites.yml: -------------------------------------------------------------------------------- 1 | ../../common-tasks/prerequisites.yml -------------------------------------------------------------------------------- /roles/relay-common/tasks/user-config.yml: -------------------------------------------------------------------------------- 1 | ../../common-tasks/user-config.yml -------------------------------------------------------------------------------- /roles/relay-nginx/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # defaults file for relay-nginx -------------------------------------------------------------------------------- /roles/relay-nginx/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # handlers file for relay-nginx -------------------------------------------------------------------------------- /roles/relay-osint/tasks/ip-forwarding.yml: -------------------------------------------------------------------------------- 1 | ../../common-tasks/ip-forwarding.yml -------------------------------------------------------------------------------- /roles/relay-phishing/tasks/write-help.yml: -------------------------------------------------------------------------------- 1 | ../../common-tasks/write-help.yml -------------------------------------------------------------------------------- /roles/users/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # defaults file for backend-common 3 | -------------------------------------------------------------------------------- /roles/backend-cobalt-strike/tasks/write-help.yml: -------------------------------------------------------------------------------- 1 | ../../common-tasks/write-help.yml -------------------------------------------------------------------------------- /roles/backend-common/files/rc.local: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | service tcpdumper.sh start 3 | -------------------------------------------------------------------------------- /roles/backend-manual-phish/tasks/write-help.yml: -------------------------------------------------------------------------------- 1 | ../../common-tasks/write-help.yml -------------------------------------------------------------------------------- /roles/backend-osint/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # defaults file for backend-osint 3 | -------------------------------------------------------------------------------- /roles/relay-cobalt-strike/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # defaults file for relay-nginx -------------------------------------------------------------------------------- /roles/relay-cobalt-strike/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # handlers file for relay-nginx -------------------------------------------------------------------------------- /roles/relay-cobalt-strike/tasks/write-help.yml: -------------------------------------------------------------------------------- 1 | ../../common-tasks/write-help.yml -------------------------------------------------------------------------------- /roles/relay-dropbox/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # defaults file for relay-dropbox 3 | -------------------------------------------------------------------------------- /roles/relay-dropbox/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # handlers file for relay-dropbox 3 | -------------------------------------------------------------------------------- /roles/relay-dropbox/tasks/ip-forwarding.yml: -------------------------------------------------------------------------------- 1 | ../../common-tasks/ip-forwarding.yml -------------------------------------------------------------------------------- /roles/relay-nginx/tasks/get-letsencrypt.yml: -------------------------------------------------------------------------------- 1 | ../../common-tasks/get-letsencrypt.yml -------------------------------------------------------------------------------- /roles/relay-osint/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # defaults file for relay-osint 3 | -------------------------------------------------------------------------------- /roles/relay-osint/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # handlers file for relay-osint 3 | -------------------------------------------------------------------------------- /roles/backend-common/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # defaults file for backend-common 3 | -------------------------------------------------------------------------------- /roles/backend-dropbox/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # defaults file for backend-dropbox 3 | -------------------------------------------------------------------------------- /roles/backend-dropbox/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # handlers file for backend-dropbox 3 | -------------------------------------------------------------------------------- /roles/backend-gophish/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # defaults file for backend-common 3 | -------------------------------------------------------------------------------- /roles/relay-cobalt-strike/tasks/ip-forwarding.yml: -------------------------------------------------------------------------------- 1 | ../../common-tasks/ip-forwarding.yml -------------------------------------------------------------------------------- /roles/relay-nginx/tasks/ovpn-create-client.yml: -------------------------------------------------------------------------------- 1 | ../../common-tasks/ovpn-create-client.yml -------------------------------------------------------------------------------- /roles/relay-osint/tasks/ovpn-create-client.yml: -------------------------------------------------------------------------------- 1 | ../../common-tasks/ovpn-create-client.yml -------------------------------------------------------------------------------- /roles/relay-phishing/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # defaults file for relay-phishing 3 | -------------------------------------------------------------------------------- /roles/relay-phishing/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # handlers file for relay-phishing 3 | -------------------------------------------------------------------------------- /roles/relay-phishing/tasks/get-letsencrypt.yml: -------------------------------------------------------------------------------- 1 | ../../common-tasks/get-letsencrypt.yml -------------------------------------------------------------------------------- /roles/backend-osint/tasks/backend-ovpn-clients.yml: -------------------------------------------------------------------------------- 1 | ../../common-tasks/backend-ovpn-clients.yml -------------------------------------------------------------------------------- /roles/backend-webcatcher/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # defaults file for backend-common 3 | -------------------------------------------------------------------------------- /roles/relay-dropbox/tasks/ovpn-create-client.yml: -------------------------------------------------------------------------------- 1 | ../../common-tasks/ovpn-create-client.yml -------------------------------------------------------------------------------- /roles/relay-phishing/tasks/ovpn-create-client.yml: -------------------------------------------------------------------------------- 1 | ../../common-tasks/ovpn-create-client.yml -------------------------------------------------------------------------------- /roles/backend-dropbox/tasks/backend-ovpn-clients.yml: -------------------------------------------------------------------------------- 1 | ../../common-tasks/backend-ovpn-clients.yml -------------------------------------------------------------------------------- /roles/backend-gophish/tasks/backend-ovpn-clients.yml: -------------------------------------------------------------------------------- 1 | ../../common-tasks/backend-ovpn-clients.yml -------------------------------------------------------------------------------- /roles/backend-manual-phish/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # defaults file for backend-manual-phish 3 | -------------------------------------------------------------------------------- /roles/backend-manual-phish/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # handlers file for backend-manual-phish 3 | -------------------------------------------------------------------------------- /roles/backend-webcatcher/tasks/backend-ovpn-clients.yml: -------------------------------------------------------------------------------- 1 | ../../common-tasks/backend-ovpn-clients.yml -------------------------------------------------------------------------------- /roles/users/vars/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | asciinemapath: /opt/ 3 | 4 | help_marker: "backend_common" 5 | -------------------------------------------------------------------------------- /roles/backend-cobalt-strike/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # defaults file for backend-cobalt-strike 3 | -------------------------------------------------------------------------------- /roles/backend-cobalt-strike/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # handlers file for backend-cobalt-strike 3 | -------------------------------------------------------------------------------- /roles/backend-cobalt-strike/tasks/backend-ovpn-clients.yml: -------------------------------------------------------------------------------- 1 | ../../common-tasks/backend-ovpn-clients.yml -------------------------------------------------------------------------------- /roles/backend-manual-phish/tasks/backend-ovpn-clients.yml: -------------------------------------------------------------------------------- 1 | ../../common-tasks/backend-ovpn-clients.yml -------------------------------------------------------------------------------- /roles/backend-common/vars/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | asciinemapath: /opt/ 3 | 4 | help_marker: "backend_common" 5 | -------------------------------------------------------------------------------- /roles/backend-manual-phish/files/manual-phish/files/EMAIL-Source-with-attachment.html: -------------------------------------------------------------------------------- 1 | ADD EMAIL HTML 2 | -------------------------------------------------------------------------------- /resources/red_wizard_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kr0ff/RedWizard/main/resources/red_wizard_logo.png -------------------------------------------------------------------------------- /tools/resources/mutt-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kr0ff/RedWizard/main/tools/resources/mutt-logo.png -------------------------------------------------------------------------------- /tools/resources/nginx-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kr0ff/RedWizard/main/tools/resources/nginx-logo.png -------------------------------------------------------------------------------- /resources/osint-infra.drawio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kr0ff/RedWizard/main/resources/osint-infra.drawio.png -------------------------------------------------------------------------------- /roles/backend-dropbox/files/python3-convert-visc-to-ovpn.py: -------------------------------------------------------------------------------- 1 | ../../relay-common/files/python3-convert-visc-to-ovpn.py -------------------------------------------------------------------------------- /roles/relay-nginx/tests/test.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: localhost 3 | remote_user: root 4 | roles: 5 | - relay-nginx -------------------------------------------------------------------------------- /tools/resources/gophish-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kr0ff/RedWizard/main/tools/resources/gophish-logo.png -------------------------------------------------------------------------------- /tools/resources/openvpn-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kr0ff/RedWizard/main/tools/resources/openvpn-logo.png -------------------------------------------------------------------------------- /tools/resources/postfix-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kr0ff/RedWizard/main/tools/resources/postfix-logo.png -------------------------------------------------------------------------------- /resources/dropbox-infra.drawio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kr0ff/RedWizard/main/resources/dropbox-infra.drawio.png -------------------------------------------------------------------------------- /resources/phishing-infra.drawio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kr0ff/RedWizard/main/resources/phishing-infra.drawio.png -------------------------------------------------------------------------------- /roles/relay-osint/tests/test.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: localhost 3 | remote_user: root 4 | roles: 5 | - relay-osint 6 | -------------------------------------------------------------------------------- /roles/relay-osint/vars/main.yml: -------------------------------------------------------------------------------- 1 | client_profiles: 2 | - "osint" 3 | 4 | help_marker: "relay_osint_{{ansible_host}}" 5 | -------------------------------------------------------------------------------- /roles/users/tests/test.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: localhost 3 | remote_user: root 4 | roles: 5 | - backend-common 6 | -------------------------------------------------------------------------------- /tools/resources/raspberrypi-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kr0ff/RedWizard/main/tools/resources/raspberrypi-logo.png -------------------------------------------------------------------------------- /tools/resources/webcatcher-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kr0ff/RedWizard/main/tools/resources/webcatcher-logo.png -------------------------------------------------------------------------------- /resources/webcatcher-infra.drawio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kr0ff/RedWizard/main/resources/webcatcher-infra.drawio.png -------------------------------------------------------------------------------- /roles/backend-common/tests/test.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: localhost 3 | remote_user: root 4 | roles: 5 | - backend-common 6 | -------------------------------------------------------------------------------- /roles/backend-osint/tests/test.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: localhost 3 | remote_user: root 4 | roles: 5 | - backend-osint 6 | -------------------------------------------------------------------------------- /roles/relay-cobalt-strike/tests/test.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: localhost 3 | remote_user: root 4 | roles: 5 | - relay-nginx -------------------------------------------------------------------------------- /roles/relay-dropbox/tests/test.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: localhost 3 | remote_user: root 4 | roles: 5 | - relay-dropbox 6 | -------------------------------------------------------------------------------- /roles/relay-phishing/tests/test.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: localhost 3 | remote_user: root 4 | roles: 5 | - relay-phishing 6 | -------------------------------------------------------------------------------- /roles/users/files/docker-info.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Mounts}}" --no-trunc 3 | -------------------------------------------------------------------------------- /tools/resources/cobaltstrike-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kr0ff/RedWizard/main/tools/resources/cobaltstrike-logo.png -------------------------------------------------------------------------------- /resources/cobaltstrike-infra.drawio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kr0ff/RedWizard/main/resources/cobaltstrike-infra.drawio.png -------------------------------------------------------------------------------- /roles/backend-dropbox/tests/test.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: localhost 3 | remote_user: root 4 | roles: 5 | - backend-dropbox 6 | -------------------------------------------------------------------------------- /roles/backend-gophish/tests/test.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: localhost 3 | remote_user: root 4 | roles: 5 | - backend-gophish 6 | -------------------------------------------------------------------------------- /roles/backend-webcatcher/tests/test.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: localhost 3 | remote_user: root 4 | roles: 5 | - backend-gophish 6 | -------------------------------------------------------------------------------- /roles/backend-dropbox/files/docker/files/check_connections.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | cat etc/openvpn/server/openvpn-status.log | grep ,Dropbox 3 | -------------------------------------------------------------------------------- /roles/relay-phishing/templates/virtual.j2: -------------------------------------------------------------------------------- 1 | # Forward addresses for return mails: 2 | @{{ domain_name }} {{phishing_reply_forwards}} 3 | -------------------------------------------------------------------------------- /roles/backend-cobalt-strike/tests/test.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: localhost 3 | remote_user: root 4 | roles: 5 | - backend-cobalt-strike 6 | -------------------------------------------------------------------------------- /roles/backend-manual-phish/tests/test.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: localhost 3 | remote_user: root 4 | roles: 5 | - backend-manual-phish 6 | -------------------------------------------------------------------------------- /tools/resources/raspberrypi-backend-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kr0ff/RedWizard/main/tools/resources/raspberrypi-backend-logo.png -------------------------------------------------------------------------------- /roles/relay-dropbox/vars/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # vars file for relay-dropbox 3 | # 4 | client_profiles: 5 | - "dropbox" 6 | 7 | help_marker: "relay_dropbox" 8 | -------------------------------------------------------------------------------- /roles/backend-cobalt-strike/files/docker/20-update-teamserver.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | cd /opt/cobaltstrike/ 4 | ./update <<< ${LICENSE} 5 | 6 | exit 0 7 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | click 2 | requests 3 | jinja2 4 | pyyaml 5 | validators 6 | IPy 7 | ansible 8 | diagrams 9 | ansible-vault 10 | coloredlogs 11 | colorama 12 | -------------------------------------------------------------------------------- /roles/backend-dropbox/files/docker/.env: -------------------------------------------------------------------------------- 1 | # Local gophish port 2 | VPNPORT=1194 3 | 4 | # Other Info 5 | RELAY_HOST=127.0.0.1 6 | VPN_CONFIG=dropbox.ovpn 7 | CODENAME=DeltaQuadrant 8 | -------------------------------------------------------------------------------- /roles/relay-phishing/files/header_checks: -------------------------------------------------------------------------------- 1 | /^Received:.*/ IGNORE 2 | /^X-Originating-IP:/ IGNORE 3 | /^X-Mailer:/ IGNORE 4 | /^Mime-Version:/ IGNORE 5 | 6 | -------------------------------------------------------------------------------- /roles/relay-nginx/vars/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # vars file for relay-nginx 3 | nginx_relay_config_name: revproxy 4 | 5 | help_marker: "relay_nginx_{{domain_name}}_{{relay_to_client_profile}}" 6 | 7 | -------------------------------------------------------------------------------- /roles/relay-cobalt-strike/vars/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # vars file for relay-nginx 3 | nginx_relay_config_name: revproxy 4 | 5 | help_marker: "relay_cobaltstrike_{{domain_name}}_{{relay_to_client_profile}}" 6 | 7 | -------------------------------------------------------------------------------- /roles/users/tasks/main.yml: -------------------------------------------------------------------------------- 1 | - name: "***** USERS: Configure the users *****" 2 | include_tasks: user-config.yml 3 | 4 | - name: "***** USERS: Quality of life *****" 5 | include_tasks: quality-of-life.yml 6 | 7 | -------------------------------------------------------------------------------- /roles/relay-nginx/tasks/os-prep.yml: -------------------------------------------------------------------------------- 1 | - name: "RELAY - NGINX: Install NGINX and Certbot from apt" 2 | become: yes 3 | ansible.builtin.apt: 4 | name: 5 | - nginx 6 | - certbot 7 | state: present 8 | -------------------------------------------------------------------------------- /roles/backend-webcatcher/files/web-catcher/.env: -------------------------------------------------------------------------------- 1 | # Directory to intall gophish (no trailing slash!!!) 2 | PHPDIR=/var/www/ 3 | 4 | # Other Info 5 | RELAY_HOST=127.0.0.1 6 | VPN_CONFIG=web-catcher.ovpn 7 | CODENAME=DeltaQuadrant 8 | -------------------------------------------------------------------------------- /roles/relay-common/templates/create_readme.j2: -------------------------------------------------------------------------------- 1 | 2 | README for the RT relay machine {{ inventory_hostname }} on {{ ansible_host }}. 3 | Below you will find the instructions for the installed components 4 | 5 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 6 | -------------------------------------------------------------------------------- /roles/backend-common/templates/create_readme.j2: -------------------------------------------------------------------------------- 1 | 2 | README for the RT BACKEND machine {{ inventory_hostname }} on {{ ansible_host }}. 3 | Below you will find the instructions for the installed components 4 | 5 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 6 | -------------------------------------------------------------------------------- /roles/backend-manual-phish/files/manual-phish/files/EMAIL-Source-with-link.html: -------------------------------------------------------------------------------- 1 | ADD HTML OF EMAIL 2 | Click here to download the article 3 | Include this link somewhere in your email source 4 | -------------------------------------------------------------------------------- /roles/backend-manual-phish/files/manual-phish/files/.msmtprc: -------------------------------------------------------------------------------- 1 | defaults 2 | logfile ~/.msmtp.log 3 | 4 | account mutt 5 | host 10.8.0.1 6 | tls off 7 | tls_nocertcheck 8 | port 25 9 | from SEND_NAME@PHISH_DOMAIN 10 | 11 | account default : mutt 12 | -------------------------------------------------------------------------------- /roles/relay-common/tasks/prerequisites-relay.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: "Checking whether the set domain name resolves to the ansible host" 3 | ansible.builtin.assert: 4 | that: ansible_host == lookup('dig', domain_name) 5 | when: domain_name is defined 6 | -------------------------------------------------------------------------------- /roles/backend-cobalt-strike/templates/environment.j2: -------------------------------------------------------------------------------- 1 | TEAMSERVER_PASSWORD={{ cobaltstrike_password }} 2 | RELAY_HOST={{ relay_host_ip }} 3 | VPN_CONFIG=cobaltstrike.ovpn 4 | MALLEABLE_PROFILE={{ malleable_profile }} 5 | CODE_NAME={{ codename }} 6 | CS_LICENSE={{ cs_license }} 7 | -------------------------------------------------------------------------------- /roles/relay-osint/tasks/firewall-config.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: "Iptables: Allow all outbound traffic" 3 | become: yes 4 | ansible.builtin.iptables: 5 | chain: OUTPUT 6 | out_interface: "{{ ansible_default_ipv4.interface }}" 7 | jump: ACCEPT 8 | protocol: tcp 9 | 10 | -------------------------------------------------------------------------------- /roles/backend-cobalt-strike/vars/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | openvpn_client_profile_path: "{{ toolkit_directory }}/client_profiles/" 3 | cs_docker_path: "{{ toolkit_directory }}/cobaltstrike" 4 | cs_ovpn_pattern: "cobaltstrike@{{ relay_host_ip }}.ovpn" 5 | 6 | help_marker: "backend_cobaltstrike_{{relay_host_ip}}" 7 | -------------------------------------------------------------------------------- /roles/relay-dropbox/templates/bash_help.j2: -------------------------------------------------------------------------------- 1 | GREEN='\033[0;32m' 2 | NC='\033[0m' # No Color 3 | echo -e "${GREEN}- Dropbox Relay setup${NC}" 4 | echo ' - Relays incoming openvpn connections for the dropbox on port {{ exposed_port }}' 5 | echo ' - This relay does not interact with this traffic, just forwards it.' 6 | -------------------------------------------------------------------------------- /roles/users/files/docker-interact.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [[ $# -eq 0 ]] ; then 4 | echo 5 | echo 'Usage: ./docker-interact.sh ' 6 | echo 'run ./docker-info.sh or "sudo docker ps" for all container names' 7 | echo 8 | exit 9 | fi 10 | 11 | docker exec -it $1 /bin/bash 12 | -------------------------------------------------------------------------------- /roles/backend-webcatcher/templates/bash_help.j2: -------------------------------------------------------------------------------- 1 | GREEN='\033[0;32m' 2 | NC='\033[0m' # No Color 3 | echo -e "${GREEN}- Web Catcher for {{ relay_host }}${NC}" 4 | echo ' - Requests are received via {{ relay_host }} on {{ relay_host_ip }}' 5 | echo ' - You can find the logs in /TOOLKIT/web-catcher/docker/{{ relay_host }}/logs/' 6 | -------------------------------------------------------------------------------- /roles/backend-webcatcher/vars/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | openvpn_client_profile_path: "{{ toolkit_directory }}/client_profiles/" 3 | web_catcher_docker_path: "{{ toolkit_directory }}/web-catcher/docker/" 4 | web_catcher_ovpn_pattern: "web-catcher@{{ relay_host_ip }}.ovpn" 5 | 6 | help_marker: "backend_webcatcher_{{ relay_host_ip }}" 7 | 8 | -------------------------------------------------------------------------------- /roles/relay-nginx/tasks/firewall-config.yml: -------------------------------------------------------------------------------- 1 | - name: "RELAY - NGINX: Allow 443 for webserver" 2 | become: yes 3 | ansible.builtin.iptables: 4 | chain: INPUT 5 | destination_port: "443" 6 | jump: ACCEPT 7 | protocol: tcp 8 | state: present 9 | changed_when: false # Done always, so no change notification 10 | -------------------------------------------------------------------------------- /roles/relay-osint/templates/bash_help.j2: -------------------------------------------------------------------------------- 1 | GREEN='\033[0;32m' 2 | NC='\033[0m' # No Color 3 | echo -e "${GREEN}- OSINT Relay on {{ ansible_host }}${NC}" 4 | echo ' Outgoing web traffic is enabeled. Please make sure your OSINT C2 sends all traffic through this relay' 5 | echo ' Please make sure your OSINT C2 sends all traffic through this relay' 6 | -------------------------------------------------------------------------------- /roles/backend-gophish/tasks/main.yml: -------------------------------------------------------------------------------- 1 | - name: "***** BACKEND GOPHISH: Set up client profiles *****" 2 | include_tasks: backend-ovpn-clients.yml 3 | 4 | - name: "***** BACKEND GOPHISH: Set up GoPhish *****" 5 | include_tasks: gophish-setup.yml 6 | 7 | - name: "***** BACKEND GOPHISH: Write Help information *****" 8 | include_tasks: write-help.yml 9 | -------------------------------------------------------------------------------- /roles/users/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: restart sshd 3 | become: yes 4 | service: 5 | name: sshd 6 | state: restarted 7 | 8 | - name: saveiptables 9 | become: yes 10 | shell: iptables-save > /etc/iptables/rules.v4 11 | 12 | - name: saveip6tables 13 | become: yes 14 | shell: ip6tables-save > /etc/iptables/rules.v6 15 | -------------------------------------------------------------------------------- /roles/backend-manual-phish/files/manual-phish/.env: -------------------------------------------------------------------------------- 1 | # SMTP settings (will be automatically set by ansible) 2 | SMTP_HOST=10.8.0.1 #Within the VPN connection 3 | REAL_NAME="SENDER_FULL_NAME" 4 | USER_NAME="SEND_NAME" 5 | DOMAIN_NAME="PHISH_DOMAIN" 6 | VPN_CONFIG=manual-phish.ovpn 7 | RELAY_HOST=127.0.0.1 8 | CODENAME=DeltaQuadrant 9 | 10 | -------------------------------------------------------------------------------- /roles/relay-common/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: restart sshd 3 | become: yes 4 | service: 5 | name: sshd 6 | state: restarted 7 | 8 | - name: saveiptables 9 | become: yes 10 | shell: iptables-save > /etc/iptables/rules.v4 11 | 12 | - name: saveip6tables 13 | become: yes 14 | shell: ip6tables-save > /etc/iptables/rules.v6 15 | -------------------------------------------------------------------------------- /roles/backend-common/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: restart sshd 3 | become: yes 4 | service: 5 | name: sshd 6 | state: restarted 7 | 8 | - name: saveiptables 9 | become: yes 10 | shell: iptables-save > /etc/iptables/rules.v4 11 | 12 | - name: saveip6tables 13 | become: yes 14 | shell: ip6tables-save > /etc/iptables/rules.v6 15 | -------------------------------------------------------------------------------- /roles/backend-dropbox/tasks/main.yml: -------------------------------------------------------------------------------- 1 | - name: "***** BACKEND DROPBOX: Set up client profiles *****" 2 | include_tasks: backend-ovpn-clients.yml 3 | 4 | - name: "***** BACKEND DROPBOX: Set up Dropbox backend *****" 5 | include_tasks: dropbox-setup.yml 6 | 7 | - name: "***** BACKEND DROPBOX: Write Help information *****" 8 | include_tasks: write-help.yml 9 | -------------------------------------------------------------------------------- /roles/backend-gophish/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: restart sshd 3 | become: yes 4 | service: 5 | name: sshd 6 | state: restarted 7 | 8 | - name: saveiptables 9 | become: yes 10 | shell: iptables-save > /etc/iptables/rules.v4 11 | 12 | - name: saveip6tables 13 | become: yes 14 | shell: ip6tables-save > /etc/iptables/rules.v6 15 | -------------------------------------------------------------------------------- /roles/backend-osint/vars/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | openvpn_client_profile_path: "{{ toolkit_directory }}/client_profiles/" 3 | osint_ovpn_pattern: "osint@{{ relay_host_ip }}.ovpn" 4 | 5 | rdp_desktop_packages: 6 | - xfce4 7 | - xfce4-goodies 8 | - xorg 9 | - dbus-x11 10 | - x11-xserver-utils 11 | - firefox 12 | 13 | help_marker: "backend_osint" 14 | -------------------------------------------------------------------------------- /roles/backend-webcatcher/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: restart sshd 3 | become: yes 4 | service: 5 | name: sshd 6 | state: restarted 7 | 8 | - name: saveiptables 9 | become: yes 10 | shell: iptables-save > /etc/iptables/rules.v4 11 | 12 | - name: saveip6tables 13 | become: yes 14 | shell: ip6tables-save > /etc/iptables/rules.v6 15 | -------------------------------------------------------------------------------- /roles/backend-manual-phish/tasks/main.yml: -------------------------------------------------------------------------------- 1 | - name: "***** BACKEND MANUAL PHISH: Set up client profiles *****" 2 | include_tasks: backend-ovpn-clients.yml 3 | 4 | - name: "***** BACKEND MANUAL PHISH: Set up Phishing Docker *****" 5 | include_tasks: manual-phish-setup.yml 6 | 7 | - name: "***** BACKEND MANUAL PHISH: Write Help *****" 8 | include_tasks: write-help.yml 9 | -------------------------------------------------------------------------------- /roles/backend-webcatcher/tasks/main.yml: -------------------------------------------------------------------------------- 1 | - name: "***** BACKEND WEB-CATCHER: Set up client profiles *****" 2 | include_tasks: backend-ovpn-clients.yml 3 | 4 | - name: "***** BACKEND WEB-CATCHER: Set up WebCatcher *****" 5 | include_tasks: catcher-setup.yml 6 | 7 | - name: "***** BACKEND WEB-CATCHER: Write Help information *****" 8 | include_tasks: write-help.yml 9 | -------------------------------------------------------------------------------- /roles/common-tasks/ip-forwarding.yml: -------------------------------------------------------------------------------- 1 | # Set ip forwarding on in /proc and in the sysctl file and reload if necessary 2 | - name: "Routing: Enable IP-frowarding for relay functionality" 3 | become: yes 4 | ansible.builtin.sysctl: 5 | name: net.ipv4.ip_forward 6 | value: '1' 7 | sysctl_set: yes 8 | state: present 9 | reload: yes 10 | 11 | 12 | -------------------------------------------------------------------------------- /roles/relay-cobalt-strike/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: "***** RELAY - Cobaltstrike: Enable IP Forwarding *****" 3 | include_tasks: ip-forwarding.yml 4 | 5 | - name: "***** RELAY - Cobaltstrike: Configure Forwards *****" 6 | include_tasks: cobaltstrike-config.yml 7 | 8 | - name: "***** RELAY - Cobaltstrike: Write help text *****" 9 | include_tasks: write-help.yml 10 | -------------------------------------------------------------------------------- /roles/backend-manual-phish/templates/bash_help.j2: -------------------------------------------------------------------------------- 1 | GREEN='\033[0;32m' 2 | NC='\033[0m' # No Color 3 | echo -e "${GREEN}- Manual Phishing Docker for {{ domain_name }}${NC}" 4 | echo ' - Email is sent via {{ relay_host }} on {{ relay_host_ip }}' 5 | echo ' - Use /TOOLKIT/docker-info.sh and /TOOLKIT/docker-interact.sh to' 6 | echo ' interact with this container and sent out your phish' 7 | -------------------------------------------------------------------------------- /roles/relay-common/vars/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | download_directory: "{{ toolkit_directory }}" 3 | 4 | # sysctl config to disallow IPv6 5 | sysctl_config: 6 | net.ipv6.conf.all.disable_ipv6: 1 7 | net.ipv6.conf.default.disable_ipv6: 1 8 | net.ipv6.conf.lo.disable_ipv6: 1 9 | net.ipv6.conf.ens3.disable_ipv6: 1 10 | net.ipv6.conf.tun0.disable_ipv6: 1 11 | 12 | help_marker: "relay_common" 13 | -------------------------------------------------------------------------------- /roles/backend-cobalt-strike/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: "***** BACKEND COBALT STRIKE: Set up client profiles *****" 3 | include_tasks: backend-ovpn-clients.yml 4 | 5 | - name: "***** BACKEND COBALT STRIKE: Set up Cobalt Strike *****" 6 | include_tasks: cobalt-strike-setup.yml 7 | 8 | - name: "***** BACKEND COBALT STRIKE: Write Help information *****" 9 | include_tasks: write-help.yml 10 | -------------------------------------------------------------------------------- /roles/backend-cobalt-strike/templates/bash_help.j2: -------------------------------------------------------------------------------- 1 | GREEN='\033[0;32m' 2 | NC='\033[0m' # No Color 3 | echo -e "${GREEN}- Cobalt Strike Docker for {{ identification }}${NC}" 4 | echo ' - Shells are received via {{ relay_host }} on {{ relay_host_ip }}' 5 | echo ' - Use "ssh -L 50050:localhost:50050 {{ansible_host}}" to set up a tunnel' 6 | echo ' Then connect your local cobaltstrike to localhost port 50050' 7 | -------------------------------------------------------------------------------- /roles/relay-phishing/templates/bash_help.j2: -------------------------------------------------------------------------------- 1 | GREEN='\033[0;32m' 2 | NC='\033[0m' # No Color 3 | echo -e "${GREEN}- Postfix / Dovecot SMTP setup for {{ domain_name }}${NC}" 4 | echo -e " - Configure your DNS settings according to ${GREEN}{{ toolkit_directory }}/dns_config.txt${NC}" 5 | echo ' - Enable outgoing mail ports in your VPS provider' 6 | echo ' - Set reverse DNS in your VPS control panel to {{ domain_name }}' 7 | -------------------------------------------------------------------------------- /roles/relay-dropbox/templates/readme.md.j2: -------------------------------------------------------------------------------- 1 | '------------------------------------------------------' 2 | 3 | 'This is the README for the dropbox forwarder' 4 | 5 | - Dropbox Relay setup 6 | - Relays incoming openvpn connections for the dropbox on port {{ exposed_port }} 7 | - This relay does not interact with this traffic, just forwards it. 8 | 9 | '------------------------------------------------------' 10 | 11 | -------------------------------------------------------------------------------- /roles/backend-osint/templates/bash_help.j2: -------------------------------------------------------------------------------- 1 | GREEN='\033[0;32m' 2 | NC='\033[0m' # No Color 3 | echo -e "${GREEN}- OSINT Server with relay {{ relay_host_ip }}${NC}" 4 | echo ' - This server hosts an always-on VPN connection to {{ relay_host_ip }}$' 5 | echo ' - There is a killswitch that prevents you from accessing the internet if VPN drops' 6 | echo ' - RDP is enabeled on this system so you can use the browser and desktop tools' 7 | -------------------------------------------------------------------------------- /roles/common-tasks/prerequisites.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: "Checking server OS version" 3 | ansible.builtin.assert: 4 | that: 5 | - ansible_distribution == 'Ubuntu' 6 | - ansible_distribution_version is version('20', 'gt') # todo change to eq 7 | fail_msg: "Invalid OS distribution or version" 8 | 9 | - name: "Checking Internet connectivity" 10 | ansible.builtin.uri: 11 | url: https://www.google.com 12 | 13 | -------------------------------------------------------------------------------- /roles/common-tasks/toolkit.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: "User management: Ensure group 'rtspec' exists" 3 | become: yes 4 | ansible.builtin.group: 5 | name: rtspec 6 | state: present 7 | 8 | - name: "Create the RT Toolkit directory in {{ toolkit_directory }}" 9 | become: yes 10 | ansible.builtin.file: 11 | path: "{{ toolkit_directory }}" 12 | owner: root 13 | group: rtspec 14 | mode: 0773 15 | state: directory 16 | 17 | -------------------------------------------------------------------------------- /roles/backend-gophish/templates/bash_help.j2: -------------------------------------------------------------------------------- 1 | GREEN='\033[0;32m' 2 | NC='\033[0m' # No Color 3 | echo -e "${GREEN}- GoPhish Phishing Docker for {{ domain_name }}${NC}" 4 | echo ' - Email is sent via {{ relay_host }} on {{ relay_host_ip }}' 5 | echo ' - Use "ssh -L {{gophish_admin_port}}:localhost:{{gophish_admin_port}} {{ansible_host}}" to set up a tunnel' 6 | echo ' - Interact with this instance via your browser with http://localhost:{{gophish_admin_port}}' 7 | -------------------------------------------------------------------------------- /roles/relay-osint/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: "***** OSINT RELAY: Generate Client profiles *****" 3 | include_tasks: ovpn-create-client.yml 4 | 5 | - name: "***** OSINT RELAY: Further harden the server *****" 6 | include_tasks: firewall-config.yml 7 | 8 | - name: "***** OSINT RELAY: Enable ip forwarding *****" 9 | include_tasks: ip-forwarding.yml 10 | 11 | - name: "***** OSINT RELAY: Write help text *****" 12 | include_tasks: write-help.yml 13 | -------------------------------------------------------------------------------- /roles/backend-webcatcher/files/web-catcher/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | services: 3 | webcatcher: 4 | privileged: true 5 | hostname: web-catcher 6 | build: 7 | context: . 8 | args: 9 | - VPN=${VPN_CONFIG} 10 | container_name: web-catcher-${RELAY_HOST} 11 | environment: 12 | - VPN=${VPN_CONFIG} 13 | - RELAY_HOST=${RELAY_HOST} 14 | - CODENAME=${CODENAME} 15 | volumes: 16 | - './logs:/var/log' 17 | -------------------------------------------------------------------------------- /roles/backend-dropbox/files/docker/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | services: 3 | dropbox: 4 | privileged: true 5 | build: 6 | context: . 7 | args: 8 | - VPN=${VPN_CONFIG} 9 | - VPNPORT=${VPNPORT} 10 | container_name: dropbox-backend 11 | environment: 12 | - VPN=${VPN_CONFIG} 13 | - RELAY_HOST=${RELAY_HOST} 14 | - CODENAME=${CODENAME} 15 | volumes: 16 | - './logs:/var/log' 17 | ports: 18 | - '${VPNPORT}:1194' 19 | 20 | -------------------------------------------------------------------------------- /roles/backend-common/templates/tcpdumper.j2: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=start tcpdumper service 3 | After=network.target 4 | 5 | [Service] 6 | Environment="TCPDUMP_FORMAT=%%Y-%%m-%%d__%%H:%%M:%%S" 7 | ExecStart=/sbin/tcpdump -i {{ ansible_default_ipv4.interface }} -Z root -G 1800 -s 65535 -w '/var/log/tcpdump/tcpdump_${TCPDUMP_FORMAT}.pcap' -C 500 port not 22 and port not 1194 and not arp 8 | ExecStop=/bin/kill -s TERM $MAINPID 9 | RemainAfterExit=yes 10 | 11 | [Install] 12 | WantedBy=multi-user.target 13 | 14 | 15 | -------------------------------------------------------------------------------- /roles/backend-osint/templates/readme.md.j2: -------------------------------------------------------------------------------- 1 | ===== Component: OSINT Server with relay {{ relay_host_ip }} ===== 2 | 3 | ----- Running on server: {{ ansible_host }} 4 | 5 | ----- Relay Server: {{ relay_host_ip }} 6 | 7 | ----- Exposed ports: ssh and rdp 8 | 9 | ----- Usage: 10 | 11 | This server hosts an always-on VPN connection to {{ relay_host_ip }}$ 12 | There is a killswitch that prevents you from accessing the internet if VPN drops 13 | RDP is enabeled on this system so you can use the browser and desktop tools 14 | 15 | -------------------------------------------------------------------------------- /roles/backend-common/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: "***** BACKEND: Preparing the operating system *****" 3 | include_tasks: os-prep.yml 4 | 5 | - name: "***** BACKEND: Harden the server *****" 6 | include_tasks: backend-hardening.yml 7 | 8 | - name: "***** BACKEND: Set up toolkit *****" 9 | include_tasks: toolkit.yml 10 | 11 | - name: "***** BACKEND: Set up complete audit logging *****" 12 | include_tasks: full-system-logging.yml 13 | 14 | - name: "***** BACKEND: Set up the help files *****" 15 | include_tasks: help-prep.yml 16 | -------------------------------------------------------------------------------- /roles/relay-cobalt-strike/templates/bash_help.j2: -------------------------------------------------------------------------------- 1 | GREEN='\033[0;32m' 2 | CYAN='\033[0;96m' 3 | NC='\033[0m' # No Color 4 | echo -e "${GREEN}- DNS Forwarder for CobaltStrike for {{ domain_name }}${NC}" 5 | echo -e " DNS Traffic forward to incoming vpn designated ${CYAN}'{{ relay_to_client_profile }}'${NC}" 6 | echo -e "${CYAN} Make sure the following DNS Settings are configured for this domain:${NC}" 7 | echo -e " - {{ dns_beacon_subdomain }} 5 min A {{ ansible_host }}" 8 | echo -e " - {{ dns_beacon_subdomain }} 5 min NS {{ domain_name }}" 9 | -------------------------------------------------------------------------------- /roles/backend-dropbox/files/server.conf: -------------------------------------------------------------------------------- 1 | mode server 2 | proto udp 3 | ifconfig-pool-persist ipp.txt 4 | keepalive 10 120 5 | user nobody 6 | group nogroup 7 | persist-key 8 | persist-tun 9 | status openvpn-status.log 10 | verb 3 11 | mute 10 12 | ca ca.crt 13 | cert server.crt 14 | key server.key 15 | dh dh.pem 16 | port 1194 17 | dev tun1 18 | topology subnet 19 | explicit-exit-notify 1 20 | push "topology subnet" 21 | ifconfig 198.51.100.0 255.255.255.0 22 | ifconfig-pool 198.51.100.100 198.51.100.200 255.255.255.0 23 | tls-server 24 | tls-auth ta.key 0 25 | -------------------------------------------------------------------------------- /roles/backend-dropbox/templates/bash_help.j2: -------------------------------------------------------------------------------- 1 | GREEN='\033[0;32m' 2 | NC='\033[0m' # No Color 3 | echo -e "${GREEN}- Dropbox Docker${NC}" 4 | echo -e " - Use TOOLKIT/docker-info.sh to find the running container" 5 | echo -e " - Use TOOLKIT/docker-interact.sh to interact with this one" 6 | echo -e " - Code for hardware implants that connect to this docker are" 7 | echo -e " not yet supplied with Red Wizard" 8 | echo -e " - But you can find key material for your own in your" 9 | echo -e " Exports_autogenerated directory on your deployment machine" 10 | 11 | -------------------------------------------------------------------------------- /roles/backend-gophish/files/gophish/files/gophish_goget.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | GOPHISH_ROOT="/opt/gophish" 4 | 5 | rm -rf "${GOPHISH_ROOT}" >/dev/null 2>&1 6 | 7 | git clone https://github.com/gophish/gophish "${GOPHISH_ROOT}" 8 | cd "${GOPHISH_ROOT}" 9 | 10 | # Additional OPSEC patches may be applied here 11 | # git patch /tmp/opsec.patch 12 | 13 | wget -q -c "https://golang.org/dl/go1.17.7.linux-amd64.tar.gz" 14 | rm -rf /usr/local/go && tar -C /usr/local -xzf go1.17.7.linux-amd64.tar.gz 15 | 16 | export PATH=$PATH:/usr/local/go/bin 17 | go get -v && go build -v 18 | -------------------------------------------------------------------------------- /roles/relay-osint/templates/readme.md.j2: -------------------------------------------------------------------------------- 1 | '------------------------------------------------------' 2 | This is the README for the OSINT relay setup for {{ ansible_host }} 3 | 4 | Outgoing web traffic is enabeled. Please make sure your OSINT C2 sends all traffic through this relay 5 | Please make sure your OSINT C2 sends all traffic through this relay 6 | 7 | Not too much special going on here, this functionality is basically ensuring that 8 | traffic coming from an OSINT C2 reaches the internet. 9 | 10 | '------------------------------------------------------' 11 | 12 | -------------------------------------------------------------------------------- /roles/relay-nginx/templates/bash_help.j2: -------------------------------------------------------------------------------- 1 | GREEN='\033[0;32m' 2 | CYAN='\033[0;96m' 3 | NC='\033[0m' # No Color 4 | echo -e "${GREEN}- Reverse Nginx server for {{ domain_name }}${NC}" 5 | echo -e " Traffic forward to incoming vpn designated ${CYAN}'{{ relay_to_client_profile }}'${NC}" 6 | echo ' Secret Strings that will be forwarded:' 7 | {% for string in secret_strings %} 8 | echo ' - https://{{ domain_name }}/{{ string.string }}' 9 | echo ' Forwarded to: {{ string.connection_method }}://{{ string.forward_path }}' 10 | {% endfor %} 11 | -------------------------------------------------------------------------------- /roles/relay-dropbox/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: "***** DROPBOX RELAY: Generate Client profiles *****" 3 | include_tasks: ovpn-create-client.yml 4 | 5 | - name: "***** DROPBOX RELAY: Further harden the server *****" 6 | include_tasks: firewall-config.yml 7 | 8 | - name: "***** DROPBOX RELAY: Enable ip forwarding *****" 9 | include_tasks: ip-forwarding.yml 10 | 11 | - name: "***** DROPBOX RELAY: Set Static IP for dropboc docker *****" 12 | include_tasks: ovpn-setup.yml 13 | 14 | - name: "***** DROPBOX RELAY: Write help text *****" 15 | include_tasks: write-help.yml 16 | -------------------------------------------------------------------------------- /roles/relay-cobalt-strike/templates/dns-config.j2: -------------------------------------------------------------------------------- 1 | =========================================================== 2 | DNS Configuration for CobaltStrike for {{ inventory_hostname }}: 3 | =========================================================== 4 | 5 | Please make sure you configured the DNS records as follows: 6 | 7 | Name: TTL: Type Value 8 | @ 5 Min A {{ ansible_host }} 9 | {{ dns_beacon_subdomain }} 5 Min A {{ ansible_host }} 10 | {{ dns_beacon_subdomain }} 5 Min NS {{ domain_name }} 11 | 12 | =========================================================== 13 | 14 | 15 | -------------------------------------------------------------------------------- /roles/relay-nginx/files/nginx.logrotate: -------------------------------------------------------------------------------- 1 | /var/log/nginx/*.log { 2 | weekly 3 | missingok 4 | rotate 52 5 | compress 6 | delaycompress 7 | notifempty 8 | create 0640 www-data adm 9 | sharedscripts 10 | prerotate 11 | if [ -d /etc/logrotate.d/httpd-prerotate ]; then \ 12 | run-parts /etc/logrotate.d/httpd-prerotate; \ 13 | fi \ 14 | endscript 15 | postrotate 16 | invoke-rc.d nginx rotate >/dev/null 2>&1 17 | endscript 18 | } 19 | -------------------------------------------------------------------------------- /roles/backend-manual-phish/vars/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | openvpn_client_profile_path: "{{ toolkit_directory }}/client_profiles/" 3 | manual_phish_docker_path: "{{ toolkit_directory }}/manual-phish/docker/" 4 | manual_phish_ovpn_pattern: "manual-phish@{{ relay_host_ip }}.ovpn" 5 | 6 | env_config: 7 | SMTP_HOST: "{{ internal_vpn_ip_gateway }}" 8 | REAL_NAME: "info" 9 | USER_NAME: "info" 10 | DOMAIN_NAME: "{{ domain_name }}" 11 | VPN_CONFIG: "manual-phish.ovpn" 12 | RELAY_HOST: "{{ relay_host_ip }}" 13 | CODENAME: "{{ codename }}" 14 | 15 | help_marker: "manual_phish_{{ domain_name }}" 16 | -------------------------------------------------------------------------------- /roles/backend-osint/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: "***** BACKEND OSINT: Set up client profiles *****" 3 | include_tasks: backend-ovpn-clients.yml 4 | 5 | - name: "***** BACKEND OSINT: Install additional packages and RDP Access *****" 6 | include_tasks: rdp-setup.yml 7 | 8 | - name: "***** BACKEND OSINT: Set up OSINT Tooling and VPN *****" 9 | include_tasks: osint-setup.yml 10 | 11 | - name: "***** BACKEND OSINT: Set up OVPN Killswitch *****" 12 | include_tasks: ovpn-killswitch.yml 13 | 14 | - name: "***** BACKEND OSINT: Write Help *****" 15 | include_tasks: write-help.yml 16 | 17 | -------------------------------------------------------------------------------- /roles/backend-manual-phish/files/manual-phish/files/change-sender-name.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | if [[ $# -lt 2 ]] ; then 3 | echo 4 | echo 'Changes the sender name of the outgoing phishing email' 5 | echo 'Usage: ./change-sender-name.sh ' 6 | echo 7 | echo 'Example: ./change-sender-name.sh "Jan Klaas Petersen" jk-petersen' 8 | echo 9 | exit 10 | fi 11 | 12 | 13 | sed -ri 's/set realname=.*/set realname='"\"$1\""/ /home/mutt/.muttrc 14 | sed -ri 's/set from=".*\@/set from="'"$2"@/ /home/mutt/.muttrc 15 | sed -ri 's/from .*\@/from '"$2"@/ /home/mutt/.msmtprc 16 | -------------------------------------------------------------------------------- /roles/relay-nginx/templates/revproxy.j2: -------------------------------------------------------------------------------- 1 | #ANSIBLE_MARKER_UPSTREAM 2 | 3 | 4 | server { 5 | listen 80; 6 | listen 443 ssl; 7 | server_name {{ domain_name }}; 8 | 9 | proxy_set_header X-Real-IP $remote_addr; 10 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 11 | 12 | #ANSIBLE_MARKER_PROXY 13 | 14 | location / { 15 | proxy_pass {{nginx_bounce_site}}; 16 | } 17 | 18 | ssl_certificate /etc/letsencrypt/live/{{domain_name}}/fullchain.pem; 19 | ssl_certificate_key /etc/letsencrypt/live/{{domain_name}}/privkey.pem; 20 | } 21 | 22 | -------------------------------------------------------------------------------- /roles/backend-dropbox/vars/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | openvpn_client_profile_path: "{{ toolkit_directory }}/client_profiles/" 3 | dropbox_docker_path: "{{ toolkit_directory }}/dropbox/docker/" 4 | dropbox_ovpn_pattern: "dropbox@{{ relay_host_ip }}.ovpn" 5 | 6 | dropbox_vpn_dir: "vpn_config" 7 | 8 | dropbox_config: 9 | VPNPORT: "{{ VPN_PORT }}" 10 | 11 | help_marker: "dropbox_{{ relay_host_ip }}" 12 | 13 | client_profiles: 14 | - "Dropbox-1" 15 | - "Dropbox-2" 16 | - "Dropbox-3" 17 | - "Dropbox-4" 18 | - "Dropbox-5" 19 | - "Dropbox-6" 20 | - "Dropbox-7" 21 | - "Dropbox-8" 22 | - "Dropbox-9" 23 | -------------------------------------------------------------------------------- /roles/backend-gophish/files/gophish/files/gophish-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "admin_server": { 3 | "listen_url": "0.0.0.0:3333", 4 | "use_tls": false, 5 | "cert_path": "gophish_admin.crt", 6 | "key_path": "gophish_admin.key" 7 | }, 8 | "phish_server": { 9 | "listen_url": "0.0.0.0:80", 10 | "use_tls": false, 11 | "cert_path": "example.crt", 12 | "key_path": "example.key" 13 | }, 14 | "db_name": "sqlite3", 15 | "db_path": "gophish.db", 16 | "migrations_prefix": "db/db_", 17 | "contact_address": "", 18 | "logging": { 19 | "filename": "/var/log/gophish-log.log", 20 | "level": "debug" 21 | } 22 | } -------------------------------------------------------------------------------- /roles/relay-nginx/templates/readme.md.j2: -------------------------------------------------------------------------------- 1 | '------------------------------------------------------' 2 | 3 | 'This is the README for the reverse nginx setup for {{ relay_to_client_profile }}' 4 | 5 | 6 | 'Traffic forward to incoming vpn designated "{{ relay_to_client_profile }}"' 7 | 'Secret Strings that will be forwarded:' 8 | {% for string in secret_strings %} 9 | ' - https://{{ domain_name }}/{{ string.string }}' 10 | ' Forwarded to: {{ string.connection_method }}://{{ string.forward_path }}' 11 | {% endfor %} 12 | 13 | '------------------------------------------------------' 14 | 15 | -------------------------------------------------------------------------------- /roles/backend-manual-phish/files/manual-phish/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | services: 3 | manualphish: 4 | privileged: true 5 | hostname: ${DOMAIN_NAME} 6 | build: 7 | context: . 8 | args: 9 | - VPN=${VPN_CONFIG} 10 | container_name: manual-phish-${DOMAIN_NAME} 11 | environment: 12 | - VPN=${VPN_CONFIG} 13 | - SMTP_HOST={SMTP_HOST} #Within the VPN connection 14 | - RELAY_HOST=${RELAY_HOST} 15 | - CODENAME=${CODENAME} 16 | - REAL_NAME=${REAL_NAME} 17 | - USER_NAME=${USER_NAME} 18 | - DOMAIN_NAME=${DOMAIN_NAME} 19 | volumes: 20 | - './logs:/var/log' 21 | -------------------------------------------------------------------------------- /roles/users/tasks/quality-of-life.yml: -------------------------------------------------------------------------------- 1 | - name: "User management: Symlink {{ toolkit_directory }} directory to homedir" 2 | become: yes 3 | ansible.builtin.file: 4 | src: "{{ toolkit_directory }}" 5 | dest: "/home/{{ item.value.username }}{{ toolkit_directory }}" 6 | state: link 7 | loop: "{{ lookup('dict', users, wantlist=True) }}" 8 | 9 | - name: "Copy Quality of life scripts" 10 | become: yes 11 | ansible.builtin.copy: 12 | src: "{{ item }}" 13 | dest: "{{ toolkit_directory }}/{{ item }}" 14 | owner: root 15 | group: rtspec 16 | mode: 0770 17 | with_items: 18 | - docker-interact.sh 19 | - docker-info.sh 20 | -------------------------------------------------------------------------------- /roles/relay-nginx/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: "***** RELAY - NGINX: OS Prep *****" 3 | include_tasks: os-prep.yml 4 | 5 | - name: "***** RELAY - NGINX: Request Lets encrypt cert for {{ domain_name }} *****" 6 | include_tasks: get-letsencrypt.yml 7 | 8 | - name: "***** PHISHING RELAY: Generate Client profiles *****" 9 | include_tasks: ovpn-create-client.yml 10 | 11 | - name: "***** RELAY - NGINX: Configure NGINX*****" 12 | include_tasks: nginx-config.yml 13 | 14 | - name: "***** RELAY - NGINX: Open port 443*****" 15 | include_tasks: firewall-config.yml 16 | 17 | - name: "***** RELAY - NGINX: Write help text *****" 18 | include_tasks: write-help.yml 19 | -------------------------------------------------------------------------------- /roles/relay-cobalt-strike/templates/readme.md.j2: -------------------------------------------------------------------------------- 1 | '------------------------------------------------------' 2 | 3 | 'This is the README for the CobaltStrike DNS Forwarder for {{ domain_name }}' 4 | 5 | This component relays DNS Traffic for CobaltStrike DNS C&C traffic 6 | DNS Traffic forward to incoming vpn designated '{{ relay_to_client_profile }}' 7 | Make sure the following DNS Settings are configured for this domain: 8 | - {{ dns_beacon_subdomain }} 5 min A {{ ansible_host }} 9 | - {{ dns_beacon_subdomain }} 5 min NS {{ domain_name }} 10 | 11 | May the shells be ever in your favour 12 | 13 | '------------------------------------------------------' 14 | -------------------------------------------------------------------------------- /roles/backend-common/files/bash_config: -------------------------------------------------------------------------------- 1 | #Create Recording directory 2 | RECDIR="/var/log/ascii/$USER" 3 | [[ -d $RECDIR ]] || mkdir -p $RECDIR 4 | 5 | #Name of the recording file 6 | RECFILE="$RECDIR"/$(date +%s%N).asciinema 7 | 8 | # Enable CLI Logging by Mansur 08-12-2016 9 | whoami="$(whoami)";export PROMPT_COMMAND='RETRN_VAL=$?;logger -p local6.debug "$whoami [$$]: $(history 1 | sed "s/^[ ]*[0-9]\+[ ]*//" ) [$RETRN_VAL]"' 10 | 11 | if [[ ${ASCIINEMA_REC:+1} ]] ; then 12 | echo Recording to: $RECDIR, Commands saved to: /var/log/commands 13 | else 14 | if ! ps -aux | grep asciinema | grep -v "grep" > /dev/null 15 | then 16 | asciinema rec $RECFILE 17 | fi 18 | fi 19 | -------------------------------------------------------------------------------- /roles/common-tasks/write-help.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: "Write informative text to /etc/bash.bashrc" 3 | become: yes 4 | ansible.builtin.blockinfile: 5 | marker: "# {mark} ANSIBLE MANAGED BLOCK {{ help_marker }}" 6 | path: /etc/bash.bashrc 7 | insertafter: "Installed components:" 8 | block: "{{ lookup('template', 'bash_help.j2') }}" 9 | 10 | - name: "Write informative text to {{ readme_location }}" 11 | become: yes 12 | ansible.builtin.blockinfile: 13 | marker: "# {mark} ANSIBLE MANAGED BLOCK {{ help_marker }}" 14 | path: "{{ readme_location }}" 15 | insertafter: ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" 16 | block: "{{ lookup('template', 'readme.md.j2') }}" 17 | 18 | -------------------------------------------------------------------------------- /roles/backend-osint/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: restart sshd 3 | become: yes 4 | ansible.builtin.service: 5 | name: sshd 6 | state: restarted 7 | 8 | - name: saveiptables 9 | become: yes 10 | ansible.builtin.shell: 11 | cmd: iptables-save > /etc/iptables/rules.v4 12 | 13 | - name: saveip6tables 14 | become: yes 15 | ansible.builtin.shell: 16 | cmd: ip6tables-save > /etc/iptables/rules.v6 17 | 18 | - name: Restart xrdp (Seems to behave badly on some systems. If this crashes, re-running usually fixes it) 19 | ansible.builtin.service: 20 | name: xrdp 21 | state: restarted 22 | daemon_reload: yes 23 | sleep: 30 24 | listen: "Restart RDP Service" 25 | -------------------------------------------------------------------------------- /roles/relay-common/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: "***** RELAY: Checking prerequisites *****" 3 | include_tasks: prerequisites.yml 4 | 5 | - name: "***** RELAY: Checking prerequisites for relays*****" 6 | include_tasks: prerequisites-relay.yml 7 | 8 | - name: "***** RELAY: Preparing the operating system *****" 9 | include_tasks: os-prep.yml 10 | 11 | - name: "***** RELAY: OpenVPN setup *****" 12 | include_tasks: ovpn-setup.yml 13 | 14 | - name: "***** RELAY: Harden the server *****" 15 | include_tasks: relay-hardening.yml 16 | 17 | - name: "***** BACKEND: Set up toolkit *****" 18 | include_tasks: toolkit.yml 19 | 20 | - name: "***** RELAY: Set up the help files *****" 21 | include_tasks: help-prep.yml 22 | -------------------------------------------------------------------------------- /roles/backend-manual-phish/files/manual-phish/files/send-all-mails.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | USER=$(id -nu) 4 | 5 | if [ $USER != "mutt" ]; then 6 | echo "Refusing to send mail as the '"${USER}"' user. Switch to the 'mutt' user and try again." 7 | exit 1 8 | else 9 | echo "Logged in as 'mutt' user. Continuing..." 10 | fi 11 | 12 | 13 | echo "Sending mails containing links" 14 | echo "user name" 15 | sleep 15 16 | /bin/bash send-link.sh rt-test@example.com https://example.com/tracking.png https://phishing-domain.com/marketing-update.doc 17 | sleep 15 18 | 19 | echo "Sending mails with attachment" 20 | echo "user name" 21 | sleep 15 22 | /bin/bash send-attachment.sh rt-test@example.com https://example.com/tracking.png 23 | -------------------------------------------------------------------------------- /roles/relay-phishing/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # tasks file for relay-phishing 3 | - name: "***** PHISHING RELAY: Further preparing the operating system *****" 4 | include_tasks: os-prep.yml 5 | 6 | - name: "***** PHISHING RELAY: Get LetsEncrypt certificate *****" 7 | include_tasks: get-letsencrypt.yml 8 | 9 | - name: "***** PHISHING RELAY: Generate Client profiles *****" 10 | include_tasks: ovpn-create-client.yml 11 | 12 | - name: "***** PHISHING RELAY: Further harden the server *****" 13 | include_tasks: firewall-config.yml 14 | 15 | - name: "***** PHISHING RELAY: Configuring the mailserver *****" 16 | include_tasks: configure-postfix.yml 17 | 18 | - name: "***** PHISHING RELAY: Write help text *****" 19 | include_tasks: write-help.yml 20 | -------------------------------------------------------------------------------- /tools/util/jinja_templating.py: -------------------------------------------------------------------------------- 1 | """ 2 | Creates a default jinja environment for tex-templates 3 | """ 4 | import os 5 | import jinja2 6 | 7 | 8 | def get_jinja_env(): 9 | """ Get the default jinja environment""" 10 | 11 | templates = os.path.join(os.path.dirname(os.path.realpath(__file__)), "templates") 12 | 13 | env = jinja2.Environment( 14 | block_start_string=r'\BLOCK{', 15 | block_end_string='}', 16 | variable_start_string=r'\VAR{', 17 | variable_end_string='}', 18 | comment_start_string=r'\#{', 19 | comment_end_string='}', 20 | line_statement_prefix='%%', 21 | line_comment_prefix='%#', 22 | trim_blocks=True, 23 | autoescape=False, 24 | loader=jinja2.FileSystemLoader(templates) 25 | ) 26 | return env 27 | -------------------------------------------------------------------------------- /roles/backend-osint/tasks/os-prep.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: "APT: update packages" 3 | become: yes 4 | ansible.builtin.apt: 5 | update_cache: yes 6 | cache_valid_time: 3600 7 | 8 | #- name: "APT: Install basic packages for OSINT server use" 9 | # become: yes 10 | # apt: 11 | # name: 12 | # - docker.io 13 | # - docker-compose 14 | # - python 15 | # - pwgen 16 | # - vim 17 | # - openvpn 18 | # - iptables 19 | # - iptables-persistent 20 | # - apparmor-utils 21 | # - tcpdump 22 | # - netcat 23 | # - dnsutils 24 | # - ipset 25 | # - zip 26 | # - screen 27 | # - apparmor-utils 28 | # - net-tools 29 | # - curl 30 | # - nano 31 | # - bridge-utils 32 | # state: present 33 | # update_cache: yes 34 | 35 | -------------------------------------------------------------------------------- /roles/relay-dropbox/tasks/firewall-config.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: "RELAY - DROPBOX: Forward for incoming dropbox traffic to backend docker" 3 | become: yes 4 | ansible.builtin.iptables: 5 | table: nat 6 | chain: PREROUTING 7 | in_interface: "{{ ansible_default_ipv4.interface }}" 8 | protocol: udp 9 | match: udp 10 | destination_port: "{{ exposed_port }}" 11 | jump: DNAT 12 | to_destination: " {{ dropbox_docker_ip }}:1194" 13 | comment: "Redirect Openvpn on {{ exposed_port }} to {{ dropbox_docker_ip }}:1194" 14 | state: present 15 | changed_when: false # Done always, so no change notification 16 | notify: saveiptables 17 | register: iptables_action 18 | retries: 10 19 | until: iptables_action is success or 'Another app is currently holding the xtables lock' not in iptables_action.msg 20 | 21 | -------------------------------------------------------------------------------- /roles/relay-phishing/templates/readme.md.j2: -------------------------------------------------------------------------------- 1 | '------------------------------------------------------' 2 | 3 | 'This is the README for the mailserver setup for {{ domain_name }}' 4 | 5 | POSTINSTALL INSTRUCTIONS: 6 | ' Configure your DNS settings according to {{ toolkit_directory }}/dns_config.txt' 7 | ' Enable outgoing mail ports in your VPS provider' 8 | ' Set reverse DNS in your VPS control panel to {{ domain_name }}' 9 | 10 | Any of our clients connected via OpenVPN can use this mailserver. Use the following information to connect: 11 | ' SMTP_HOST={{ internal_vpn_ip_gateway }}' 12 | ' DOMAIN_NAME={{ domain_name }}' 13 | ' VPN_CONFIG=manual-phish.ovpn OR gophish.ovpn' 14 | ' RELAY_HOST={{ ansible_host }}' 15 | ' CODENAME=DEVELOPMENT' 16 | 17 | Happy phishing! 18 | 19 | '------------------------------------------------------' 20 | 21 | -------------------------------------------------------------------------------- /ansible.cfg: -------------------------------------------------------------------------------- 1 | [defaults] 2 | #inventory = inventory/hosts 3 | #ansible_python_interpreter = /usr/bin/python3 4 | host_key_checking = False 5 | 6 | # Use the YAML callback plugin. 7 | #stdout_callback = unixy 8 | stdout_callback = yaml 9 | 10 | # Measure timings of playbooks 11 | callback_enabled = profile_roles, profile_tasks, timer 12 | 13 | # Use the stdout_callback when running ad-hoc commands. 14 | bin_ansible_callbacks = True 15 | 16 | # default timeout set to 60 seconds 17 | timeout = 60 18 | 19 | # If you have the processing power available and want to use more forks 20 | #forks = 30 21 | 22 | # If tasks fail, this is a fatal error 23 | #any_errors_fatal = True 24 | 25 | # Create ansible logs in the current directory 26 | log_path = ansible.log 27 | 28 | # Use a static private key for SSH 29 | #private_key_file = ~/.ssh/id_rt_dev_keys 30 | 31 | -------------------------------------------------------------------------------- /roles/backend-osint/tasks/ovpn-killswitch.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: "Install NetworkManager" 3 | become: yes 4 | ansible.builtin.apt: 5 | name: 6 | - network-manager 7 | state: present 8 | update_cache: yes 9 | cache_valid_time: 3600 10 | 11 | - name: "Create OpenVPN killswitch script" 12 | become: yes 13 | ansible.builtin.template: 14 | src: startvpn.j2 15 | dest: "{{ toolkit_directory }}/startvpn.sh" 16 | mode: 0755 17 | 18 | - name: "Add cronjob for starting VPN script" 19 | become: yes 20 | ansible.builtin.cron: 21 | name: "Force VPN Connection" 22 | user: root 23 | minute: "*" 24 | hour: "*" 25 | day: "*" 26 | month: "*" 27 | weekday: "*" 28 | job: "{{ toolkit_directory }}/startvpn.sh {{ openvpn_client_profile_path }}{{ relay_host }}/{{ osint_ovpn_pattern }}" 29 | cron_file: "forcevpn" 30 | -------------------------------------------------------------------------------- /roles/backend-webcatcher/files/web-catcher/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM php:7.2-apache 2 | LABEL maintainer="Ben Brucker " 3 | 4 | RUN apt-get -qq update && apt-get -qq install -y \ 5 | curl \ 6 | wget \ 7 | openvpn 8 | 9 | COPY src/ /var/www/html/ 10 | 11 | # RUN touch /var/log/requests.log 12 | # RUN chown www-data:www-data /var/log/requests.log 13 | 14 | # Fix bugs with rsyslog and Docker 15 | RUN echo "#!/bin/sh\nexit 0" > /usr/sbin/policy-rc.d 16 | 17 | # Copy the OpenVPN config and change the remote to the relay VPS 18 | # Also ensure $vpn is available inside the container 19 | ARG VPN 20 | ENV VPN=${VPN} 21 | 22 | COPY $VPN /root/$VPN 23 | 24 | # Copy the entrypoint and execute the container 25 | COPY docker-entrypoint.sh /docker-entrypoint.sh 26 | RUN chmod +x /docker-entrypoint.sh 27 | ENTRYPOINT ["/docker-entrypoint.sh"] 28 | 29 | -------------------------------------------------------------------------------- /roles/backend-manual-phish/files/manual-phish/files/.muttrc: -------------------------------------------------------------------------------- 1 | ######################### 2 | # sending with msmtp 3 | ######################### 4 | 5 | set sendmail="/usr/bin/msmtp" 6 | set use_from=yes 7 | set realname="SENDER_FULL_NAME" 8 | set from="SEND_NAME@PHISH_DOMAIN" 9 | set envelope_from=yes 10 | 11 | ######################### 12 | # receiving with imap 13 | ######################### 14 | 15 | set spoolfile="+INBOX" 16 | set record="+Sent" 17 | set postponed="+Drafts" 18 | set trash="+Trash" 19 | set header_cache = "/home/mutt/.mutt_cache" 20 | set message_cachedir = "/home/mutt/.mutt_cache" 21 | 22 | # Automatically poll subscribed mailboxes for new mail (new in 1.5.11) 23 | set imap_check_subscribed 24 | # Reduce polling frequency to a sane level 25 | set mail_check=60 26 | 27 | ######################### 28 | # usability 29 | ######################### 30 | 31 | set editor="vim" 32 | 33 | -------------------------------------------------------------------------------- /roles/common-tasks/backend-ovpn-clients.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: "Create local OpenVPN client profiles directory: {{ openvpn_client_profile_path }}{{ relay_host }}/" 3 | become: yes 4 | ansible.builtin.file: 5 | path: "{{ openvpn_client_profile_path }}{{ relay_host }}/" 6 | state: directory 7 | recurse: true 8 | 9 | - name: Map local client profiles 10 | ansible.builtin.find: 11 | paths: "{{ export_path }}/client_profiles/{{ relay_host }}/" 12 | recurse: no 13 | patterns: "*.ovpn" 14 | register: ovpn_client_files 15 | delegate_to: localhost 16 | 17 | - name: Copy OpenVPN profiles to remote C2 18 | become: yes 19 | ansible.builtin.copy: 20 | src: "{{ export_path }}/client_profiles/{{ relay_host }}/{{ item.path | basename }}" 21 | dest: "{{ openvpn_client_profile_path }}{{ relay_host }}/{{ item.path | basename }}" 22 | with_items: "{{ ovpn_client_files.files }}" 23 | -------------------------------------------------------------------------------- /roles/backend-gophish/vars/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | openvpn_client_profile_path: "{{ toolkit_directory }}/client_profiles/" 3 | gophish_docker_path: "{{ toolkit_directory }}/gophish/docker/" 4 | gophish_ovpn_pattern: "gophish@{{ relay_host_ip }}.ovpn" 5 | 6 | gophish_config: 7 | SMTP_USER: "{{ ansible_user }}" 8 | SMTP_PASSWORD: "{{ ansible_become_pass }}" 9 | SMTP_FROMS: "{{ from_addresses }}" 10 | CONTACT_EMAIL: "info@{{ domain_name }}" 11 | # SMTP_PORT: 25 12 | DOMAIN_NAME: "{{ domain_name }}" 13 | GOPHISHPORT: "{{ gophish_admin_port }}" 14 | GOPHISH_PW: "{{ gophish_password }}" 15 | SMTP_HOST: "{{ internal_vpn_ip_gateway }}" 16 | # Directory to intall gophish (no trailing slash!!!) 17 | #GOPHISHDIR:/opt/gophish 18 | 19 | # Github release version (latest for latest) 20 | #GOPHISHVERSION: latest 21 | #CONTACT_EMAIL= 22 | #GOPHISH_PW=gophish 23 | 24 | help_marker: "gophish_{{ domain_name }}" 25 | -------------------------------------------------------------------------------- /roles/backend-gophish/files/gophish/.env: -------------------------------------------------------------------------------- 1 | # Directory to intall gophish (no trailing slash!!!) 2 | GOPHISHDIR=/opt/gophish 3 | 4 | # Github release version (latest for latest) 5 | GOPHISHVERSION=latest 6 | 7 | # Local gophish port 8 | GOPHISHPORT=31337 9 | GOPHISHWEBPORT=31380 10 | 11 | # gophish contact information 12 | CONTACT_EMAIL= 13 | 14 | # The default GoPhish password 15 | GOPHISH_PW=gophish 16 | 17 | # The default GoPhish API token (default: echo "gophish" | md5sum) 18 | GOPHISH_API_TOKEN=c394550c7850cc7a3f2b86530af1b870 19 | 20 | # SMTP settings (will be automatically set by ansible) 21 | SMTP_HOST=10.8.0.1 22 | SMTP_PORT=25 23 | SMTP_USER=kaas 24 | SMTP_PASSWORD=test 25 | 26 | # From email addresses, delimit multiple with "," (NO SPACES!!!) 27 | SMTP_FROMS=gophish@test.domain.com 28 | 29 | # Other Info 30 | DOMAIN_NAME=random-domain-name.com 31 | RELAY_HOST=127.0.0.1 32 | VPN_CONFIG=gophish.ovpn 33 | CODENAME=DeltaQuadrant 34 | -------------------------------------------------------------------------------- /roles/backend-common/files/tcpdumper.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # chkconfig: 2345 20 80 3 | 4 | start() { 5 | echo "starting tcpdump" 6 | screen -S tcpmonitor -m -d sh -c 'tcpdump -i ens160 -w /var/log/tcpdump/cap.pcap -C 500 -s 1500 port not 22' 7 | sleep 2 8 | echo "tcpdump started with PID of $(ps fax | grep tcpdump | grep -v grep | head -1 | awk '{print $1}') and logging to /var/log/tcpdump/cap.pcap" 9 | echo "started tcpdump ["$(tput setaf 2)OK$(tput sgr0)"]" 10 | } 11 | 12 | stop() { 13 | echo "stopping tcpmonitor" 14 | screen -X -S tcpmonitor quit 15 | sleep 2 16 | echo "tcpmonitor stopped ["$(tput setaf 2)OK$(tput sgr0)"]" 17 | } 18 | 19 | case "$1" in 20 | start) 21 | start 22 | ;; 23 | stop) 24 | stop 25 | ;; 26 | restart) 27 | stop 28 | start 29 | ;; 30 | *) 31 | echo "Usage: $0 {start|stop|status|restart}" 32 | esac 33 | 34 | exit 0 35 | -------------------------------------------------------------------------------- /roles/relay-nginx/templates/update-rev-proxy-ip.j2: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # The goal of this script is to dynamically determine the connected openvpn 4 | # connection with a given name and set the reverse proxy redirection towards 5 | # that connection's IP address 6 | 7 | TARGET={{ relay_to_client_profile }} 8 | PORT={{ backend_port }} 9 | CURRENTIP=$(cat /etc/nginx/sites-available/{{ nginx_relay_config_name }}.conf | grep "server.*$TARGET" | head -n1| awk -F ' ' '{print $2}' | cut -d":" -f1) 10 | 11 | NEWIP=$(cat /etc/openvpn/openvpn-status.log | grep $TARGET | tail -n1 | cut -d"," -f1) 12 | 13 | if [ -z "$NEWIP" ] 14 | then 15 | NEWIP=127.0.0.1 16 | fi 17 | 18 | if [ "$CURRENTIP" = "$NEWIP" ]; then 19 | : 20 | else 21 | sed -ri "s/server (\b[0-9]{1,3}\.){3}[0-9]{1,3}\b:$PORT; # $TARGET/server ""$NEWIP:$PORT; # $TARGET/" /etc/nginx/sites-available/{{ nginx_relay_config_name }}.conf 22 | systemctl restart nginx.service 23 | fi 24 | -------------------------------------------------------------------------------- /roles/relay-phishing/tasks/firewall-config.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: "Iptables: Allow Mail Server Traffic outbound" 3 | become: yes 4 | ansible.builtin.iptables: 5 | chain: OUTPUT 6 | out_interface: "{{ ansible_default_ipv4.interface }}" 7 | destination_port: "{{ item }}" 8 | jump: ACCEPT 9 | protocol: tcp 10 | loop: 11 | - "25" 12 | - "143" 13 | - "587" 14 | - "993" 15 | 16 | - name: "Iptables: Allow inbound SMTP traffic" 17 | become: yes 18 | ansible.builtin.iptables: 19 | chain: INPUT 20 | in_interface: "{{ ansible_default_ipv4.interface }}" 21 | destination_port: "{{ item }}" 22 | jump: ACCEPT 23 | protocol: tcp 24 | loop: 25 | - "25" 26 | 27 | 28 | - name: "Iptables: Allow inbound SMTP OpenVPN traffic" 29 | become: yes 30 | ansible.builtin.iptables: 31 | chain: INPUT 32 | in_interface: "tun0" 33 | destination_port: "25" 34 | jump: ACCEPT 35 | protocol: tcp 36 | loop: 37 | - "25" 38 | -------------------------------------------------------------------------------- /roles/relay-phishing/templates/dns-config.j2: -------------------------------------------------------------------------------- 1 | =========================================================== 2 | DNS Configuration for {{ inventory_hostname }}: 3 | =========================================================== 4 | 5 | Please make sure you configured the DNS records as follows: 6 | 7 | Name: TTL: Type Value 8 | @ 5 Min A {{ ansible_host }} 9 | @ 5 Min MX 10 {{ domain_name }}. 10 | @ 5 Min TXT v=spf1 mx:{{ domain_name }} ip4:{{ ansible_host }} -all 11 | mail 5 Min A {{ ansible_host }} 12 | _dmarc 5 Min TXT v=DMARC1; p=none; sp=none; adkim=s; aspf=s; rua=mailto:dmarc-reports@{{ domain_name }}; ruf=mailto:dmarc-reports@{{ domain_name }}; fo=1 13 | mail._domainkey 1 Min TXT {{ dkim_contents['content'] | b64decode | regex_replace("t=y;","") }} 14 | 15 | Make sure there are no newlines in your dkim signature 16 | ALSO MAKE SURE OUTGOING MAIL PORTS ARE ENABELED IN YOUR VPS SETTINGS! 17 | 18 | =========================================================== 19 | 20 | 21 | -------------------------------------------------------------------------------- /roles/relay-dropbox/tasks/ovpn-setup.yml: -------------------------------------------------------------------------------- 1 | # Because a persistent connection is important for the dropboxes, make sure 2 | # the portforward is sent to a persistent IP address 3 | - name: "OpenVPN Server: Add a client config for static IP addresses" 4 | become: yes 5 | ansible.builtin.lineinfile: 6 | path: "/etc/openvpn/server.conf" 7 | line: 'client-config-dir ccd' 8 | state: present 9 | 10 | - name: "OpenVPN Server: Copy configuration file {{ ovpn_config_directory }}/server/server.conf to /etc/openvpn" 11 | become: yes 12 | ansible.builtin.lineinfile: 13 | path: "/etc/openvpn/ccd/dropbox" 14 | line: 'ifconfig-push {{ dropbox_docker_ip }} 255.255.255.255' 15 | state: present 16 | create: yes 17 | 18 | # TODO: Convert this into a handler that gets called when needed 19 | - name: "OpenVPN Server: Start the systemd service now and on (re)boot" 20 | become: yes 21 | ansible.builtin.systemd: 22 | name: openvpn@server 23 | enabled: yes 24 | state: restarted 25 | 26 | -------------------------------------------------------------------------------- /roles/common-tasks/help-prep.yml: -------------------------------------------------------------------------------- 1 | - name: "Check the contents of the bashrc file" 2 | become: yes 3 | ansible.builtin.shell: "cat /etc/bash.bashrc" 4 | register: help 5 | 6 | - name: "Logging: Write informative text to /etc/bash.bashrc" 7 | become: yes 8 | ansible.builtin.blockinfile: 9 | marker: "# {mark} ANSIBLE MANAGED BLOCK WELCOME TEXT" 10 | create: yes 11 | path: /etc/bash.bashrc 12 | block: | 13 | echo --------------------------------- 14 | echo Welcome to this RT machine: {{ inventory_hostname }} on {{ ansible_host }} 15 | echo 16 | echo Installed components: 17 | echo 18 | echo Please read the {{ readme_location }} file for more information about installed components 19 | echo 20 | when: '"Installed components" not in help.stdout' 21 | 22 | - name: "Create the basic readme file" 23 | become: yes 24 | ansible.builtin.template: 25 | src: create_readme.j2 26 | dest: "{{ readme_location }}" 27 | mode: 0755 28 | force: no 29 | 30 | -------------------------------------------------------------------------------- /roles/backend-gophish/files/gophish/files/gophish.service: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # /etc/init.d/gophish 3 | # initialization file for stop/start of gophish application server 4 | # description: stops/starts gophish application server 5 | # processname:gophish 6 | # config:/opt/gophish/config.json 7 | 8 | # define script variables 9 | 10 | processName=Gophish 11 | process=gophish 12 | appDirectory=/opt/gophish 13 | logfile=/var/log/gophish/gophish.log 14 | errfile=/var/log/gophish/gophish.error 15 | 16 | start() { 17 | echo 'Starting '${processName}'…' 18 | cd ${appDirectory} 19 | nohup ./$process >>$logfile 2>>$errfile & 20 | sleep 1 21 | } 22 | 23 | stop() { 24 | echo 'Stopping '${processName}'…' 25 | pid=$(/usr/sbin/pidof ${process}) 26 | kill ${pid} 27 | sleep 1 28 | } 29 | 30 | status() { 31 | pid=$(/usr/sbin/pidof ${process}) 32 | if [[ “$pid” != “” ]]; then 33 | echo ${processName}' is running…' 34 | else 35 | echo ${processName}' is not running…' 36 | fi 37 | } 38 | 39 | case $1 in 40 | start|stop|status) “$1” ;; 41 | esac -------------------------------------------------------------------------------- /roles/backend-manual-phish/files/manual-phish/files/bash-instructions: -------------------------------------------------------------------------------- 1 | ----------------------------------------------------------- 2 | Welcome to the manual phishing container. Follow up steps: 3 | 4 | 1: Check you are logged in as the "mutt" user 5 | 2: Verify the sender details in .muttrc and .msmtprc 6 | 3: You can easily change the name you are sending the email from with 7 | the change-sender-name.sh mail 8 | 4: Edit the email source files in EMAIL-Source-with-link.html or the 9 | or EMAIL-Source-with-attachment.html 10 | 5: Edit your send scripts in send-link.sh or send-attachment.sh 11 | 6: If you want you can prepare the sending in send-all-mails.sh 12 | 7: If you want to send an attachment, make sure to change the permissions with 13 | chown mutt:mutt , You can obtain root access by just typing "exit" 14 | 15 | DO NOT FORGET TO TEST YOUR MAIL 16 | - Send it to yourself 17 | - Use mail-tester.com 18 | - Check if everything works from mobile and laptop 19 | - See if the links reachable outside Company IP space 20 | -------------------------------------------------------------------------------- /roles/relay-phishing/vars/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # vars file for relay-phishing 3 | 4 | postfix_config: 5 | myhostname: "{{ domain_name }}" 6 | milter_protocol: 2 7 | milter_default_action: accept 8 | smtpd_milters: inet:localhost:12345 9 | non_smtpd_milters: inet:localhost:12345 10 | mydestination: '"{{ domain_name }}, DEVELOPMENT-phishing-relay, localhost.localdomain, localhost"' 11 | mynetworks: '"127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128 10.8.0.0/24"' 12 | smtpd_tls_cert_file: "/etc/letsencrypt/live/{{ domain_name }}/fullchain.pem" 13 | smtpd_tls_key_file: "/etc/letsencrypt/live/{{ domain_name }}/privkey.pem" 14 | smtpd_tls_security_level: may 15 | smtp_tls_security_level: encrypt 16 | smtpd_use_tls: "no" 17 | virtual_alias_domains: '"{{ domain_name }}"' 18 | virtual_alias_maps: "hash:/etc/postfix/virtual" 19 | 20 | client_profiles: 21 | - "gophish" # The gophish profile can be used to let an nginx reverse proxy automatically choose this connection 22 | - "manual-phish" 23 | 24 | help_marker: "relay_phishing_{{ domain_name }}" 25 | -------------------------------------------------------------------------------- /roles/backend-gophish/files/gophish/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | services: 3 | gophish: 4 | privileged: true 5 | hostname: ${DOMAIN_NAME} 6 | build: 7 | context: . 8 | args: 9 | - VPN=${VPN_CONFIG} 10 | - GOPHISHDIR=${GOPHISHDIR} 11 | - GOPHISHVERSION=${GOPHISHVERSION} 12 | - CONTACT_EMAIL=${CONTACT_EMAIL} 13 | container_name: gophish-${DOMAIN_NAME} 14 | environment: 15 | - VPN=${VPN_CONFIG} 16 | - GOPHISHDIR=${GOPHISHDIR} 17 | - GOPHISHVERSION=${GOPHISHVERSION} 18 | - RELAY_HOST=${RELAY_HOST} 19 | - CODENAME=${CODENAME} 20 | - GOPHISH_INITIAL_ADMIN_PASSWORD=${GOPHISH_PW} 21 | - GOPHISH_INITIAL_ADMIN_API_TOKEN=${GOPHISH_API_TOKEN} 22 | - SMTP_HOST=${SMTP_HOST} 23 | - SMTP_PORT=${SMTP_PORT} 24 | - SMTP_USER=${SMTP_USER} 25 | - SMTP_PASSWORD=${SMTP_PASSWORD} 26 | - SMTP_FROMS=${SMTP_FROMS} 27 | volumes: 28 | - './logs:/var/log' 29 | ports: 30 | - '${GOPHISHPORT}:3333' 31 | - '${GOPHISHWEBPORT}:80' 32 | 33 | -------------------------------------------------------------------------------- /roles/backend-manual-phish/templates/readme.md.j2: -------------------------------------------------------------------------------- 1 | ===== Component: Backend - ManualPhish for campaign {{ domain_name }} ===== 2 | 3 | ----- Running on server: {{ ansible_host }} 4 | 5 | ----- Relay Mail Server: {{ relay_host }} ({{ relay_host_ip }}) 6 | 7 | ----- Manual Phish for domain: {{ domain_name }} 8 | 9 | ----- Preconfigured: Sending profiles 10 | 11 | ----- Usage: 12 | 13 | Before usage it is recommended to use the following SSH-config: 14 | 15 | ``` 16 | Host 17 | HostName {{ ansible_host }} 18 | User 19 | IdentityFile ~/.ssh/ 20 | IdentitiesOnly yes 21 | 22 | Host 23 | HostName {{ relay_host_ip }} 24 | User 25 | IdentityFile ~/.ssh/ 26 | IdentitiesOnly yes 27 | 28 | ``` 29 | 30 | Use docker-info.sh and docker-interact.sh to interact with the deployed manual phish container. 31 | The welcome message shows the steps you can take to send out a mual phishing email from your command line via the deployed mailserver. 32 | 33 | -------------------------------------------------------------------------------- /roles/backend-dropbox/templates/readme.md.j2: -------------------------------------------------------------------------------- 1 | ===== Component: Backend - Implant container for {{ relay_host }} ===== 2 | 3 | ----- Running on server: {{ ansible_host }} 4 | 5 | ----- Relay Server: {{ relay_host }} ({{ relay_host_ip }}) 6 | 7 | ----- Exposed ports for incoming implants: {{ exposed_port }} 8 | 9 | ----- Usage: 10 | 11 | Before usage it is recommended to use the following SSH-config: 12 | 13 | ``` 14 | Host 15 | HostName {{ ansible_host }} 16 | User 17 | IdentityFile ~/.ssh/ 18 | IdentitiesOnly yes 19 | 20 | Host 21 | HostName {{ relay_host_ip }} 22 | User 23 | IdentityFile ~/.ssh/ 24 | IdentitiesOnly yes 25 | 26 | ``` 27 | 28 | Use docker-info.sh and docker-interact.sh to interact with the dropbox container 29 | 30 | This container will allow incoming OpenVPN connections from your hardware implants to that container. 31 | You can find all neccesary key material in your local configuration directory in "Exports_Autogenerated/dropbox_keys" 32 | 33 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Secura 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /roles/backend-osint/tasks/rdp-setup.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: "Install required packages" 3 | become: yes 4 | ansible.builtin.apt: 5 | name: 6 | - xfce4 7 | - xfce4-goodies 8 | - xorg 9 | - dbus-x11 10 | - x11-xserver-utils 11 | - firefox 12 | - xrdp 13 | state: latest 14 | update_cache: true 15 | cache_valid_time: 3600 16 | 17 | - name: "Add the xrdp user to the ssl-cert group" 18 | become: yes 19 | ansible.builtin.user: 20 | name: xrdp 21 | groups: ssl-cert 22 | append: yes 23 | 24 | - name: "Configure xrdp to only listen to localhost" 25 | become: yes 26 | ansible.builtin.blockinfile: 27 | marker: "# {mark} ANSIBLE MANAGED BLOCK" 28 | path: /etc/xrdp/xrdp.ini 29 | insertafter: "[Globals]" 30 | block: | 31 | address=127.0.0.1 32 | 33 | - name: "Add .xsession file for all users" 34 | become: yes 35 | ansible.builtin.copy: 36 | content: | 37 | startxfce4 38 | dest: "/home/{{ item.value.username }}/.xsession" 39 | owner: "{{ item.value.username }}" 40 | group: "{{ item.value.username }}" 41 | mode: 0775 42 | force: yes 43 | loop: "{{ lookup('dict', users, wantlist=True) }}" 44 | notify: "Restart RDP Service" 45 | 46 | -------------------------------------------------------------------------------- /roles/common-tasks/user-config.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: "User management: Ensure group 'rtspec' exists" 3 | become: true 4 | ansible.builtin.group: 5 | name: rtspec 6 | state: present 7 | 8 | - name: "User management: Ensure group 'docker' exists" 9 | become: true 10 | ansible.builtin.group: 11 | name: docker 12 | state: present 13 | 14 | - name: "User management: Adding existing user '{{ ansible_user }}' to group rtspec" 15 | become: true 16 | ansible.builtin.user: 17 | name: "{{ ansible_user }}" 18 | groups: rtspec 19 | append: yes 20 | 21 | - name: "User management: Add predefined users to the system" 22 | become: true 23 | ansible.builtin.user: 24 | name: "{{ item.value.username }}" 25 | password: "{{ item.value.pwhash }}" 26 | shell: /bin/bash 27 | groups: sudo,docker,rtspec 28 | append: yes 29 | state: present 30 | update_password: on_create 31 | loop: "{{ lookup('dict', users, wantlist=True) }}" 32 | 33 | 34 | - name: "User management: Set authorized keys for users" 35 | become: true 36 | ansible.builtin.authorized_key: 37 | user: "{{ item.value.username }}" 38 | key: "{{ item.value.sshkey }}" 39 | state: present 40 | loop: "{{ lookup('dict', users, wantlist=True) }}" 41 | -------------------------------------------------------------------------------- /roles/backend-webcatcher/templates/readme.md.j2: -------------------------------------------------------------------------------- 1 | ===== Component: Backend - WebCatcher for relay {{ relay_host }} ===== 2 | 3 | ----- Running on server: {{ ansible_host }} 4 | 5 | ----- Relay Mail Server: {{ relay_host }} ({{ relay_host_ip }}) 6 | 7 | ----- Preconfigured: Sending profiles 8 | 9 | ----- Usage: 10 | 11 | The goal of the webcathcer is to catch arbitrary HTTPS requests that are sent to the specific URL's. 12 | 13 | Before usage it is recommended to use the following SSH-config: 14 | 15 | ``` 16 | Host 17 | HostName {{ ansible_host }} 18 | User 19 | IdentityFile ~/.ssh/ 20 | IdentitiesOnly yes 21 | 22 | Host 23 | HostName {{ relay_host_ip }} 24 | User 25 | IdentityFile ~/.ssh/ 26 | IdentitiesOnly yes 27 | 28 | ``` 29 | 30 | Next, get the configured URL by logging in to the WebCatcher-relay: 31 | 32 | ``` 33 | ssh 34 | 35 | ``` 36 | 37 | The welcome message will display the URL's that will be forwarded to the C2 server. 38 | 39 | Visit the URL and check if the request was received by the webcatcher: 40 | 41 | ``` 42 | ssh 43 | cat /TOOLKIT/web-catcher/docker/Nginx-Webcatcher-Callback/logs/requests.log 44 | 45 | ``` 46 | 47 | -------------------------------------------------------------------------------- /roles/backend-manual-phish/tasks/manual-phish-setup.yml: -------------------------------------------------------------------------------- 1 | 2 | - name: "Manual Phish: Creating {{ manual_phish_docker_path }}{{ relay_host }}/ directory" 3 | become: yes 4 | ansible.builtin.file: 5 | path: "{{ manual_phish_docker_path }}{{ relay_host }}/" 6 | state: directory 7 | mode: 0755 8 | 9 | - name: "Manual Phish: Copy the Manual Phish docker container" 10 | become: yes 11 | ansible.builtin.copy: 12 | src: files/manual-phish/ 13 | dest: "{{ manual_phish_docker_path }}{{ relay_host }}/" 14 | 15 | - name: "Manual Phish selecting OVPN config based on pattern {{ manual_phish_ovpn_pattern }}" 16 | become: yes 17 | ansible.builtin.copy: 18 | src: "{{ openvpn_client_profile_path }}{{ relay_host }}/{{ manual_phish_ovpn_pattern }}" 19 | dest: "{{ manual_phish_docker_path }}{{ relay_host }}/manual-phish.ovpn" 20 | remote_src: yes 21 | 22 | - name: "Manual Phish setting environment variables" 23 | become: yes 24 | ansible.builtin.lineinfile: 25 | dest: "{{ manual_phish_docker_path }}{{ relay_host }}/.env" 26 | regexp: "^{{ item.key }}=.*$" 27 | line: "{{ item.key }}={{ item.value }}" 28 | backrefs: yes 29 | with_dict: "{{ env_config }}" 30 | 31 | - name: "Manual Phish Starting Manual Phish" 32 | become: yes 33 | ansible.builtin.shell: "cd {{ manual_phish_docker_path }}{{ relay_host }}/; docker-compose up -d --build" 34 | -------------------------------------------------------------------------------- /roles/backend-cobalt-strike/files/docker/10-start-openvpn.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | red=$(tput -T xterm-256color setaf 1) 4 | green=$(tput -T xterm-256color setaf 2) 5 | orange=$(tput -T xterm-256color setaf 3) 6 | blue=$(tput -T xterm-256color setaf 4) 7 | darkgreen=$(tput -T xterm-256color setaf 6) 8 | white=$(tput -T xterm-256color setaf 7) 9 | reset=$(tput -T xterm-256color sgr0) 10 | 11 | if [ ${DISABLE_VPN} ]; then 12 | echo "${orange}[!] VPN explicitly disabled${reset}" 13 | exit 0 14 | fi 15 | 16 | # TODO: make this a docker volume instead of hardcoding into the image 17 | sed -i -e "/remote / s/ .*/ ${RELAYVPS} 1194/" /root/*.ovpn 18 | 19 | # TODO: make this log file persistent as well 20 | openvpn --config "/root/${VPN}" --log /var/log/openvpn/connection.log --daemon 21 | 22 | cat <<-EOF 23 | ${blue}[*]${reset} Starting the VPN 24 | ${blue}[*]${reset} Connecting to: ${green}${RELAYVPS}${reset} - Project ${green}${CODENAME}${reset} 25 | 26 | EOF 27 | 28 | until [[ $(grep -i 'Initialization sequence completed' /var/log/openvpn/connection.log 2>/dev/null) ]]; do 29 | # Waiting for VPN connection to be established 30 | sleep 1 31 | done 32 | 33 | cat <<-EOF 34 | ${green}[+]${green} VPN connection established 35 | ${blue}[*]${reset} IP address of VPN interface: ${green}$(ip -4 address show dev tun0 | awk '/inet/ { print $2 }')${reset} 36 | EOF 37 | 38 | exit 0 39 | -------------------------------------------------------------------------------- /roles/backend-cobalt-strike/templates/browser.profile.j2: -------------------------------------------------------------------------------- 1 | # TODO: CHANGE-SECRETS-Before-use 2 | 3 | set sleeptime "5000"; 4 | set jitter "0"; 5 | set useragent "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Blank Lizard"; 6 | 7 | http-get { 8 | 9 | set uri "/{{ http_get_uri }}/"; 10 | 11 | client { 12 | 13 | header "Accept" "*/*"; 14 | 15 | metadata { 16 | base64; 17 | header "Cookie"; 18 | } 19 | } 20 | 21 | server { 22 | header "Content-Encoding" "gzip"; 23 | 24 | output { 25 | print; 26 | } 27 | } 28 | } 29 | 30 | http-post { 31 | set uri "/{{ http_post_uri }}/"; 32 | client { 33 | 34 | header "Accept" "*/*"; 35 | 36 | id { 37 | parameter "sn"; 38 | } 39 | 40 | 41 | output { 42 | base64; 43 | print; 44 | } 45 | } 46 | 47 | server { 48 | 49 | header "Server" "Server"; 50 | 51 | output { 52 | print; 53 | } 54 | } 55 | } 56 | 57 | # dress up the staging process too 58 | http-stager { 59 | 60 | set uri_x86 "/{{ http_stager_86_uri }}/vase.gif"; 61 | set uri_x64 "/{{ http_stager_64_uri }}/rose.gif"; 62 | 63 | server { 64 | header "Content-Type" "image/gif"; 65 | 66 | output { 67 | print; 68 | } 69 | } 70 | } 71 | 72 | -------------------------------------------------------------------------------- /roles/backend-cobalt-strike/files/docker/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:20.04 2 | LABEL maintainer="Geert Smelt " 3 | 4 | ARG DEBIAN_FRONTEND=noninteractive 5 | ARG LICENSE_KEY 6 | 7 | RUN apt -qq update && apt -qq install -y \ 8 | openssh-server \ 9 | openvpn \ 10 | syslog-ng \ 11 | rsync \ 12 | cron \ 13 | nano \ 14 | net-tools \ 15 | dnsutils \ 16 | iputils-ping \ 17 | openssl \ 18 | openjdk-11-jre-headless \ 19 | 2>&1 > /dev/null 20 | 21 | ADD cobaltstrike-dist.tgz /opt 22 | 23 | WORKDIR /opt/cobaltstrike 24 | RUN chown -R root:root /opt/cobaltstrike && echo ${LICENSE_KEY} | ./update 25 | 26 | # Create Docker volumes for data persistence 27 | RUN mkdir c2-profiles aggressor-scripts data logs 28 | ADD aggressor-scripts aggressor-scripts 29 | ADD c2-profiles c2-profiles 30 | VOLUME ["/opt/cobaltstrike/c2-profiles", "/opt/cobaltstrike/aggressor-scripts", "/opt/cobaltstrike/data", "/opt/cobaltstrike/logs"] 31 | 32 | COPY cobaltstrike.ovpn /root/cobaltstrike.ovpn 33 | 34 | RUN mkdir /docker-entrypoint.d 35 | 36 | COPY docker-entrypoint.sh / 37 | COPY 10-start-openvpn.sh /docker-entrypoint.d 38 | COPY 20-update-teamserver.sh /docker-entrypoint.d 39 | 40 | # TODO: Somehow after Ansible copies the whole folder, the executable permissions are lost 41 | RUN chmod +x /docker-entrypoint.sh && chmod +x /docker-entrypoint.d/*.sh 42 | 43 | ENTRYPOINT ["/docker-entrypoint.sh"] 44 | CMD ["./teamserver"] 45 | -------------------------------------------------------------------------------- /roles/backend-dropbox/files/docker/docker-entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | red=$(tput -T xterm-256color setaf 1) 4 | green=$(tput -T xterm-256color setaf 2) 5 | orange=$(tput -T xterm-256color setaf 3) 6 | blue=$(tput -T xterm-256color setaf 4) 7 | darkgreen=$(tput -T xterm-256color setaf 6) 8 | white=$(tput -T xterm-256color setaf 7) 9 | reset=$(tput -T xterm-256color sgr0) 10 | 11 | # Start the VPN (if applicable) and renew the certificate 12 | if [ -n ${VPN} ]; then 13 | mkdir -p /var/log/openvpn 14 | openvpn --config "/root/${VPN}" --log /var/log/openvpn/connection.log & 15 | sleep 4 16 | 17 | # Display the IP address 18 | IPADDR=$(ip addr show | grep "global tun0" | cut -f6 -d " ") 19 | cat <<-EOF 20 | ---------------- 21 | ${blue}[*]${reset} Starting the VPN 22 | ${blue}[*]${reset} Connecting to: ${green}${RELAY_HOST}${reset} - Project ${green}${CODENAME}${reset} 23 | ${blue}[*]${reset} IP address of VPN interface: ${green}${IPADDR}${reset} 24 | ---------------- 25 | EOF 26 | else 27 | ipaddr=$(ip addr show | grep "global eth0" | cut -f6 -d " ") 28 | cat <<-EOF 29 | -------------------------- 30 | ${orange}[!]${reset} ${red}DOCKER STARTED WITHOUT VPN${reset} 31 | ${orange}[!]${reset} To change this, set the VPN_CONFIG variable in the .env file accordingly 32 | ${orange}[!]${reset} IP address: ${IPADDR} 33 | -------------------------- 34 | EOF 35 | fi 36 | 37 | cd /etc/openvpn/server 38 | openvpn server.conf 39 | tail -F /var/log/openvpn/connection.log 40 | -------------------------------------------------------------------------------- /roles/backend-cobalt-strike/files/docker/docker-entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | if [ "$1" = "./teamserver" ] || [ "$1" = "./agscript" ]; then 6 | if /usr/bin/find "/docker-entrypoint.d/" -mindepth 1 -maxdepth 1 -type f -print -quit 2>/dev/null | read v; then 7 | echo >&2 "$0: /docker-entrypoint.d/ is not empty, will attempt to perform configuration" 8 | 9 | echo >&2 "$0: Looking for shell scripts in /docker-entrypoint.d/" 10 | find "/docker-entrypoint.d/" -follow -type f -print | sort -V | while read -r f; do 11 | case "$f" in 12 | *.sh) 13 | if [ -x "$f" ]; then 14 | echo >&2 "$0: Launching $f"; 15 | "$f" 16 | else 17 | # warn on shell scripts without exec bit 18 | echo >&2 "$0: Ignoring $f, not executable"; 19 | fi 20 | ;; 21 | *) echo >&2 "$0: Ignoring $f";; 22 | esac 23 | done 24 | 25 | echo >&2 "$0: Configuration complete; ready for start up" 26 | else 27 | echo >&2 "$0: No files found in /docker-entrypoint.d/, skipping configuration" 28 | fi 29 | else 30 | echo >&2 "You haven't specified a command to run, please do so in docker-compose.yml by overriding the 'command' parameter" 31 | fi 32 | 33 | # Start the Cobalt Strike Teamserver with the IP of the redirector 34 | exec "$@" 35 | -------------------------------------------------------------------------------- /roles/backend-webcatcher/files/web-catcher/docker-entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | red=$(tput -T xterm-256color setaf 1) 4 | green=$(tput -T xterm-256color setaf 2) 5 | orange=$(tput -T xterm-256color setaf 3) 6 | blue=$(tput -T xterm-256color setaf 4) 7 | darkgreen=$(tput -T xterm-256color setaf 6) 8 | white=$(tput -T xterm-256color setaf 7) 9 | reset=$(tput -T xterm-256color sgr0) 10 | 11 | # Start the VPN (if applicable) and renew the certificate 12 | if [ -n ${VPN} ]; then 13 | mkdir -p /var/log/openvpn 14 | openvpn --config "/root/${VPN}" --log /var/log/openvpn/connection.log & 15 | sleep 4 16 | 17 | # Display the IP address 18 | IPADDR=$(ip addr show | grep "global tun0" | cut -f6 -d " ") 19 | cat <<-EOF 20 | ---------------- 21 | ${blue}[*]${reset} Starting the VPN 22 | ${blue}[*]${reset} Connecting to: ${green}${RELAY_HOST}${reset} - Project ${green}${CODENAME}${reset} 23 | ${blue}[*]${reset} IP address of VPN interface: ${green}${IPADDR}${reset} 24 | ---------------- 25 | EOF 26 | else 27 | ipaddr=$(ip addr show | grep "global eth0" | cut -f6 -d " ") 28 | cat <<-EOF 29 | -------------------------- 30 | ${orange}[!]${reset} ${red}DOCKER STARTED WITHOUT VPN${reset} 31 | ${orange}[!]${reset} To change this, set the VPN_CONFIG variable in the .env file accordingly 32 | ${orange}[!]${reset} IP address: ${IPADDR} 33 | -------------------------- 34 | EOF 35 | fi 36 | 37 | touch /var/log/requests.log 38 | chown www-data:www-data /var/log/requests.log 39 | 40 | exec apache2-foreground 41 | -------------------------------------------------------------------------------- /roles/backend-manual-phish/files/manual-phish/files/send-attachment.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | USER=$(id -nu) 4 | 5 | if [ $USER != "mutt" ]; then 6 | echo "Refusing to send mail as the '"${USER}"' user. Switch to the 'mutt' user and try again." 7 | exit 1 8 | else 9 | echo "Logged in as 'mutt' user. Continuing..." 10 | fi 11 | 12 | if [ "$#" -ne 2 ]; then 13 | echo "Use: $0 " 14 | exit 15 | fi 16 | 17 | TO=$1 18 | TRACK=$2 19 | 20 | subject="XXX SUBJECT XXX" 21 | attachments="/home/mutt/XXX-FILENAME-XXX.doc" 22 | 23 | html_file="/home/mutt/EMAIL-Source-with-attachment.html" 24 | WORK_FILE="/home/mutt/TEMP-attachment.html" 25 | 26 | cat $html_file > $WORK_FILE 27 | # Add tracking pixel 28 | echo "" >> $WORK_FILE 29 | 30 | START=`date` 31 | # -------------------------------------------------------------------------------------- 32 | # send html with pdf attachment 33 | mutt -e "set content_type=text/html" -s "$subject" $TO -a $attachments -- < $WORK_FILE 34 | 35 | END=`date` 36 | echo "-------------------------------" >> /var/log/phish-log.log 37 | START=$(date) 38 | echo "START= $START" >> /var/log/phish-log.log 39 | echo "TARGET= $TO" >> /var/log/phish-log.log 40 | echo "TYPE= Attachment" >> /var/log/phish-log.log 41 | echo "ATTACH= $attachments" >> /var/log/phish-log.log 42 | echo "TRACKING= $TRACK" >> /var/log/phish-log.log 43 | END=$(date) 44 | echo "END= $END" >> /var/log/phish-log.log 45 | echo "-------------------------------" >> /var/log/phish-log.log 46 | -------------------------------------------------------------------------------- /roles/relay-cobalt-strike/tasks/cobaltstrike-config.yml: -------------------------------------------------------------------------------- 1 | - name: "RELAY - COBALTSTRIKE: Copy script to dynamically update the target for dns connections" 2 | become: yes 3 | ansible.builtin.template: 4 | src: "update-dns-forward.j2" 5 | dest: "{{ toolkit_directory }}/update-dns-forward-to-{{ relay_to_client_profile }}.sh" 6 | mode: "0744" 7 | 8 | - name: "RELAY - COBALTSTRIKE: Add cronjob entry for dynamically updating IP address" 9 | become: yes 10 | ansible.builtin.cron: 11 | name: "Update Backend IP address" 12 | user: root 13 | minute: 0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51,54,57 14 | hour: "*" 15 | day: "*" 16 | month: "*" 17 | weekday: "*" 18 | job: "{{ toolkit_directory }}/update-dns-forward-to-{{ relay_to_client_profile }}.sh" 19 | cron_file: "update-dns-forward-to-{{ relay_to_client_profile }}" 20 | 21 | - name: "RELAY - COBALTSTRIKE: Create a DNS Template" 22 | ansible.builtin.template: 23 | src: dns-config.j2 24 | dest: "{{ toolkit_directory }}/dns_config_cs_{{ inventory_hostname }}.txt" 25 | 26 | - name: "RELAY - COBALTSTRIKE: Create local DNS-Config directory" 27 | ansible.builtin.file: 28 | path: "{{ export_path }}/dns_configs/" 29 | state: directory 30 | recurse: yes 31 | delegate_to: localhost 32 | 33 | - name: "RELAY - COBALTSTRIKE: Download the client profiles to {{ export_path }} directory" 34 | ansible.builtin.fetch: 35 | src: "{{ toolkit_directory }}/dns_config_cs_{{ inventory_hostname }}.txt" 36 | dest: "{{ export_path }}/dns_configs/" 37 | flat: yes 38 | -------------------------------------------------------------------------------- /roles/backend-cobalt-strike/templates/readme.md.j2: -------------------------------------------------------------------------------- 1 | ===== Component: Backend - CobaltStrike for campaign {{ identification }} ===== 2 | 3 | ----- Running on server: {{ ansible_host }} 4 | 5 | ----- Relay Server: {{ relay_host }} ({{ relay_host_ip }}) 6 | 7 | ----- Exposed ports: 50050 8 | 9 | ----- Campaign for domain: {{ domain_name }} 10 | 11 | ----- Preconfigured: Default HTTPS and DNS Listeners 12 | 13 | ----- Usage: 14 | 15 | Before usage it is recommended to use the following SSH-config: 16 | 17 | ``` 18 | Host 19 | HostName {{ ansible_host }} 20 | LocalForward 50050 localhost:50050 21 | User 22 | IdentityFile ~/.ssh/ 23 | IdentitiesOnly yes 24 | 25 | Host 26 | HostName {{ relay_host_ip }} 27 | User 28 | IdentityFile ~/.ssh/ 29 | IdentitiesOnly yes 30 | 31 | ``` 32 | 33 | Next, get the configured URLs that you can use for your malleable profiles: 34 | 35 | ``` 36 | ssh 37 | 38 | ``` 39 | 40 | The welcome message will display the URL's that will be forwarded to the CobaltStrike instance. 41 | 42 | Next, connect to CobaltStrike by connecting to this server via SSH 43 | 44 | ``` 45 | ssh 46 | ``` 47 | 48 | Next point CobaltStrike to: 49 | ``` 50 | http://localhost:50050 51 | ``` 52 | 53 | Log-in to CobaltStrike using the preconfigured password. 54 | 55 | A default HTTPS and DNS listener should be preconfigured that can help you set up your own campaigns 56 | 57 | -------------------------------------------------------------------------------- /roles/relay-cobalt-strike/templates/update-dns-forward.j2: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # The goal of this script is to dynamically determine the connected openvpn 4 | # connection with a given name and set the dns forward for the incoming cs beacons 5 | 6 | TARGET={{ relay_to_client_profile }} 7 | CONTAINERIP=$(/usr/sbin/iptables-save | grep "Cobaltstrike Forward" | grep dport | cut -d" " -f4) 8 | SYSTEMIP=$(ip -4 addr show ens3 | awk '/inet/ { print $2 }' | cut -d "/" -f1) 9 | 10 | NEWCONTAINERIP=$(cat /etc/openvpn/openvpn-status.log | grep $TARGET | tail -n1 | cut -d"," -f1) 11 | 12 | if [ -z "$NEWCONTAINERIP" ] 13 | then 14 | NEWCONTAINERIP=127.0.0.1 15 | fi 16 | 17 | if [ "$CONTAINERIP" = "$NEWCONTAINERIP"/32 ]; then 18 | : 19 | else 20 | # First flush all old CS related forward rules. This seemed to be the 21 | # easiest way with the least amount of neccesary error handling 22 | /usr/sbin/iptables-save | grep -v "Cobaltstrike Forward" | /usr/sbin/iptables-restore 23 | 24 | # Mark incoming DNS packets with the tag 0x400 25 | /usr/sbin/iptables -t nat -A PREROUTING -m state --state NEW --protocol udp --destination ${SYSTEMIP} --destination-port 53 -j MARK --set-mark 0x400 -m comment --comment "Cobaltstrike Forward" 26 | 27 | # For every marked packet, apply a DNAT and a SNAT (in this case, a MASQUERADE) 28 | /usr/sbin/iptables -t nat -A PREROUTING -m mark --mark 0x400 --protocol udp -j DNAT --to-destination ${NEWCONTAINERIP}:53 -m comment --comment "Cobaltstrike Forward" 29 | /usr/sbin/iptables -t nat -A POSTROUTING -m mark --mark 0x400 -j MASQUERADE -m comment --comment "Cobaltstrike Forward" 30 | fi 31 | -------------------------------------------------------------------------------- /roles/backend-manual-phish/files/manual-phish/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:18.04 2 | LABEL maintainer="Ben Brucker " 3 | 4 | # Install required packages 5 | ARG DEBIAN_FRONTEND=noninteractive 6 | RUN apt-get -qq update && apt-get -qq install -y \ 7 | zip \ 8 | curl \ 9 | wget \ 10 | openvpn \ 11 | vim \ 12 | net-tools \ 13 | tcpdump \ 14 | netcat \ 15 | dnsutils \ 16 | ipset \ 17 | curl \ 18 | nano \ 19 | bridge-utils \ 20 | dnsutils \ 21 | iputils-ping \ 22 | syslog-ng \ 23 | python3 \ 24 | python3-pip \ 25 | mutt \ 26 | msmtp \ 27 | tzdata \ 28 | > /dev/null 29 | 30 | 31 | # Set the locale (I want to use German Umlauts) 32 | RUN locale-gen en_US.UTF-8 33 | ENV LANG en_US.UTF-8 34 | ENV LANGUAGE en_US:en 35 | ENV LC_ALL en_US.UTF-8 36 | 37 | # Set the timezone (change this to your local timezone) 38 | RUN echo "Europe/Amsterdam" | tee /etc/timezone 39 | RUN dpkg-reconfigure --frontend noninteractive tzdata 40 | 41 | RUN adduser --disabled-login --gecos '' mutt 42 | WORKDIR /home/mutt 43 | USER mutt 44 | 45 | COPY files/.muttrc /home/mutt/ 46 | COPY files/.msmtprc /home/mutt/ 47 | COPY files/* /home/mutt/ 48 | 49 | USER root 50 | # Fix bugs with rsyslog and Docker 51 | 52 | # Copy the OpenVPN config and change the remote to the relay VPS 53 | # Also ensure $vpn is available inside the container 54 | ARG VPN 55 | ENV VPN=${VPN} 56 | 57 | COPY $VPN /root/$VPN 58 | 59 | # Copy the entrypoint and execute the container 60 | COPY docker-entrypoint.sh /docker-entrypoint.sh 61 | RUN chmod +x /docker-entrypoint.sh 62 | ENTRYPOINT ["/docker-entrypoint.sh"] 63 | -------------------------------------------------------------------------------- /roles/backend-gophish/templates/readme.md.j2: -------------------------------------------------------------------------------- 1 | ===== Component: Backend - GoPhish for campaign {{ domain_name }} ===== 2 | 3 | ----- Running on server: {{ ansible_host }} 4 | 5 | ----- Relay Mail Server: {{ relay_host }} ({{ relay_host_ip }}) 6 | 7 | ----- Exposed ports: {{ gophish_admin_port }} 8 | 9 | ----- GoPhish for domain: {{ domain_name }} 10 | 11 | ----- Preconfigured: Sending profiles 12 | 13 | ----- Usage: 14 | 15 | Before usage it is recommended to use the following SSH-config: 16 | 17 | ``` 18 | Host 19 | HostName {{ ansible_host }} 20 | LocalForward {{ gophish_admin_port }} localhost:{{ gophish_admin_port }} 21 | User 22 | IdentityFile ~/.ssh/ 23 | IdentitiesOnly yes 24 | 25 | Host 26 | HostName {{ relay_host_ip }} 27 | User 28 | IdentityFile ~/.ssh/ 29 | IdentitiesOnly yes 30 | 31 | ``` 32 | 33 | Next, get the configured URLs that you can use for your landing page by logging in to the phishing-relay: 34 | 35 | ``` 36 | ssh 37 | 38 | ``` 39 | 40 | The welcome message will display the URL's that will be forwarded to the GoPhish instance. 41 | Save the URL to use as the URL for the GoPhish campaign. (When setting up the campaign in GoPhish) 42 | 43 | Next, connect to GoPhish: 44 | 45 | ``` 46 | ssh 47 | ``` 48 | 49 | 50 | 51 | Use your browser to navigate to: 52 | 53 | ``` 54 | http://localhost:13337 55 | ``` 56 | 57 | 58 | Log-in to gophish using the preconfigured password. 59 | Now you can configure your GoPhish campagin. 60 | -------------------------------------------------------------------------------- /roles/backend-manual-phish/files/manual-phish/files/send-link.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | USER=$(id -nu) 4 | 5 | if [ $USER != mutt ]; then 6 | echo "Refusing to send mail as the '"${USER}"' user. Switch to the 'mutt' user and try again." 7 | exit 1 8 | else 9 | echo "Logged in as '${USER}' user. Continuing..." 10 | fi 11 | 12 | if [ "$#" -ne 3 ]; then 13 | echo "Use: $0 " 14 | exit 15 | fi 16 | 17 | # TO = Email Address 18 | # TRACK = Tracking Pixel Name 19 | # LINK = Link to the phishing page / file download 20 | TO=$1 21 | TRACK=$2 22 | LINK=$3 23 | 24 | subject="XXX SUBJECT XXX" 25 | 26 | html_file="./EMAIL-Source-with-link.html" 27 | WORK_FILE="./TEMP-link.html" 28 | 29 | START=`date` 30 | # Make working copy of the source 31 | 32 | cp $html_file $WORK_FILE 33 | # Complete the link 34 | sed -i "s|UNIQUELINK|$LINK|g" $WORK_FILE 35 | # Add tracking pixel 36 | echo "" >> $WORK_FILE 37 | 38 | # -------------------------------------------------------------------------------------- 39 | # send html email 40 | mutt -e "set content_type=text/html" -s "$subject" $TO -- < $WORK_FILE 41 | 42 | 43 | echo "-------------------------------" >> /var/log/phish-log.log 44 | START=$(date) 45 | 46 | echo "START= $START" >> /var/log/phish-log.log 47 | echo "TARGET= $TO" >> /var/log/phish-log.log 48 | echo "TYPE= LINK" >> /var/log/phish-log.log 49 | echo "TRACKING= $TRACK" >> /var/log/phish-log.log 50 | echo "LINK= $LINK" >> /var/log/phish-log.log 51 | END=$(date) 52 | echo "END= $END" >> /var/log/phish-log.log 53 | echo "-------------------------------" >> /var/log/phish-log.log 54 | 55 | 56 | -------------------------------------------------------------------------------- /roles/backend-webcatcher/tasks/catcher-setup.yml: -------------------------------------------------------------------------------- 1 | 2 | - name: "Web-Catcher: Creating {{ web_catcher_docker_path }}{{ relay_host }}/ directory" 3 | become: yes 4 | ansible.builtin.file: 5 | path: "{{ web_catcher_docker_path }}{{ relay_host }}/" 6 | state: directory 7 | mode: 0755 8 | 9 | - name: "Web-Catcher: Copy the Catcher docker container" 10 | become: yes 11 | ansible.builtin.copy: 12 | src: files/web-catcher/ 13 | dest: "{{ web_catcher_docker_path }}{{ relay_host }}/" 14 | force: yes 15 | 16 | - name: "Web-Catcher selecting OVPN config based on pattern {{ web_catcher_ovpn_pattern }}" 17 | become: yes 18 | ansible.builtin.copy: 19 | src: "{{ openvpn_client_profile_path }}{{ relay_host }}/{{ web_catcher_ovpn_pattern }}" 20 | dest: "{{ web_catcher_docker_path }}{{ relay_host }}/web-catcher.ovpn" 21 | remote_src: yes 22 | 23 | - name: Add Codename 24 | ansible.builtin.lineinfile: 25 | dest: "{{ web_catcher_docker_path }}{{ relay_host }}/.env" 26 | regexp: "^CODENAME=.*$" 27 | line: "CODENAME={{ codename }}" 28 | backrefs: yes 29 | become: yes 30 | 31 | - name: "Setting Remote addresses" 32 | ansible.builtin.lineinfile: 33 | dest: "{{ web_catcher_docker_path }}{{ relay_host }}/.env" 34 | regexp: "^RELAY_HOST=.*$" 35 | line: "RELAY_HOST={{ relay_host_ip }}" 36 | backrefs: yes 37 | become: yes 38 | 39 | - name: "Web-Catcher Building image" 40 | become: yes 41 | ansible.builtin.shell: "cd {{ web_catcher_docker_path }}{{ relay_host }}/; docker-compose build" 42 | 43 | - name: "Web-Catcher Starting Docker" 44 | become: yes 45 | ansible.builtin.shell: "cd {{ web_catcher_docker_path }}{{ relay_host }}/; docker-compose up --detach" 46 | -------------------------------------------------------------------------------- /roles/relay-phishing/meta/main.yml: -------------------------------------------------------------------------------- 1 | galaxy_info: 2 | author: your name 3 | description: your role description 4 | company: your company (optional) 5 | 6 | # If the issue tracker for your role is not on github, uncomment the 7 | # next line and provide a value 8 | # issue_tracker_url: http://example.com/issue/tracker 9 | 10 | # Choose a valid license ID from https://spdx.org - some suggested licenses: 11 | # - BSD-3-Clause (default) 12 | # - MIT 13 | # - GPL-2.0-or-later 14 | # - GPL-3.0-only 15 | # - Apache-2.0 16 | # - CC-BY-4.0 17 | license: license (GPL-2.0-or-later, MIT, etc) 18 | 19 | min_ansible_version: 2.1 20 | 21 | # If this a Container Enabled role, provide the minimum Ansible Container version. 22 | # min_ansible_container_version: 23 | 24 | # 25 | # Provide a list of supported platforms, and for each platform a list of versions. 26 | # If you don't wish to enumerate all versions for a particular platform, use 'all'. 27 | # To view available platforms and versions (or releases), visit: 28 | # https://galaxy.ansible.com/api/v1/platforms/ 29 | # 30 | # platforms: 31 | # - name: Fedora 32 | # versions: 33 | # - all 34 | # - 25 35 | # - name: SomePlatform 36 | # versions: 37 | # - all 38 | # - 1.0 39 | # - 7 40 | # - 99.99 41 | 42 | galaxy_tags: [] 43 | # List tags for your role here, one per line. A tag is a keyword that describes 44 | # and categorizes the role. Users find roles by searching for tags. Be sure to 45 | # remove the '[]' above, if you add tags to this list. 46 | # 47 | # NOTE: A tag is limited to a single word comprised of alphanumeric characters. 48 | # Maximum 20 tags per role. 49 | 50 | dependencies: [] 51 | -------------------------------------------------------------------------------- /roles/backend-gophish/files/gophish/files/gophish_api.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import requests 4 | import argparse 5 | import sys 6 | 7 | parser = argparse.ArgumentParser() 8 | # connection 9 | parser.add_argument("-H", dest="host", default=None) 10 | parser.add_argument("-P", dest="port", type=int, default=25) 11 | 12 | # auth 13 | parser.add_argument("-u", dest="user", default=None) 14 | parser.add_argument("-p", dest="passwd", default=None) 15 | 16 | # gophish 17 | parser.add_argument("-k", dest="key", default=None) 18 | parser.add_argument("-f", dest="froms", default=None) 19 | 20 | arguments = parser.parse_args() 21 | 22 | if not arguments.host: 23 | sys.stderr.write("No host was specified\n") 24 | sys.exit(-1) 25 | 26 | if not arguments.key: 27 | sys.stderr.write("No API key was specified\n") 28 | sys.exit(-1) 29 | 30 | if not arguments.froms: 31 | sys.stderr.write("From addresses are required\n") 32 | sys.exit(-1) 33 | 34 | url = "http://127.0.0.1:3333/api/smtp/" 35 | 36 | existing_entries = requests.get(url, headers={"Authorization": arguments.key}).json() 37 | 38 | froms = [x.strip() for x in arguments.froms.split(",")] 39 | for f in froms: 40 | f = f.lower() 41 | has_from = len(existing_entries) and f in [r["from_address"] for r in existing_entries] 42 | if has_from: 43 | continue 44 | 45 | payload = { 46 | "name": f.split("@")[0], 47 | "host": arguments.host, 48 | "interface_type": "SMTP", 49 | "from_address": f, 50 | "ignore_cert_errors": True 51 | } 52 | 53 | if arguments.user and arguments.passwd: 54 | payload["username"] = arguments.user 55 | payload["password"] = arguments.passwd 56 | 57 | requests.post(url, headers={"Authorization": arguments.key}, json=payload).json() 58 | print("Added user: %s" % f) -------------------------------------------------------------------------------- /roles/backend-cobalt-strike/templates/listener.service.cna.j2: -------------------------------------------------------------------------------- 1 | println('listener_service.cna: Loading listener_service.cna...'); 2 | 3 | on ready{ 4 | println('listener_service.cna: Creating HTTPS Listener...'); 5 | 6 | listener_create_ext( 7 | "{{ codename }}-HTTPS", # Listener name, use something unique across all teamservers (i.e., server1-http) 8 | "windows/beacon_https/reverse_https", # Listener type, remember, payloads are driven by listeners 9 | %(host => "{{ domain_name }}", # Staging host, Only one staging host can be set 10 | port => 443, # Port for c2 communications 11 | beacons => "{{ domain_name }}", # Comma separated list of beacon hosts 12 | strategy => "round-robin" # Host rotation strategy aka fail strategy 13 | ) 14 | ); 15 | println('listener_service.cna: HTTPS Listener Created'); 16 | 17 | println('listener_service.cna: Creating DNS Listener...'); 18 | 19 | listener_create_ext( 20 | "{{ codename }}-DNS", # Listener name, use something unique across all teamservers (i.e., server1-http) 21 | "windows/beacon_dns/reverse_dns_txt", # Listener type, remember, payloads are driven by listeners 22 | %(host => "{{ dns_beacon_subdomain }}.{{ domain_name }}", # Staging host, Only one staging host can be set 23 | port => 53, 24 | bindto => 53, # Port for c2 communications 25 | beacons => "{{ dns_beacon_subdomain }}.{{ domain_name }}", # Comma separated list of beacon hosts 26 | strategy => "round-robin" # Host rotation strategy aka fail strategy 27 | ) 28 | ); 29 | println('listener_service.cna: DNS Listener Created'); 30 | }; 31 | -------------------------------------------------------------------------------- /roles/relay-dropbox/meta/main.yml: -------------------------------------------------------------------------------- 1 | galaxy_info: 2 | author: Ben Brucker 3 | description: Sets up requirements to enable relay functionality for RT dropboxes 4 | company: Secura BV 5 | 6 | # If the issue tracker for your role is not on github, uncomment the 7 | # next line and provide a value 8 | # issue_tracker_url: http://example.com/issue/tracker 9 | 10 | # Choose a valid license ID from https://spdx.org - some suggested licenses: 11 | # - BSD-3-Clause (default) 12 | # - MIT 13 | # - GPL-2.0-or-later 14 | # - GPL-3.0-only 15 | # - Apache-2.0 16 | # - CC-BY-4.0 17 | license: license (GPL-2.0-or-later, MIT, etc) 18 | 19 | min_ansible_version: 2.1 20 | 21 | # If this a Container Enabled role, provide the minimum Ansible Container version. 22 | # min_ansible_container_version: 23 | 24 | # 25 | # Provide a list of supported platforms, and for each platform a list of versions. 26 | # If you don't wish to enumerate all versions for a particular platform, use 'all'. 27 | # To view available platforms and versions (or releases), visit: 28 | # https://galaxy.ansible.com/api/v1/platforms/ 29 | # 30 | # platforms: 31 | # - name: Fedora 32 | # versions: 33 | # - all 34 | # - 25 35 | # - name: SomePlatform 36 | # versions: 37 | # - all 38 | # - 1.0 39 | # - 7 40 | # - 99.99 41 | 42 | galaxy_tags: [] 43 | # List tags for your role here, one per line. A tag is a keyword that describes 44 | # and categorizes the role. Users find roles by searching for tags. Be sure to 45 | # remove the '[]' above, if you add tags to this list. 46 | # 47 | # NOTE: A tag is limited to a single word comprised of alphanumeric characters. 48 | # Maximum 20 tags per role. 49 | 50 | dependencies: [] 51 | -------------------------------------------------------------------------------- /step-0-first-time-setup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | orange=$(printf '\033[0;33m') 4 | green=$(printf '\033[0;32m') 5 | reset=$(printf '\033[0;00m') 6 | blue=$(printf '\033[0;34m') 7 | red=$(printf '\033[0;31m') 8 | yellow=$(printf '\033[0;93m') 9 | purple=$(printf '\033[0;95m') 10 | cyan=$(printf '\033[1;36m') 11 | 12 | bold=$(printf '\033[1m') 13 | underline=$(printf '\033[4m') 14 | reversed=$(printf '\033[7m') 15 | 16 | echo 17 | echo "__________ .___ __ __.__ .___" 18 | echo "\______ \ ____ __| _/ / \ / \__|____________ _______ __| _/" 19 | echo " | _// __ \ / __ | \ \/\/ / \___ /\__ \\_ __ \/ __ |" 20 | echo " | | \ ___// /_/ | \ /| |/ / / __ \| | \/ /_/ |" 21 | echo " |____|_ /\___ >____ | \__/\ / |__/_____ \(____ /__| \____ |" 22 | echo " \/ \/ \/ \/ \/ \/ \/" 23 | echo 24 | echo " --- First Time Setup --- " 25 | echo 26 | echo 27 | 28 | echo -e "${cyan}[*] Performing first time setup${reset}\n\n" 29 | 30 | echo -e "${cyan}\n[*] Installing required packages via apt${reset}\n\n" 31 | sudo apt-get install python3 python3-pip ssh-askpass 32 | 33 | echo -e "${cyan}\n[*] Installing required Python packages${reset}\n\n" 34 | python3 -m pip install -r requirements.txt 35 | 36 | echo -e "${cyan}\n[+] Installation complete.${reset}\n\n" 37 | echo -e "${yellow}[ ] Manual follow up required!${reset}\n" 38 | echo -e "${yellow} Step 1: Edit the globals.yml file via 'ansible-vault edit globals.yml'${reset}" 39 | echo -e "${yellow} The password is 'ansible'${reset}\n" 40 | echo -e "${yellow} Step 2: Set a sensible password for your globals.yml via 'ansible-vault rekey globals.yml'${reset}\n" 41 | 42 | -------------------------------------------------------------------------------- /roles/backend-dropbox/files/docker/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:18.04 2 | LABEL maintainer="Ben Brucker" 3 | 4 | # Install required packages 5 | ARG DEBIAN_FRONTEND=noninteractive 6 | RUN apt-get -qq update && apt-get -qq install -y \ 7 | zip \ 8 | ssh \ 9 | curl \ 10 | wget \ 11 | openvpn \ 12 | vim \ 13 | dnsutils \ 14 | tcpdump \ 15 | netcat \ 16 | dnsutils \ 17 | ssh \ 18 | ipset \ 19 | iputils-ping \ 20 | syslog-ng \ 21 | python3 \ 22 | net-tools \ 23 | curl \ 24 | nano \ 25 | openvpn \ 26 | easy-rsa \ 27 | bridge-utils \ 28 | python3-pip \ 29 | > /dev/null 30 | 31 | RUN python3 -m pip install --upgrade requests 32 | 33 | ARG VPNPORT 34 | ENV VPNPORT=${VPNPORT} 35 | # Run the installation shell script 36 | RUN mkdir -p /etc/openvpn/server/ 37 | 38 | COPY files/id_dropbox / 39 | COPY files/check_connections.sh / 40 | COPY vpn_config/server/ca.crt /etc/openvpn/server/ 41 | COPY vpn_config/server/dh.pem /etc/openvpn/server/ 42 | COPY vpn_config/server/server.conf /etc/openvpn/server/ 43 | COPY vpn_config/server/server.crt /etc/openvpn/server/ 44 | COPY vpn_config/server/server.key /etc/openvpn/server/ 45 | COPY vpn_config/server/ta.key /etc/openvpn/server/ 46 | 47 | run service ssh stop 48 | 49 | # Fix bugs with rsyslog and Docker 50 | RUN echo "#!/bin/sh\nexit 0" > /usr/sbin/policy-rc.d 51 | 52 | # Copy the OpenVPN config and change the remote to the relay VPS 53 | # Also ensure $vpn is available inside the container 54 | ARG VPN 55 | ENV VPN=${VPN} 56 | 57 | COPY $VPN /root/$VPN 58 | 59 | # Copy the entrypoint and execute the container 60 | COPY docker-entrypoint.sh /docker-entrypoint.sh 61 | RUN chmod +x /docker-entrypoint.sh 62 | RUN chmod 600 /id_dropbox 63 | ENTRYPOINT ["/docker-entrypoint.sh"] 64 | -------------------------------------------------------------------------------- /roles/users/meta/main.yml: -------------------------------------------------------------------------------- 1 | galaxy_info: 2 | author: your name 3 | description: your role description 4 | company: your company (optional) 5 | 6 | # If the issue tracker for your role is not on github, uncomment the 7 | # next line and provide a value 8 | # issue_tracker_url: http://example.com/issue/tracker 9 | 10 | # Choose a valid license ID from https://spdx.org - some suggested licenses: 11 | # - BSD-3-Clause (default) 12 | # - MIT 13 | # - GPL-2.0-or-later 14 | # - GPL-3.0-only 15 | # - Apache-2.0 16 | # - CC-BY-4.0 17 | license: license (GPL-2.0-or-later, MIT, etc) 18 | 19 | min_ansible_version: 2.1 20 | 21 | # If this a Container Enabled role, provide the minimum Ansible Container version. 22 | # min_ansible_container_version: 23 | 24 | # 25 | # Provide a list of supported platforms, and for each platform a list of versions. 26 | # If you don't wish to enumerate all versions for a particular platform, use 'all'. 27 | # To view available platforms and versions (or releases), visit: 28 | # https://galaxy.ansible.com/api/v1/platforms/ 29 | # 30 | # platforms: 31 | # - name: Fedora 32 | # versions: 33 | # - all 34 | # - 25 35 | # - name: SomePlatform 36 | # versions: 37 | # - all 38 | # - 1.0 39 | # - 7 40 | # - 99.99 41 | 42 | galaxy_tags: [] 43 | # List tags for your role here, one per line. A tag is a keyword that describes 44 | # and categorizes the role. Users find roles by searching for tags. Be sure to 45 | # remove the '[]' above, if you add tags to this list. 46 | # 47 | # NOTE: A tag is limited to a single word comprised of alphanumeric characters. 48 | # Maximum 20 tags per role. 49 | 50 | dependencies: [] 51 | # List your role dependencies here, one per line. Be sure to remove the '[]' above, 52 | # if you add dependencies to this list. 53 | -------------------------------------------------------------------------------- /roles/relay-osint/meta/main.yml: -------------------------------------------------------------------------------- 1 | galaxy_info: 2 | author: your name 3 | description: your role description 4 | company: your company (optional) 5 | 6 | # If the issue tracker for your role is not on github, uncomment the 7 | # next line and provide a value 8 | # issue_tracker_url: http://example.com/issue/tracker 9 | 10 | # Choose a valid license ID from https://spdx.org - some suggested licenses: 11 | # - BSD-3-Clause (default) 12 | # - MIT 13 | # - GPL-2.0-or-later 14 | # - GPL-3.0-only 15 | # - Apache-2.0 16 | # - CC-BY-4.0 17 | license: license (GPL-2.0-or-later, MIT, etc) 18 | 19 | min_ansible_version: 2.1 20 | 21 | # If this a Container Enabled role, provide the minimum Ansible Container version. 22 | # min_ansible_container_version: 23 | 24 | # 25 | # Provide a list of supported platforms, and for each platform a list of versions. 26 | # If you don't wish to enumerate all versions for a particular platform, use 'all'. 27 | # To view available platforms and versions (or releases), visit: 28 | # https://galaxy.ansible.com/api/v1/platforms/ 29 | # 30 | # platforms: 31 | # - name: Fedora 32 | # versions: 33 | # - all 34 | # - 25 35 | # - name: SomePlatform 36 | # versions: 37 | # - all 38 | # - 1.0 39 | # - 7 40 | # - 99.99 41 | 42 | galaxy_tags: [] 43 | # List tags for your role here, one per line. A tag is a keyword that describes 44 | # and categorizes the role. Users find roles by searching for tags. Be sure to 45 | # remove the '[]' above, if you add tags to this list. 46 | # 47 | # NOTE: A tag is limited to a single word comprised of alphanumeric characters. 48 | # Maximum 20 tags per role. 49 | 50 | # List your role dependencies here, one per line. Be sure to remove the '[]' above, 51 | # if you add dependencies to this list. 52 | dependencies: [] 53 | -------------------------------------------------------------------------------- /roles/backend-common/meta/main.yml: -------------------------------------------------------------------------------- 1 | galaxy_info: 2 | author: your name 3 | description: your role description 4 | company: your company (optional) 5 | 6 | # If the issue tracker for your role is not on github, uncomment the 7 | # next line and provide a value 8 | # issue_tracker_url: http://example.com/issue/tracker 9 | 10 | # Choose a valid license ID from https://spdx.org - some suggested licenses: 11 | # - BSD-3-Clause (default) 12 | # - MIT 13 | # - GPL-2.0-or-later 14 | # - GPL-3.0-only 15 | # - Apache-2.0 16 | # - CC-BY-4.0 17 | license: license (GPL-2.0-or-later, MIT, etc) 18 | 19 | min_ansible_version: 2.1 20 | 21 | # If this a Container Enabled role, provide the minimum Ansible Container version. 22 | # min_ansible_container_version: 23 | 24 | # 25 | # Provide a list of supported platforms, and for each platform a list of versions. 26 | # If you don't wish to enumerate all versions for a particular platform, use 'all'. 27 | # To view available platforms and versions (or releases), visit: 28 | # https://galaxy.ansible.com/api/v1/platforms/ 29 | # 30 | # platforms: 31 | # - name: Fedora 32 | # versions: 33 | # - all 34 | # - 25 35 | # - name: SomePlatform 36 | # versions: 37 | # - all 38 | # - 1.0 39 | # - 7 40 | # - 99.99 41 | 42 | galaxy_tags: [] 43 | # List tags for your role here, one per line. A tag is a keyword that describes 44 | # and categorizes the role. Users find roles by searching for tags. Be sure to 45 | # remove the '[]' above, if you add tags to this list. 46 | # 47 | # NOTE: A tag is limited to a single word comprised of alphanumeric characters. 48 | # Maximum 20 tags per role. 49 | 50 | dependencies: [] 51 | # List your role dependencies here, one per line. Be sure to remove the '[]' above, 52 | # if you add dependencies to this list. 53 | -------------------------------------------------------------------------------- /roles/backend-dropbox/meta/main.yml: -------------------------------------------------------------------------------- 1 | galaxy_info: 2 | author: your name 3 | description: your role description 4 | company: your company (optional) 5 | 6 | # If the issue tracker for your role is not on github, uncomment the 7 | # next line and provide a value 8 | # issue_tracker_url: http://example.com/issue/tracker 9 | 10 | # Choose a valid license ID from https://spdx.org - some suggested licenses: 11 | # - BSD-3-Clause (default) 12 | # - MIT 13 | # - GPL-2.0-or-later 14 | # - GPL-3.0-only 15 | # - Apache-2.0 16 | # - CC-BY-4.0 17 | license: license (GPL-2.0-or-later, MIT, etc) 18 | 19 | min_ansible_version: 2.1 20 | 21 | # If this a Container Enabled role, provide the minimum Ansible Container version. 22 | # min_ansible_container_version: 23 | 24 | # 25 | # Provide a list of supported platforms, and for each platform a list of versions. 26 | # If you don't wish to enumerate all versions for a particular platform, use 'all'. 27 | # To view available platforms and versions (or releases), visit: 28 | # https://galaxy.ansible.com/api/v1/platforms/ 29 | # 30 | # platforms: 31 | # - name: Fedora 32 | # versions: 33 | # - all 34 | # - 25 35 | # - name: SomePlatform 36 | # versions: 37 | # - all 38 | # - 1.0 39 | # - 7 40 | # - 99.99 41 | 42 | galaxy_tags: [] 43 | # List tags for your role here, one per line. A tag is a keyword that describes 44 | # and categorizes the role. Users find roles by searching for tags. Be sure to 45 | # remove the '[]' above, if you add tags to this list. 46 | # 47 | # NOTE: A tag is limited to a single word comprised of alphanumeric characters. 48 | # Maximum 20 tags per role. 49 | 50 | dependencies: [] 51 | # List your role dependencies here, one per line. Be sure to remove the '[]' above, 52 | # if you add dependencies to this list. 53 | -------------------------------------------------------------------------------- /roles/backend-gophish/meta/main.yml: -------------------------------------------------------------------------------- 1 | galaxy_info: 2 | author: your name 3 | description: your role description 4 | company: your company (optional) 5 | 6 | # If the issue tracker for your role is not on github, uncomment the 7 | # next line and provide a value 8 | # issue_tracker_url: http://example.com/issue/tracker 9 | 10 | # Choose a valid license ID from https://spdx.org - some suggested licenses: 11 | # - BSD-3-Clause (default) 12 | # - MIT 13 | # - GPL-2.0-or-later 14 | # - GPL-3.0-only 15 | # - Apache-2.0 16 | # - CC-BY-4.0 17 | license: license (GPL-2.0-or-later, MIT, etc) 18 | 19 | min_ansible_version: 2.1 20 | 21 | # If this a Container Enabled role, provide the minimum Ansible Container version. 22 | # min_ansible_container_version: 23 | 24 | # 25 | # Provide a list of supported platforms, and for each platform a list of versions. 26 | # If you don't wish to enumerate all versions for a particular platform, use 'all'. 27 | # To view available platforms and versions (or releases), visit: 28 | # https://galaxy.ansible.com/api/v1/platforms/ 29 | # 30 | # platforms: 31 | # - name: Fedora 32 | # versions: 33 | # - all 34 | # - 25 35 | # - name: SomePlatform 36 | # versions: 37 | # - all 38 | # - 1.0 39 | # - 7 40 | # - 99.99 41 | 42 | galaxy_tags: [] 43 | # List tags for your role here, one per line. A tag is a keyword that describes 44 | # and categorizes the role. Users find roles by searching for tags. Be sure to 45 | # remove the '[]' above, if you add tags to this list. 46 | # 47 | # NOTE: A tag is limited to a single word comprised of alphanumeric characters. 48 | # Maximum 20 tags per role. 49 | 50 | dependencies: [] 51 | # List your role dependencies here, one per line. Be sure to remove the '[]' above, 52 | # if you add dependencies to this list. 53 | -------------------------------------------------------------------------------- /roles/backend-osint/meta/main.yml: -------------------------------------------------------------------------------- 1 | galaxy_info: 2 | author: your name 3 | description: your role description 4 | company: your company (optional) 5 | 6 | # If the issue tracker for your role is not on github, uncomment the 7 | # next line and provide a value 8 | # issue_tracker_url: http://example.com/issue/tracker 9 | 10 | # Choose a valid license ID from https://spdx.org - some suggested licenses: 11 | # - BSD-3-Clause (default) 12 | # - MIT 13 | # - GPL-2.0-or-later 14 | # - GPL-3.0-only 15 | # - Apache-2.0 16 | # - CC-BY-4.0 17 | license: license (GPL-2.0-or-later, MIT, etc) 18 | 19 | min_ansible_version: 2.1 20 | 21 | # If this a Container Enabled role, provide the minimum Ansible Container version. 22 | # min_ansible_container_version: 23 | 24 | # 25 | # Provide a list of supported platforms, and for each platform a list of versions. 26 | # If you don't wish to enumerate all versions for a particular platform, use 'all'. 27 | # To view available platforms and versions (or releases), visit: 28 | # https://galaxy.ansible.com/api/v1/platforms/ 29 | # 30 | # platforms: 31 | # - name: Fedora 32 | # versions: 33 | # - all 34 | # - 25 35 | # - name: SomePlatform 36 | # versions: 37 | # - all 38 | # - 1.0 39 | # - 7 40 | # - 99.99 41 | 42 | galaxy_tags: [] 43 | # List tags for your role here, one per line. A tag is a keyword that describes 44 | # and categorizes the role. Users find roles by searching for tags. Be sure to 45 | # remove the '[]' above, if you add tags to this list. 46 | # 47 | # NOTE: A tag is limited to a single word comprised of alphanumeric characters. 48 | # Maximum 20 tags per role. 49 | 50 | dependencies: [] 51 | # List your role dependencies here, one per line. Be sure to remove the '[]' above, 52 | # if you add dependencies to this list. 53 | -------------------------------------------------------------------------------- /roles/backend-cobalt-strike/meta/main.yml: -------------------------------------------------------------------------------- 1 | galaxy_info: 2 | author: your name 3 | description: your role description 4 | company: your company (optional) 5 | 6 | # If the issue tracker for your role is not on github, uncomment the 7 | # next line and provide a value 8 | # issue_tracker_url: http://example.com/issue/tracker 9 | 10 | # Choose a valid license ID from https://spdx.org - some suggested licenses: 11 | # - BSD-3-Clause (default) 12 | # - MIT 13 | # - GPL-2.0-or-later 14 | # - GPL-3.0-only 15 | # - Apache-2.0 16 | # - CC-BY-4.0 17 | license: license (GPL-2.0-or-later, MIT, etc) 18 | 19 | min_ansible_version: 2.1 20 | 21 | # If this a Container Enabled role, provide the minimum Ansible Container version. 22 | # min_ansible_container_version: 23 | 24 | # 25 | # Provide a list of supported platforms, and for each platform a list of versions. 26 | # If you don't wish to enumerate all versions for a particular platform, use 'all'. 27 | # To view available platforms and versions (or releases), visit: 28 | # https://galaxy.ansible.com/api/v1/platforms/ 29 | # 30 | # platforms: 31 | # - name: Fedora 32 | # versions: 33 | # - all 34 | # - 25 35 | # - name: SomePlatform 36 | # versions: 37 | # - all 38 | # - 1.0 39 | # - 7 40 | # - 99.99 41 | 42 | galaxy_tags: [] 43 | # List tags for your role here, one per line. A tag is a keyword that describes 44 | # and categorizes the role. Users find roles by searching for tags. Be sure to 45 | # remove the '[]' above, if you add tags to this list. 46 | # 47 | # NOTE: A tag is limited to a single word comprised of alphanumeric characters. 48 | # Maximum 20 tags per role. 49 | 50 | # List your role dependencies here, one per line. Be sure to remove the '[]' above, 51 | # if you add dependencies to this list. 52 | dependencies: [] 53 | -------------------------------------------------------------------------------- /roles/backend-manual-phish/meta/main.yml: -------------------------------------------------------------------------------- 1 | galaxy_info: 2 | author: your name 3 | description: your role description 4 | company: your company (optional) 5 | 6 | # If the issue tracker for your role is not on github, uncomment the 7 | # next line and provide a value 8 | # issue_tracker_url: http://example.com/issue/tracker 9 | 10 | # Choose a valid license ID from https://spdx.org - some suggested licenses: 11 | # - BSD-3-Clause (default) 12 | # - MIT 13 | # - GPL-2.0-or-later 14 | # - GPL-3.0-only 15 | # - Apache-2.0 16 | # - CC-BY-4.0 17 | license: license (GPL-2.0-or-later, MIT, etc) 18 | 19 | min_ansible_version: 2.1 20 | 21 | # If this a Container Enabled role, provide the minimum Ansible Container version. 22 | # min_ansible_container_version: 23 | 24 | # 25 | # Provide a list of supported platforms, and for each platform a list of versions. 26 | # If you don't wish to enumerate all versions for a particular platform, use 'all'. 27 | # To view available platforms and versions (or releases), visit: 28 | # https://galaxy.ansible.com/api/v1/platforms/ 29 | # 30 | # platforms: 31 | # - name: Fedora 32 | # versions: 33 | # - all 34 | # - 25 35 | # - name: SomePlatform 36 | # versions: 37 | # - all 38 | # - 1.0 39 | # - 7 40 | # - 99.99 41 | 42 | galaxy_tags: [] 43 | # List tags for your role here, one per line. A tag is a keyword that describes 44 | # and categorizes the role. Users find roles by searching for tags. Be sure to 45 | # remove the '[]' above, if you add tags to this list. 46 | # 47 | # NOTE: A tag is limited to a single word comprised of alphanumeric characters. 48 | # Maximum 20 tags per role. 49 | 50 | dependencies: [] 51 | # List your role dependencies here, one per line. Be sure to remove the '[]' above, 52 | # if you add dependencies to this list. 53 | -------------------------------------------------------------------------------- /roles/backend-webcatcher/meta/main.yml: -------------------------------------------------------------------------------- 1 | galaxy_info: 2 | author: your name 3 | description: your role description 4 | company: your company (optional) 5 | 6 | # If the issue tracker for your role is not on github, uncomment the 7 | # next line and provide a value 8 | # issue_tracker_url: http://example.com/issue/tracker 9 | 10 | # Choose a valid license ID from https://spdx.org - some suggested licenses: 11 | # - BSD-3-Clause (default) 12 | # - MIT 13 | # - GPL-2.0-or-later 14 | # - GPL-3.0-only 15 | # - Apache-2.0 16 | # - CC-BY-4.0 17 | license: license (GPL-2.0-or-later, MIT, etc) 18 | 19 | min_ansible_version: 2.1 20 | 21 | # If this a Container Enabled role, provide the minimum Ansible Container version. 22 | # min_ansible_container_version: 23 | 24 | # 25 | # Provide a list of supported platforms, and for each platform a list of versions. 26 | # If you don't wish to enumerate all versions for a particular platform, use 'all'. 27 | # To view available platforms and versions (or releases), visit: 28 | # https://galaxy.ansible.com/api/v1/platforms/ 29 | # 30 | # platforms: 31 | # - name: Fedora 32 | # versions: 33 | # - all 34 | # - 25 35 | # - name: SomePlatform 36 | # versions: 37 | # - all 38 | # - 1.0 39 | # - 7 40 | # - 99.99 41 | 42 | galaxy_tags: [] 43 | # List tags for your role here, one per line. A tag is a keyword that describes 44 | # and categorizes the role. Users find roles by searching for tags. Be sure to 45 | # remove the '[]' above, if you add tags to this list. 46 | # 47 | # NOTE: A tag is limited to a single word comprised of alphanumeric characters. 48 | # Maximum 20 tags per role. 49 | 50 | dependencies: [] 51 | # List your role dependencies here, one per line. Be sure to remove the '[]' above, 52 | # if you add dependencies to this list. 53 | -------------------------------------------------------------------------------- /tools/list-tags.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import os.path 3 | 4 | import yaml 5 | 6 | 7 | class BColors: 8 | HEADER = '\033[95m' 9 | OKBLUE = '\033[94m' 10 | OKCYAN = '\033[96m' 11 | OKGREEN = '\033[92m' 12 | WARNING = '\033[93m' 13 | FAIL = '\033[91m' 14 | ENDC = '\033[0m' 15 | BOLD = '\033[1m' 16 | UNDERLINE = '\033[4m' 17 | 18 | 19 | def parse_yaml(filename): 20 | """ 21 | Find the playbook and safely load the YAML 22 | """ 23 | if not os.path.exists(filename): 24 | fix_path = os.path.join( 25 | os.path.dirname(__file__), 26 | "..", 27 | filename 28 | ) 29 | with open(fix_path, 'r') as stream: 30 | return yaml.safe_load(stream) 31 | with open(filename, 'r') as stream: 32 | return yaml.safe_load(stream) 33 | 34 | 35 | def print_tags(tag_list): 36 | """ 37 | Print and colorize tags 38 | """ 39 | for tag in tag_list: 40 | print('\n' + BColors.OKGREEN + tag + BColors.ENDC + ":") 41 | for host in tag_list[tag]['hosts']: 42 | print(str(tag_list[tag]['hosts'][host]) + ' on ' + BColors.OKCYAN + host + BColors.ENDC) 43 | 44 | 45 | def parse_plays(playbook_yaml): 46 | """ 47 | Parse the entries from the playbook file 48 | """ 49 | tag_list = {} 50 | for item in playbook_yaml: 51 | for tag in item['tags']: 52 | if tag not in tag_list: 53 | tag_list[tag] = {} 54 | tag_list[tag]['hosts'] = {} 55 | tag_list[tag]['hosts'][item['hosts']] = item['roles'] 56 | return tag_list 57 | 58 | 59 | def main(): 60 | """ 61 | Start the playbook parsing 62 | """ 63 | playbook_yaml = parse_yaml("playbook.yml") 64 | tag_list = parse_plays(playbook_yaml) 65 | print_tags(tag_list) 66 | 67 | 68 | if __name__ == '__main__': 69 | main() 70 | -------------------------------------------------------------------------------- /tools/util/infra_logger.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # encoding: utf-8 3 | 4 | """ 5 | This module provides generic logging functionality for the infra deployment 6 | Use in your submodule in the following fashion: 7 | 8 | from infra_logger import initiate_logger 9 | logger = initiate_logger() 10 | logger.error("MESSAGE") 11 | """ 12 | 13 | import logging 14 | import os 15 | from pathlib import Path 16 | 17 | # set pwd to current working directory 18 | PWD = Path(os.getcwd()) 19 | 20 | class CustomFormatter(logging.Formatter): 21 | """ Initiates the custom format for our log messages""" 22 | bold_grey = "\x1b[38;1m" 23 | bold_yellow = "\x1b[33;1m" 24 | bold_magenta = "\x1b[35;1m" 25 | bold_red = "\x1b[31;1m" 26 | bold_cyan = "\x1b[36;1m" 27 | reset = "\x1b[0m" 28 | message_format = "(%(filename)s) %(message)s" 29 | 30 | FORMATS = { 31 | logging.DEBUG: f"{bold_grey}DEBUG:{reset} {message_format}", 32 | logging.INFO: f"{bold_cyan}INFO:{reset} {message_format}", 33 | logging.WARNING: f"{bold_yellow}WARNING:{reset} {message_format}", 34 | logging.ERROR: f"{bold_red}ERROR:{reset} {message_format}", 35 | logging.CRITICAL: f"{bold_magenta}CRITICAL:{reset} {message_format}" 36 | } 37 | 38 | def format(self, record): 39 | log_fmt = self.FORMATS.get(record.levelno) 40 | formatter = logging.Formatter(log_fmt) 41 | return formatter.format(record) 42 | 43 | 44 | def initiate_logger(name): 45 | "Initiates the logger. This should be called by the submodule" 46 | 47 | # create logger with the name of the module calling it 48 | logger = logging.getLogger(name) 49 | logger.setLevel(logging.DEBUG) 50 | 51 | # create console handler with a higher log level 52 | console_handler = logging.StreamHandler() 53 | console_handler.setLevel(logging.DEBUG) 54 | console_handler.setFormatter(CustomFormatter()) 55 | logger.addHandler(console_handler) 56 | 57 | return logger 58 | -------------------------------------------------------------------------------- /roles/backend-gophish/files/gophish/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:18.04 2 | LABEL maintainer="Stefan Vlems " 3 | 4 | # Install required packages 5 | ARG DEBIAN_FRONTEND=noninteractive 6 | RUN apt-get -qq update && apt-get -qq install -y \ 7 | zip \ 8 | git \ 9 | curl \ 10 | wget \ 11 | openvpn \ 12 | vim \ 13 | dnsutils \ 14 | tcpdump \ 15 | netcat \ 16 | dnsutils \ 17 | ipset \ 18 | iputils-ping \ 19 | syslog-ng \ 20 | python3 \ 21 | net-tools \ 22 | curl \ 23 | nano \ 24 | bridge-utils \ 25 | python3-pip \ 26 | > /dev/null 27 | 28 | RUN python3 -m pip install --upgrade requests 29 | 30 | # Set and create the gophish installation directory 31 | ARG GOPHISHDIR 32 | ARG GOPHISHVERSION 33 | ARG CONTACT_EMAIL 34 | 35 | ENV GOPHISHDIR=${GOPHISHDIR} 36 | ENV GOPHISHVERSION=${GOPHISHVERSION} 37 | ENV CONTACT_EMAIL=${CONTACT_EMAIL} 38 | 39 | RUN mkdir -p ${GOPHISHDIR}/tmp 2>/dev/null 40 | 41 | # Run the installation shell script 42 | COPY files/gophish_goget.sh /tmp/goget.sh 43 | RUN /bin/sh /tmp/goget.sh $GOPHISHVERSION $GOPHISHDIR 44 | 45 | # Fix bugs with rsyslog and Docker 46 | RUN echo "#!/bin/sh\nexit 0" > /usr/sbin/policy-rc.d 47 | 48 | # Copy the OpenVPN config and change the remote to the relay VPS 49 | # Also ensure $vpn is available inside the container 50 | ARG VPN 51 | ENV VPN=${VPN} 52 | 53 | 54 | COPY $VPN /root/$VPN 55 | # Create a GoPhish service 56 | # COPY files/gophish.service /etc/init.d/gophish 57 | # RUN chmod +x /etc/init.d/gophish 58 | 59 | # Set-up the GoPhish config 60 | COPY files/gophish-config.json $GOPHISHDIR/config.json 61 | RUN sed -i "s/\"contact_address\": \"\"/\"contact_address\": \"$CONTACT_EMAIL\"/g" $GOPHISHDIR/config.json 62 | COPY files/gophish_api.py $GOPHISHDIR/gophish_api.py 63 | 64 | # Copy the entrypoint and execute the container 65 | COPY docker-entrypoint.sh /docker-entrypoint.sh 66 | RUN chmod +x /docker-entrypoint.sh 67 | ENTRYPOINT ["/docker-entrypoint.sh"] 68 | -------------------------------------------------------------------------------- /roles/relay-nginx/meta/main.yml: -------------------------------------------------------------------------------- 1 | galaxy_info: 2 | author: your name 3 | description: your description 4 | company: your company (optional) 5 | 6 | # If the issue tracker for your role is not on github, uncomment the 7 | # next line and provide a value 8 | # issue_tracker_url: http://example.com/issue/tracker 9 | 10 | # Some suggested licenses: 11 | # - BSD (default) 12 | # - MIT 13 | # - GPLv2 14 | # - GPLv3 15 | # - Apache 16 | # - CC-BY 17 | license: license (GPLv2, CC-BY, etc) 18 | 19 | min_ansible_version: 1.2 20 | 21 | # If this a Container Enabled role, provide the minimum Ansible Container version. 22 | # min_ansible_container_version: 23 | 24 | # Optionally specify the branch Galaxy will use when accessing the GitHub 25 | # repo for this role. During role install, if no tags are available, 26 | # Galaxy will use this branch. During import Galaxy will access files on 27 | # this branch. If Travis integration is configured, only notifications for this 28 | # branch will be accepted. Otherwise, in all cases, the repo's default branch 29 | # (usually master) will be used. 30 | #github_branch: 31 | 32 | # 33 | # platforms is a list of platforms, and each platform has a name and a list of versions. 34 | # 35 | # platforms: 36 | # - name: Fedora 37 | # versions: 38 | # - all 39 | # - 25 40 | # - name: SomePlatform 41 | # versions: 42 | # - all 43 | # - 1.0 44 | # - 7 45 | # - 99.99 46 | 47 | galaxy_tags: [] 48 | # List tags for your role here, one per line. A tag is a keyword that describes 49 | # and categorizes the role. Users find roles by searching for tags. Be sure to 50 | # remove the '[]' above, if you add tags to this list. 51 | # 52 | # NOTE: A tag is limited to a single word comprised of alphanumeric characters. 53 | # Maximum 20 tags per role. 54 | 55 | dependencies: [] 56 | # List your role dependencies here, one per line. Be sure to remove the '[]' above, 57 | # if you add dependencies to this list. 58 | -------------------------------------------------------------------------------- /roles/backend-manual-phish/files/manual-phish/docker-entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | red=$(tput -T xterm-256color setaf 1) 4 | green=$(tput -T xterm-256color setaf 2) 5 | orange=$(tput -T xterm-256color setaf 3) 6 | blue=$(tput -T xterm-256color setaf 4) 7 | darkgreen=$(tput -T xterm-256color setaf 6) 8 | white=$(tput -T xterm-256color setaf 7) 9 | reset=$(tput -T xterm-256color sgr0) 10 | 11 | # Start the VPN (if applicable) and renew the certificate 12 | if [ -n ${VPN} ]; then 13 | mkdir -p /var/log/openvpn 14 | openvpn --config "/root/${VPN}" --log /var/log/openvpn/connection.log & 15 | sleep 4 16 | 17 | # Display the IP address 18 | IPADDR=$(ip addr show | grep "global tun0" | cut -f6 -d " ") 19 | cat <<-EOF 20 | ---------------- 21 | ${blue}[*]${reset} Starting the VPN 22 | ${blue}[*]${reset} Connecting to: ${green}${RELAY_HOST}${reset} - Project ${green}${CODENAME}${reset} 23 | ${blue}[*]${reset} IP address of VPN interface: ${green}${IPADDR}${reset} 24 | ---------------- 25 | EOF 26 | else 27 | ipaddr=$(ip addr show | grep "global eth0" | cut -f6 -d " ") 28 | cat <<-EOF 29 | -------------------------- 30 | ${orange}[!]${reset} ${red}DOCKER STARTED WITHOUT VPN${reset} 31 | ${orange}[!]${reset} To change this, set the VPN_CONFIG variable in the .env file accordingly 32 | ${orange}[!]${reset} IP address: ${IPADDR} 33 | -------------------------- 34 | EOF 35 | fi 36 | 37 | echo "Configuring access" 38 | touch /var/log/phish-log.log 39 | mkdir -p /home/mutt/Mail/INBOX 40 | chown mutt:mutt /var/log/phish-log.log 41 | chown -R mutt:mutt /home/mutt/ 42 | echo "su mutt" >> /root/.bashrc 43 | 44 | su mutt 45 | echo "Configuring Mutt" 46 | 47 | cd /home/mutt; 48 | chmod +x change-sender-name.sh 49 | ./change-sender-name.sh $REAL_NAME $USER_NAME 50 | sed -i 's/PHISH_DOMAIN/'"$DOMAIN_NAME"/ /home/mutt/.muttrc 51 | sed -i 's/PHISH_DOMAIN/'"$DOMAIN_NAME/" /home/mutt/.msmtprc 52 | echo 'echo "' >>/home/mutt/.bashrc 53 | cat bash-instructions >>/home/mutt/.bashrc 54 | echo '"' >>/home/mutt/.bashrc 55 | 56 | tail -f /root/$VPN 57 | -------------------------------------------------------------------------------- /roles/relay-cobalt-strike/meta/main.yml: -------------------------------------------------------------------------------- 1 | galaxy_info: 2 | author: your name 3 | description: your description 4 | company: your company (optional) 5 | 6 | # If the issue tracker for your role is not on github, uncomment the 7 | # next line and provide a value 8 | # issue_tracker_url: http://example.com/issue/tracker 9 | 10 | # Some suggested licenses: 11 | # - BSD (default) 12 | # - MIT 13 | # - GPLv2 14 | # - GPLv3 15 | # - Apache 16 | # - CC-BY 17 | license: license (GPLv2, CC-BY, etc) 18 | 19 | min_ansible_version: 1.2 20 | 21 | # If this a Container Enabled role, provide the minimum Ansible Container version. 22 | # min_ansible_container_version: 23 | 24 | # Optionally specify the branch Galaxy will use when accessing the GitHub 25 | # repo for this role. During role install, if no tags are available, 26 | # Galaxy will use this branch. During import Galaxy will access files on 27 | # this branch. If Travis integration is configured, only notifications for this 28 | # branch will be accepted. Otherwise, in all cases, the repo's default branch 29 | # (usually master) will be used. 30 | #github_branch: 31 | 32 | # 33 | # platforms is a list of platforms, and each platform has a name and a list of versions. 34 | # 35 | # platforms: 36 | # - name: Fedora 37 | # versions: 38 | # - all 39 | # - 25 40 | # - name: SomePlatform 41 | # versions: 42 | # - all 43 | # - 1.0 44 | # - 7 45 | # - 99.99 46 | 47 | galaxy_tags: [] 48 | # List tags for your role here, one per line. A tag is a keyword that describes 49 | # and categorizes the role. Users find roles by searching for tags. Be sure to 50 | # remove the '[]' above, if you add tags to this list. 51 | # 52 | # NOTE: A tag is limited to a single word comprised of alphanumeric characters. 53 | # Maximum 20 tags per role. 54 | 55 | dependencies: [] 56 | # List your role dependencies here, one per line. Be sure to remove the '[]' above, 57 | # if you add dependencies to this list. 58 | -------------------------------------------------------------------------------- /roles/backend-gophish/files/gophish/docker-entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | touch /var/log/gophish-log.log 4 | 5 | red=$(tput -T xterm-256color setaf 1) 6 | green=$(tput -T xterm-256color setaf 2) 7 | orange=$(tput -T xterm-256color setaf 3) 8 | blue=$(tput -T xterm-256color setaf 4) 9 | darkgreen=$(tput -T xterm-256color setaf 6) 10 | white=$(tput -T xterm-256color setaf 7) 11 | reset=$(tput -T xterm-256color sgr0) 12 | 13 | # Start the VPN (if applicable) and renew the certificate 14 | if [ -n ${VPN} ]; then 15 | mkdir -p /var/log/openvpn 16 | openvpn --config "/root/${VPN}" --log /var/log/openvpn/connection.log & 17 | sleep 4 18 | 19 | # Display the IP address 20 | IPADDR=$(ip addr show | grep "global tun0" | cut -f6 -d " ") 21 | cat <<-EOF 22 | ---------------- 23 | ${blue}[*]${reset} Starting the VPN 24 | ${blue}[*]${reset} Connecting to: ${green}${RELAY_HOST}${reset} - Project ${green}${CODENAME}${reset} 25 | ${blue}[*]${reset} IP address of VPN interface: ${green}${IPADDR}${reset} 26 | ---------------- 27 | EOF 28 | else 29 | ipaddr=$(ip addr show | grep "global eth0" | cut -f6 -d " ") 30 | cat <<-EOF 31 | -------------------------- 32 | ${orange}[!]${reset} ${red}DOCKER STARTED WITHOUT VPN${reset} 33 | ${orange}[!]${reset} To change this, set the VPN_CONFIG variable in the .env file accordingly 34 | ${orange}[!]${reset} IP address: ${IPADDR} 35 | -------------------------- 36 | EOF 37 | fi 38 | 39 | echo "Starting goPhish version ${GOPHISHVERSION}" 40 | 41 | export gf_add="python3 ${GOPHISHDIR}/gophish_api.py -H ${SMTP_HOST}" 42 | 43 | if [ -n ${SMTP_USER} ]; then 44 | gf_add="$gf_add -u ${SMTP_USER} -p ${SMTP_PASSWORD}" 45 | fi 46 | 47 | if [ -n ${SMTP_PORT} ]; then 48 | gf_add="$gf_add -P ${SMTP_PORT}" 49 | fi 50 | 51 | if [ -n ${SMTP_FROMS} ]; then 52 | gf_add="$gf_add -f ${SMTP_FROMS}" 53 | fi 54 | 55 | if [ -n ${GOPHISH_INITIAL_ADMIN_API_TOKEN} ]; then 56 | gf_add="$gf_add -k ${GOPHISH_INITIAL_ADMIN_API_TOKEN}" 57 | fi 58 | 59 | echo "Create users command: $gf_add" 60 | bash -c "sleep 10 ; $gf_add" &>/dev/null & 61 | 62 | exec sh -c "cd ${GOPHISHDIR} && ./gophish" 63 | -------------------------------------------------------------------------------- /roles/backend-osint/tasks/osint-setup.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: "SpiderFoot: Clone the git repository" 3 | ansible.builtin.git: 4 | repo: 'https://github.com/smicallef/spiderfoot.git' 5 | dest: "{{ toolkit_directory }}/spiderfoot" 6 | 7 | - name: "SpiderFoot: Build Docker image (This can take 5+ Minutes, do not despair)" 8 | become: yes 9 | community.docker.docker_image: 10 | build: 11 | dockerfile: Dockerfile 12 | path: "{{ toolkit_directory }}/spiderfoot" 13 | rm: yes 14 | debug: yes 15 | name: spiderfoot 16 | push: no 17 | source: build 18 | state: present 19 | tag: latest 20 | 21 | - name: "SpiderFoot: Create Docker volume for storing data" 22 | become: yes 23 | community.docker.docker_volume: 24 | volume_name: spiderfoot 25 | state: present 26 | recreate: never 27 | 28 | - name: "SpiderFoot: Start Docker container" 29 | become: yes 30 | community.docker.docker_container: 31 | container_default_behavior: no_defaults 32 | # TODO: Set a limit on CPU and memory to prevent max resources 33 | #cpu_period: 34 | #cpu_quota: 35 | #cpu_shares: 36 | cpus: 0.75 37 | #cpuset_cpus: 38 | #cpuset_mems: 39 | debug: yes 40 | hostname: spiderfoot 41 | image: spiderfoot:latest 42 | log_driver: journald 43 | memory: 2G # out of 4G 44 | name: spiderfoot 45 | network_mode: bridge 46 | output_logs: yes 47 | privileged: no 48 | published_ports: 49 | - 127.0.0.1:5001:5001 50 | pull: no # Image should be built locally and will not be pushed 51 | restart_policy: unless-stopped 52 | state: started 53 | volumes: 54 | # Store userdata in a named volume defined above 55 | # Required to be able to save spiderfoot.db in case of recreated container 56 | - "spiderfoot:/home/spiderfoot" 57 | 58 | - name: "SpiderFoot: Create symbolic link to Docker volume in {{ toolkit_directory }}/spiderfoot-userdata" 59 | become: yes 60 | ansible.builtin.file: 61 | src: "/var/lib/docker/volumes/spiderfoot/_data" 62 | dest: "{{ toolkit_directory }}/spiderfoot-userdata" 63 | state: link 64 | -------------------------------------------------------------------------------- /roles/backend-cobalt-strike/files/docker/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.7" 2 | 3 | services: 4 | teamserver: 5 | build: 6 | context: . 7 | args: 8 | LICENSE_KEY: ${CS_LICENSE} 9 | image: cobaltstrike:latest 10 | container_name: teamserver 11 | hostname: teamserver 12 | environment: 13 | - PASSWORD=${TEAMSERVER_PASSWORD} 14 | - RELAYVPS=${RELAY_HOST} 15 | - VPN=${VPN_CONFIG} 16 | - LICENSE=${CS_LICENSE} 17 | - C2_PROFILE=${MALLEABLE_PROFILE} 18 | - CODENAME=${CODE_NAME} 19 | ports: 20 | - "50050:50050" 21 | - "51000-51020:51000-51020" 22 | - "22" 23 | - "53" 24 | - "80" 25 | - "135" 26 | - "138" 27 | - "443" 28 | - "445" 29 | - "8080" 30 | - "8443" 31 | volumes: 32 | - profiles:/opt/cobaltstrike/c2-profiles 33 | - datamodel:/opt/cobaltstrike/data 34 | - logs:/opt/cobaltstrike/logs 35 | cap_add: 36 | - NET_ADMIN 37 | devices: 38 | - /dev/net/tun 39 | networks: 40 | cobaltstrike: 41 | restart: unless-stopped 42 | command: ["./teamserver", "${RELAY_HOST}", "${TEAMSERVER_PASSWORD}", "/opt/cobaltstrike/c2-profiles/${MALLEABLE_PROFILE}"] 43 | healthcheck: # Search for C382 (hex of 50050) in the listening ports list 44 | test: ["CMD", "grep", "C382", "/proc/net/tcp"] 45 | interval: 30s 46 | timeout: 1s 47 | retries: 15 48 | start_period: 30s 49 | 50 | bot: 51 | image: cobaltstrike:latest 52 | container_name: bot 53 | hostname: bot 54 | environment: 55 | - PASSWORD=${TEAMSERVER_PASSWORD} 56 | - LICENSE=${CS_LICENSE} 57 | - DISABLE_VPN=true 58 | volumes: 59 | - scripts:/opt/cobaltstrike/aggressor-scripts 60 | depends_on: 61 | - teamserver 62 | networks: 63 | cobaltstrike: 64 | restart: unless-stopped 65 | command: ["./agscript", "teamserver", "50050", "bot", "${TEAMSERVER_PASSWORD}", "/opt/cobaltstrike/aggressor-scripts/listener.service.cna"] 66 | 67 | volumes: 68 | scripts: 69 | profiles: 70 | datamodel: 71 | logs: 72 | 73 | networks: 74 | cobaltstrike: 75 | name: cobaltstrike 76 | driver: bridge 77 | -------------------------------------------------------------------------------- /roles/backend-gophish/tasks/gophish-setup.yml: -------------------------------------------------------------------------------- 1 | 2 | - name: "GoPhish: Creating {{ gophish_docker_path }}{{ relay_host }}/ directory" 3 | become: yes 4 | ansible.builtin.file: 5 | path: "{{ gophish_docker_path }}{{ relay_host }}/" 6 | state: directory 7 | mode: 0755 8 | 9 | - name: "GoPhish: Copy the GoPhish docker container" 10 | become: yes 11 | ansible.builtin.copy: 12 | src: files/gophish/ 13 | dest: "{{ gophish_docker_path }}{{ relay_host }}/" 14 | 15 | - name: "GoPhish selecting OVPN config based on pattern {{ gophish_ovpn_pattern }}" 16 | become: yes 17 | ansible.builtin.copy: 18 | src: "{{ openvpn_client_profile_path }}{{ relay_host }}/{{ gophish_ovpn_pattern }}" 19 | dest: "{{ gophish_docker_path }}{{ relay_host }}/gophish.ovpn" 20 | remote_src: yes 21 | 22 | - name: Add Codename 23 | ansible.builtin.lineinfile: 24 | dest: "{{ gophish_docker_path }}{{ relay_host }}/.env" 25 | regexp: "^CODENAME=.*$" 26 | line: "CODENAME={{ codename }}" 27 | backrefs: yes 28 | become: yes 29 | 30 | - name: "Creating Sender addresses" 31 | ansible.builtin.set_fact: 32 | from_addresses: "{{ send_from|map('regex_replace', '$', domain_name)|list|join(',') }}" 33 | changed_when: false # Done always, so no change notification 34 | 35 | - name: "Setting Remote addresses" 36 | ansible.builtin.lineinfile: 37 | dest: "{{ gophish_docker_path }}{{ relay_host }}/.env" 38 | regexp: "^RELAY_HOST=.*$" 39 | line: "RELAY_HOST={{ relay_host_ip }}" 40 | backrefs: yes 41 | become: yes 42 | 43 | - name: "GoPhish setting environment variables" 44 | become: yes 45 | ansible.builtin.lineinfile: 46 | dest: "{{ gophish_docker_path }}{{ relay_host }}/.env" 47 | regexp: "^{{ item.key }}=.*$" 48 | line: "{{ item.key }}={{ item.value }}" 49 | backrefs: yes 50 | with_dict: "{{ gophish_config }}" 51 | 52 | - name: "GoPhish Building image (This can take 5+ minutes, do not despair)" 53 | become: yes 54 | ansible.builtin.shell: "cd {{ gophish_docker_path }}{{ relay_host }}/; docker-compose build" 55 | 56 | - name: "GoPhish Starting GoPhish" 57 | become: yes 58 | ansible.builtin.shell: "cd {{ gophish_docker_path }}{{ relay_host }}/; docker-compose up --detach" 59 | -------------------------------------------------------------------------------- /roles/relay-phishing/tasks/os-prep.yml: -------------------------------------------------------------------------------- 1 | #- name: Ensure localisation files for '{{ config_system_locale }}' are available 2 | # locale_gen: 3 | # name: "{{ config_system_locale }}" 4 | # state: present 5 | # 6 | #- name: Ensure language files for '{{ config_system_language }}' are available 7 | # locale_gen: 8 | # name: "{{ config_system_language }}" 9 | # state: present 10 | # 11 | #- name: Get current locale and language configuration 12 | # command: localectl status 13 | # register: locale_status 14 | # changed_when: false 15 | # 16 | #- name: Parse 'LANG' from current locale and language configuration 17 | # set_fact: 18 | # locale_lang: "{{ locale_status.stdout | regex_search('LANG=([^\n]+)', '\\1') | first }}" 19 | # 20 | #- name: Parse 'LANGUAGE' from current locale and language configuration 21 | # set_fact: 22 | # locale_language: "{{ locale_status.stdout | regex_search('LANGUAGE=([^\n]+)', '\\1') | default([locale_lang], true) | first }}" 23 | # 24 | #- name: Configure locale to '{{ config_system_locale }}' and language to '{{ config_system_language }}' 25 | # become: yes 26 | # command: localectl set-locale LANG={{ config_system_locale }} LANGUAGE={{ config_system_language }} 27 | # changed_when: locale_lang != config_system_locale or locale_language != config_system_language 28 | 29 | - name: "APT: Uninstall exim if present on the system" 30 | become: yes 31 | ansible.builtin.apt: 32 | name: 33 | - exim4 34 | - exim4-base 35 | - exim4-config 36 | - exim4-daemon-light 37 | state: absent 38 | update_cache: true 39 | 40 | - name: "APT: Install Git and mailserver packages" 41 | become: yes 42 | ansible.builtin.apt: 43 | name: 44 | - python3 45 | - git 46 | - dovecot-imapd 47 | - dovecot-lmtpd 48 | - postfix 49 | - postgrey 50 | - postfix-policyd-spf-python 51 | - opendkim 52 | - opendkim-tools 53 | - opendmarc 54 | - mailutils 55 | - certbot 56 | state: present 57 | update_cache: true 58 | 59 | - name: "Hostname: Add {{ domain_name }} to /etc/hosts" 60 | become: yes 61 | ansible.builtin.lineinfile: 62 | dest: /etc/hosts 63 | line: "127.0.0.1 localhost {{ domain_name }}" 64 | state: present 65 | -------------------------------------------------------------------------------- /roles/backend-webcatcher/files/web-catcher/src/logger.php: -------------------------------------------------------------------------------- 1 | $value) 28 | echo "$header: $value\r\n"; 29 | 30 | // If you wanted raw request data vs. parsed POST data: 31 | $postdata = file_get_contents('php://input'); 32 | if(strlen($postdata)) echo $postdata."\r\n"; 33 | 34 | // Post data / Cookies / Files 35 | if(count($_POST) || count($_COOKIE)) { 36 | ob_start(); 37 | 38 | echo "POST\n"; 39 | var_dump($_POST); 40 | 41 | echo "COOKIES\n"; 42 | var_dump($_COOKIE); 43 | 44 | echo "FILES\n"; 45 | var_dump($_FILES); 46 | 47 | $postdata = ob_get_clean(); 48 | echo str_replace("\n","\r\n",$postdata); 49 | } 50 | echo "\r\n"; 51 | 52 | // usage of random character string discourages guessing 53 | // the url if the directory is web-accessible; but, if at 54 | // all possible, make it inaccessible: 55 | file_put_contents('/var/log/requests.log',ob_get_clean(),FILE_APPEND); 56 | } 57 | 58 | // then, a simple maintenance page: 59 | ?> 60 | 61 | 62 | 63 | Some Title 64 | 65 | 66 |

67 | Add some styling here 68 |

69 | 70 | 71 | -------------------------------------------------------------------------------- /roles/backend-common/tasks/backend-hardening.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: "Allow all inbound loopback traffic" 3 | become: yes 4 | ansible.builtin.iptables: 5 | action: append 6 | chain: INPUT 7 | in_interface: lo 8 | jump: ACCEPT 9 | wait: 60 10 | notify: saveiptables 11 | register: iptables_action 12 | retries: 10 13 | until: iptables_action is success or 'Another app is currently holding the xtables lock' not in iptables_action.msg 14 | 15 | - name: "Allow already established inbound connections" 16 | become: yes 17 | ansible.builtin.iptables: 18 | chain: INPUT 19 | ctstate: ESTABLISHED,RELATED 20 | jump: ACCEPT 21 | wait: 60 22 | notify: saveiptables 23 | register: iptables_action 24 | retries: 10 25 | until: iptables_action is success or 'Another app is currently holding the xtables lock' not in iptables_action.msg 26 | 27 | - name: "Allow inbound ICMP traffic" 28 | become: yes 29 | ansible.builtin.iptables: 30 | chain: INPUT 31 | jump: ACCEPT 32 | protocol: icmp 33 | wait: 60 34 | notify: saveiptables 35 | register: iptables_action 36 | retries: 10 37 | until: iptables_action is success or 'Another app is currently holding the xtables lock' not in iptables_action.msg 38 | 39 | - name: "Allow inbound SSH traffic from Company IP space" 40 | become: yes 41 | ansible.builtin.iptables: 42 | chain: INPUT 43 | destination_port: "22" 44 | jump: ACCEPT 45 | protocol: tcp 46 | source: "{{ item }}" 47 | wait: 60 48 | with_items: "{{ company_ip_space }}" 49 | notify: saveiptables 50 | register: iptables_action 51 | retries: 10 52 | until: iptables_action is success or 'Another app is currently holding the xtables lock' not in iptables_action.msg 53 | 54 | - name: "Drop all other inbound traffic" 55 | become: yes 56 | ansible.builtin.iptables: 57 | chain: INPUT 58 | policy: DROP 59 | wait: 60 60 | notify: saveiptables 61 | register: iptables_action 62 | retries: 10 63 | until: iptables_action is success or 'Another app is currently holding the xtables lock' not in iptables_action.msg 64 | 65 | - name: "Deploy SSH server configuration from template" 66 | become: yes 67 | ansible.builtin.template: 68 | src: sshd_config.j2 69 | dest: /etc/ssh/sshd_config 70 | notify: 71 | - restart sshd 72 | -------------------------------------------------------------------------------- /roles/common-tasks/ovpn-create-client.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: "OpenVPN clients: Check if ovpn configuration exists in {{ ovpn_config_directory }}" 3 | ansible.builtin.stat: 4 | path: "{{ ovpn_config_directory }}/config.conf" 5 | register: ovpn_config 6 | 7 | - name: "Missing OpenVPN configuration. Can't create client profiles. Exiting." 8 | block: 9 | - ansible.builtin.debug: 10 | msg: "Missing OpenVPN configuration. Can't create client profiles. Exiting." 11 | 12 | - meta: end_play 13 | when: ovpn_config.stat.exists == False 14 | 15 | - name: "OpenVPN clients: Check to see if client profiles already exist in {{ ovpn_config_directory }}/clients/" 16 | ansible.builtin.stat: 17 | path: "{{ ovpn_config_directory }}/clients/{{ item }}.visz" 18 | register: existing_client_profiles 19 | with_items: "{{ client_profiles }}" 20 | ignore_errors: True 21 | 22 | - name: "OpenVPN clients: Create ovpn client profile" 23 | become: yes 24 | ansible.builtin.expect: 25 | command: "openvpn-generate client --path {{ ovpn_config_directory }}" 26 | responses: 27 | "Common Name": "{{ item.item }}" 28 | echo: yes 29 | with_items: "{{ existing_client_profiles.results }}" 30 | when: item.stat.exists == False 31 | 32 | - name: "OpenVPN clients: Convert the client profiles from visc to ovpn" 33 | become: yes 34 | ansible.builtin.command: "python3 {{ ovpn_config_directory }}/python3-convert-visc-to-ovpn.py {{ ovpn_config_directory }}/clients/{{ item.item }}.visz" 35 | with_items: "{{ existing_client_profiles.results }}" 36 | when: item.stat.exists == False 37 | 38 | - name: Create local OpenVPN client profiles directory 39 | ansible.builtin.file: 40 | path: "{{ export_path }}/client_profiles/{{ inventory_hostname }}/" 41 | state: directory 42 | recurse: yes 43 | delegate_to: localhost 44 | 45 | - name: Map remote client profiles 46 | ansible.builtin.find: 47 | paths: "{{ ovpn_config_directory }}/clients/" 48 | recurse: no 49 | patterns: "*.ovpn" 50 | register: ovpn_client_files 51 | 52 | - name: "Download the client profiles to {{ export_path }} directory" 53 | ansible.builtin.fetch: 54 | src: "{{ item.path }}" 55 | dest: "{{ export_path }}/client_profiles/{{ inventory_hostname }}/" 56 | flat: yes 57 | with_items: "{{ ovpn_client_files.files }}" 58 | -------------------------------------------------------------------------------- /tools/util/templates/configuration.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # ############################################################################# 3 | # IP Space Configuration 4 | # ############################################################################# 5 | 6 | # IP Space for allowing incoming SSH connections to the deployed infrastructure 7 | # Please set this to for example your companies outbound IP ranges 8 | \VAR{company_ip_space} 9 | 10 | 11 | # IP Space for your private C2 machines. These ranges determine what systems 12 | # are allowed to use the redirectors. 13 | \VAR{company_c2_space} 14 | 15 | # ############################################################################# 16 | # Credentials 17 | # ############################################################################# 18 | 19 | # User / ssh-key for all hosts 20 | # Note that if you need to configure individual keys 21 | # please do so in the hosts file for the respective hosts 22 | \VAR{ansible_user} 23 | 24 | # ############################################################################# 25 | # RT Campaign 26 | # ############################################################################# 27 | 28 | # The Codename for this RT assessment 29 | \VAR{codename} 30 | 31 | # Return emails for phishing campaigns will be forwarded to these addresses 32 | \VAR{phishing_reply_forwards} # space separated 33 | 34 | # Directory where RT tooling and docker-containers are stored 35 | # Usually no need to change this 36 | \VAR{toolkit_directory} 37 | 38 | # Address needed for Certbot to request Let's Encrypt certificates 39 | \VAR{certbot_mail_address} 40 | 41 | # ############################################################################# 42 | # User accounts fot the RT backend servers. 43 | # ############################################################################# 44 | 45 | # Please configure these values for your teammembers 46 | \VAR{users} 47 | 48 | # ############################################################################# 49 | # Other configurations (Usually no change is needed here) 50 | # ############################################################################# 51 | 52 | # Locales to use within the infrastructure 53 | \VAR{config_system_locale} 54 | \VAR{config_system_language} 55 | 56 | \VAR{ovpn_config_directory} 57 | 58 | \VAR{ansible_python_interpreter} 59 | 60 | \VAR{readme_location} 61 | 62 | # The internal IP space created by the openvpn servers on your redirectors 63 | # Usually there is no need to change this 64 | \VAR{internal_vpn_ip_space} 65 | \VAR{internal_vpn_ip_gateway} 66 | 67 | -------------------------------------------------------------------------------- /roles/backend-cobalt-strike/tasks/cobalt-strike-setup.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: "Cobalt Strike: Copy Docker build context" 3 | become: yes 4 | ansible.builtin.copy: 5 | src: docker/ 6 | dest: "{{ cs_docker_path }}/{{ relay_host }}" 7 | directory_mode: 0755 8 | 9 | - name: "Cobalt Strike: Select OpenVPN configuration based on pattern {{ cs_ovpn_pattern }}" 10 | become: yes 11 | ansible.builtin.copy: 12 | src: "{{ openvpn_client_profile_path }}/{{ relay_host }}/{{ cs_ovpn_pattern }}" 13 | dest: "{{ cs_docker_path }}/{{ relay_host }}/cobaltstrike.ovpn" 14 | remote_src: yes 15 | 16 | - name: "Cobalt Strike: Copy .env file for docker-compose" 17 | become: yes 18 | ansible.builtin.template: 19 | src: environment.j2 20 | dest: "{{ cs_docker_path }}/{{ relay_host }}/.env" 21 | 22 | - name: "Cobalt Strike: Create Malleable C2 profiles folder" 23 | become: yes 24 | ansible.builtin.file: 25 | path: "{{ cs_docker_path }}/{{ relay_host }}/c2-profiles/" 26 | state: directory 27 | mode: '0755' 28 | 29 | - name: "Cobalt Strike: Initialising cobaltstrike variables" 30 | become: yes 31 | set_fact: 32 | c2_tcp_port: "{{ 65535 | random(1024) }}" 33 | run_once: yes 34 | 35 | - name: "Cobalt Strike: Create aggressor scripts folder" 36 | become: yes 37 | ansible.builtin.file: 38 | path: "{{ cs_docker_path }}/{{ relay_host }}/aggressor-scripts/" 39 | state: directory 40 | mode: '0755' 41 | 42 | - name: "Cobalt Strike: Install Malleable C2 profile {{ malleable_profile }}" 43 | become: yes 44 | ansible.builtin.template: 45 | src: "{{ malleable_profile }}.j2" 46 | dest: "{{ cs_docker_path }}/{{ relay_host }}/c2-profiles/{{ malleable_profile }}" 47 | mode: 0755 48 | force: yes 49 | 50 | - name: "Cobalt Strike: Install default HTTPS listener" 51 | become: yes 52 | ansible.builtin.template: 53 | src: listener.service.cna.j2 54 | dest: "{{ cs_docker_path }}/{{ relay_host }}/aggressor-scripts/listener.service.cna" 55 | mode: 0755 56 | force: yes 57 | 58 | - name: "Cobalt Strike: Build Docker image and create container (This can take 5+ minutes, do not depair)" 59 | become: yes 60 | community.docker.docker_compose: 61 | build: yes 62 | debug: yes 63 | files: 64 | - docker-compose.yml 65 | project_src: "{{ cs_docker_path }}/{{ relay_host }}" 66 | pull: no 67 | recreate: smart 68 | state: present 69 | stopped: no 70 | timeout: 10 71 | register: result 72 | failed_when: "not result.services.teamserver.teamserver.state.running" 73 | changed_when: "result.actions in ['restart', 'create']" 74 | 75 | - name: "Cobalt Strike: Create symbolic link to Docker volumes in {{ toolkit_directory }}" 76 | become: yes 77 | ansible.builtin.file: 78 | src: "/var/lib/docker/volumes" 79 | dest: "{{ toolkit_directory }}/docker-volumes" 80 | state: link 81 | -------------------------------------------------------------------------------- /roles/backend-common/tasks/full-system-logging.yml: -------------------------------------------------------------------------------- 1 | 2 | - name: "Logging: Copy the informative text for the bash shell to /tmp/bash_config" 3 | become: yes 4 | ansible.builtin.copy: 5 | src: bash_config 6 | dest: /tmp/bash_config 7 | 8 | - name: "Logging: Check if /etc/rsyslog.d/bash.conf exists" 9 | ansible.builtin.stat: 10 | path: /etc/rsyslog.d/bash.conf 11 | register: bash_conf 12 | 13 | - name: "Logging: Create empty /etc/rsyslog.d/bash.conf if it does not yet exist" 14 | become: yes 15 | ansible.builtin.file: 16 | path: /etc/rsyslog.d/bash.conf 17 | state: touch 18 | owner: root 19 | group: root 20 | mode: 0644 21 | when: bash_conf.stat.exists == 0 22 | 23 | - name: "Logging: Add local6 logging to /etc/rsyslog.d/bash.conf configuration" 24 | become: yes 25 | ansible.builtin.lineinfile: 26 | dest: "/etc/rsyslog.d/bash.conf" 27 | line: "local6.* /var/log/commands/commands.log" 28 | state: present 29 | 30 | - name: "Logging: Add command logging to the /etc/logrotate.d/rsyslog" 31 | become: yes 32 | ansible.builtin.lineinfile: 33 | dest: "/etc/logrotate.d/rsyslog" 34 | line: "/var/log/commands/commands.log" 35 | state: present 36 | 37 | - name: "Logging: Restart rsyslog" 38 | become: yes 39 | ansible.builtin.service: 40 | name: rsyslog 41 | state: restarted 42 | changed_when: false # Always restart just to be sure. No need to mention changed message 43 | 44 | - name: "Logging: Create asciinema log directory /var/log/ascii" 45 | become: yes 46 | ansible.builtin.file: 47 | path: /var/log/ascii 48 | owner: root 49 | group: rtspec 50 | mode: 0773 51 | state: directory 52 | 53 | - name: "Logging: Write informative text to /etc/bash.bashrc" 54 | become: yes 55 | ansible.builtin.blockinfile: 56 | path: /etc/bash.bashrc 57 | block: "{{ lookup('file', 'bash_config') }}" 58 | create: yes 59 | state: present 60 | 61 | - name: "Logging: Create the /var/log/tcpdump directory" 62 | become: yes 63 | ansible.builtin.file: 64 | path: /var/log/tcpdump 65 | state: directory 66 | owner: root 67 | group: rtspec 68 | mode: 0775 69 | 70 | - name: "Logging: Add AppArmor in complain mode to circumvent tcpdump permission issues" 71 | become: yes 72 | ansible.builtin.command: aa-complain /sbin/tcpdump 73 | changed_when: false # Done always, so no change notification 74 | 75 | - name: "Logging: Copy the tcpdumper script to /etc/systemd/system/tcpdumper.service" 76 | become: yes 77 | ansible.builtin.template: 78 | src: tcpdumper.j2 79 | dest: /etc/systemd/system/tcpdumper.service 80 | 81 | - name: "Logging: Force systemd to reread configs" 82 | become: yes 83 | ansible.builtin.systemd: 84 | daemon_reload: yes 85 | 86 | - name: "Logging: Enable service for tcpdumper" 87 | ansible.builtin.systemd: 88 | name: tcpdumper 89 | enabled: yes 90 | state: started 91 | become: yes 92 | 93 | -------------------------------------------------------------------------------- /roles/backend-common/tasks/os-prep.yml: -------------------------------------------------------------------------------- 1 | - name: "Change Ubuntu mirror because of hash mismatches on ESXi" 2 | become: yes 3 | ansible.builtin.replace: 4 | path: /etc/apt/sources.list 5 | regexp: 'http://[^\s]*archive\.ubuntu\.com/ubuntu' 6 | replace: 'http://archive.ubuntu.com/ubuntu' 7 | 8 | - name: "Change Ubuntu mirror because of hash mismatches on ESXi" 9 | become: true 10 | replace: 11 | path: /etc/apt/sources.list 12 | regexp: 'http://[^\s]*archive\.ubuntu\.com/ubuntu' 13 | replace: 'http://archive.ubuntu.com/ubuntu' 14 | 15 | 16 | - name: "Install basic packages for backend server use" 17 | become: yes 18 | ansible.builtin.apt: 19 | name: 20 | - docker.io 21 | - docker-compose 22 | - python3 23 | - pwgen 24 | - vim 25 | - openvpn 26 | - iptables 27 | - iptables-persistent 28 | - apparmor-utils 29 | - tcpdump 30 | - python3-pexpect 31 | - python3-click 32 | - netcat 33 | - dnsutils 34 | - python3-pip 35 | - ipset 36 | - zip 37 | - screen 38 | - apparmor-utils 39 | - net-tools 40 | - curl 41 | - nano 42 | - bridge-utils 43 | - asciinema 44 | state: present 45 | update_cache: yes 46 | cache_valid_time: 0 47 | register: apt_action 48 | retries: 10 49 | until: apt_action is success or ('Failed to lock apt for exclusive operation' not in apt_action.msg and '/var/lib/dpkg/lock' not in apt_action.msg) 50 | # https://github.com/ansible/ansible/issues/51663#issuecomment-752286191 51 | 52 | - name: "Remove UFW so it can't interfere with our iptables rules" 53 | become: yes 54 | ansible.builtin.apt: 55 | name: 56 | - ufw 57 | state: absent 58 | register: apt_action 59 | retries: 10 60 | until: apt_action is success or ('Failed to lock apt for exclusive operation' not in apt_action.msg and '/var/lib/dpkg/lock' not in apt_action.msg) 61 | # https://github.com/ansible/ansible/issues/51663#issuecomment-752286191 62 | 63 | - name: "Autoremove unused packages" 64 | become: yes 65 | ansible.builtin.command: 66 | cmd: apt -y autoremove 67 | register: apt_result 68 | changed_when: "'packages will be REMOVED' in apt_result.stdout" 69 | 70 | - name: "Purge residual kernel packages" 71 | become: yes 72 | ansible.builtin.shell: 73 | cmd: apt remove -y --purge $(dpkg -l | grep "^rc\s*linux-image-" | awk '{print $2}' | tr '\n' ' ') 74 | register: apt_result 75 | changed_when: "'packages will be REMOVED' in apt_result.stdout" 76 | 77 | - name: "Set the system's hostname to {{ codename }}-{{ inventory_hostname }}" 78 | become: yes 79 | ansible.builtin.hostname: 80 | name: "{{ codename }}-{{ inventory_hostname }}" 81 | 82 | - name: "Add {{ codename }}-{{ inventory_hostname }} to /etc/hosts" 83 | become: yes 84 | ansible.builtin.lineinfile: 85 | dest: /etc/hosts 86 | regexp: '^127\.0\.0\.1[ \t]+localhost' 87 | line: "127.0.0.1 localhost {{ codename }}-{{ inventory_hostname }}" 88 | state: present 89 | 90 | -------------------------------------------------------------------------------- /roles/backend-osint/templates/startvpn.j2: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | trap ctrl_c INT 4 | VPN_FILE=$1 5 | TUNNEL=tun0 6 | 7 | function check_running() { 8 | if [[ $(ip link | grep $TUNNEL | grep ",UP,") == *$TUNNEL* ]]; then 9 | echo "VPN Already up, exiting" 10 | exit 0 11 | fi 12 | } 13 | 14 | function check_permission() { 15 | if test " `id -u`" != " 0" 16 | then 17 | echo "permission denied (use sudo)" 18 | exit 1 19 | fi 20 | } 21 | 22 | function check_argument() { 23 | if [ -z $VPN_FILE ] 24 | then 25 | echo "First argument must be VPN file(.ovpn)" 26 | exit 1 27 | fi 28 | } 29 | 30 | function ensure_ssh_connectivity() { 31 | {% for companyip in company_ip_space %} 32 | ip route add {{ companyip }} via {{ ansible_default_ipv4.gateway }} 33 | {% endfor %} 34 | } 35 | 36 | function config() { 37 | #Get the default network interface 38 | echo "Detecting your default network interface..." 39 | INTERFACE=`ip addr | grep "state UP" | cut -d ":" -f 2 | head -n 1` 40 | echo "Using "$INTERFACE 41 | 42 | echo "Using interface "$TUNNEL " for VPN, change the script if you need another one." 43 | 44 | #Get the VPN IP, PORT and PROTOCOL from the VPN file 45 | echo "Detecting your VPN server address..." 46 | IP=`cat $VPN_FILE | grep "remote " | awk '{print $2}'` 47 | echo "Using IP "$IP 48 | 49 | echo "Detecting your VPN port..." 50 | PORT=`cat $VPN_FILE | grep "remote " | awk '{print $3}'` 51 | echo "Using port "$PORT 52 | 53 | echo "Detecting your VPN protocol..." 54 | PROTOCOL=`cat $VPN_FILE | grep "remote " | awk '{print $4}'` 55 | echo "Using protocol "$PROTOCOL 56 | } 57 | 58 | function ctrl_c() { 59 | echo "Flushing iptables and exiting" 60 | exit 1 61 | } 62 | 63 | function set_firewall_rules() { 64 | echo "Setting firewall rules" 65 | ##Allow connection with the VPN IP 66 | iptables -A OUTPUT -p $PROTOCOL -d $IP --dport $PORT -j ACCEPT 67 | iptables -A INPUT -p $PROTOCOL -s $IP --sport $PORT -j ACCEPT 68 | ##Allow connection through the tunnel 69 | iptables -A OUTPUT -o $TUNNEL -j ACCEPT 70 | iptables -A INPUT -i $TUNNEL -j ACCEPT 71 | ##Block all connection through the main interface, but allow outgoing for SSH 72 | {% for companyip in company_ip_space %} 73 | iptables -A OUTPUT -o $INTERFACE -j ACCEPT -d {{ companyip }} 74 | {% endfor %} 75 | iptables -A OUTPUT -o $INTERFACE -j DROP 76 | iptables -A INPUT -i $INTERFACE -j DROP 77 | } 78 | 79 | function reconnect() { 80 | echo "Reconnecting VPN" 81 | #Kill older openvpn processes to avoid creating new tunnels 82 | kill `ps -ef | grep "openvpn $VPN_FILE" | grep -v "grep" | awk '{print $2}'` > /dev/null 2>&1 83 | #Start openvpn 84 | /usr/sbin/openvpn $VPN_FILE & 85 | } 86 | 87 | #Check every 20 seconds if VPN goes down, then reconnect it 88 | function check_connection() { 89 | echo "Check VPN connection" 90 | while [ true ] 91 | do 92 | if [[ $(ip link | grep $TUNNEL | grep ",UP,") != *$TUNNEL* ]]; then 93 | reconnect 94 | fi 95 | sleep 20 96 | done 97 | } 98 | 99 | check_running 100 | check_permission 101 | check_argument 102 | ensure_ssh_connectivity 103 | config 104 | set_firewall_rules 105 | check_connection 106 | -------------------------------------------------------------------------------- /roles/relay-common/tasks/os-prep.yml: -------------------------------------------------------------------------------- 1 | #- name: Ensure localisation files for '{{ config_system_locale }}' are available 2 | # locale_gen: 3 | # name: "{{ config_system_locale }}" 4 | # state: present 5 | # 6 | #- name: Ensure language files for '{{ config_system_language }}' are available 7 | # locale_gen: 8 | # name: "{{ config_system_language }}" 9 | # state: present 10 | # 11 | #- name: Get current locale and language configuration 12 | # command: localectl status 13 | # register: locale_status 14 | # changed_when: false 15 | # 16 | #- name: Parse 'LANG' from current locale and language configuration 17 | # set_fact: 18 | # locale_lang: "{{ locale_status.stdout | regex_search('LANG=([^\n]+)', '\\1') | first }}" 19 | # 20 | #- name: Parse 'LANGUAGE' from current locale and language configuration 21 | # set_fact: 22 | # locale_language: "{{ locale_status.stdout | regex_search('LANGUAGE=([^\n]+)', '\\1') | default([locale_lang], true) | first }}" 23 | # 24 | #- name: Configure locale to '{{ config_system_locale }}' and language to '{{ config_system_language }}' 25 | # become: yes 26 | # command: localectl set-locale LANG={{ config_system_locale }} LANGUAGE={{ config_system_language }} 27 | # changed_when: locale_lang != config_system_locale or locale_language != config_system_language 28 | 29 | - name: "Install packages for the basic function of the relay" 30 | become: yes 31 | ansible.builtin.apt: 32 | name: 33 | - python3 34 | - python3-click 35 | - python3-pexpect 36 | - python3-pip 37 | - pwgen 38 | - vim 39 | - iptables 40 | - iptables-persistent 41 | - tcpdump 42 | - netcat 43 | - dnsutils 44 | - ipset 45 | - net-tools 46 | - curl 47 | - nano 48 | - bridge-utils 49 | state: present 50 | update_cache: yes 51 | cache_valid_time: 3600 52 | register: apt_action 53 | retries: 10 54 | until: apt_action is success or ('Failed to lock apt for exclusive operation' not in apt_action.msg and '/var/lib/dpkg/lock' not in apt_action.msg) 55 | # https://github.com/ansible/ansible/issues/51663#issuecomment-752286191 56 | 57 | - name: "Remove ufw so it can't interfere with our iptables setup" 58 | become: yes 59 | ansible.builtin.apt: 60 | name: 61 | - ufw 62 | state: absent 63 | 64 | - name: "Autoremove unused packages" 65 | become: yes 66 | ansible.builtin.command: 67 | cmd: apt -y autoremove 68 | register: apt_result 69 | changed_when: "'packages will be REMOVED' in apt_result.stdout" 70 | 71 | - name: "Purge residual kernel packages" 72 | become: yes 73 | ansible.builtin.shell: 74 | cmd: apt remove -y --purge $(dpkg -l | grep "^rc\s*linux-image-" | awk '{print $2}' | tr '\n' ' ') 75 | register: apt_result 76 | changed_when: "'packages will be REMOVED' in apt_result.stdout" 77 | 78 | - name: "Set the hostname to {{ codename }}-{{ inventory_hostname }}" 79 | become: yes 80 | ansible.builtin.hostname: 81 | name: "{{ codename }}-{{ inventory_hostname }}" 82 | 83 | - name: "Add {{ codename }}-{{ inventory_hostname }} to /etc/hosts" 84 | become: yes 85 | ansible.builtin.lineinfile: 86 | dest: /etc/hosts 87 | line: "127.0.0.1 localhost {{ codename }}-{{ inventory_hostname }}" 88 | state: present 89 | -------------------------------------------------------------------------------- /roles/relay-nginx/tasks/nginx-config.yml: -------------------------------------------------------------------------------- 1 | - name: "RELAY - NGINX: Disable NGINX Default Virtual Host" 2 | become: yes 3 | ansible.builtin.file: 4 | path: /etc/nginx/sites-enabled/default 5 | state: absent 6 | changed_when: false # Done always, so no change notification 7 | 8 | - name: "RELAY - NGINX: Copy NGINX template file (Also saving a backup)" 9 | become: yes 10 | ansible.builtin.template: 11 | src: "revproxy.j2" 12 | dest: "/etc/nginx/sites-available/{{nginx_relay_config_name}}.conf" 13 | force: no 14 | 15 | - name: "RELAY - NGINX: Add upstream proxy to nginx config" 16 | become: yes 17 | ansible.builtin.blockinfile: 18 | path: "/etc/nginx/sites-available/{{nginx_relay_config_name}}.conf" 19 | marker: "#### {mark} UPSTREAM FOR {{ relay_to_client_profile }} ####" 20 | insertafter: "#ANSIBLE_MARKER_UPSTREAM" 21 | block: | 22 | upstream backend-{{ relay_to_client_profile }} { 23 | zone backend 64k; 24 | # The backend address is supposed to be automatically updated with the 25 | # update-rev-proxy-to-{{ relay_to_client_profile }}.sh script running in a cronjob 26 | server 10.8.0.2:{{ backend_port }}; # {{ relay_to_client_profile }} 27 | } 28 | 29 | - name: "RELAY - NGINX: Add forward proxy rules for secret strings" 30 | become: yes 31 | ansible.builtin.blockinfile: 32 | path: "/etc/nginx/sites-available/{{nginx_relay_config_name}}.conf" 33 | marker: "#### {mark} FORWARD FOR {{ relay_to_client_profile }} ####" 34 | insertafter: "#ANSIBLE_MARKER_PROXY" 35 | block: | 36 | {% for secret in secret_strings %} 37 | location /{{secret.string}} { 38 | proxy_pass {{ secret.connection_method }}://backend-{{ relay_to_client_profile }}{{ secret.forward_path }}; 39 | } 40 | {% endfor %} 41 | 42 | - name: "RELAY - NGINX: Copy script to dynamically update the target for reverse connections" 43 | become: yes 44 | ansible.builtin.template: 45 | src: "update-rev-proxy-ip.j2" 46 | dest: "{{ toolkit_directory }}/update-rev-proxy-to-{{ relay_to_client_profile }}.sh" 47 | mode: "0744" 48 | 49 | - name: "RELAY - NGINX: Add cronjob entry for dynamically updating IP address" 50 | become: yes 51 | ansible.builtin.cron: 52 | name: "Update Backend IP address" 53 | user: root 54 | minute: 0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51,54,57 55 | hour: "*" 56 | day: "*" 57 | month: "*" 58 | weekday: "*" 59 | job: "{{ toolkit_directory }}/update-rev-proxy-to-{{ relay_to_client_profile }}.sh" 60 | cron_file: "update-backend-ip-{{ relay_to_client_profile }}" 61 | 62 | - name: "RELAY - NGINX: Link NGINX Relayhost Reverse Proxy" 63 | become: yes 64 | ansible.builtin.file: 65 | src: /etc/nginx/sites-available/{{nginx_relay_config_name}}.conf 66 | dest: /etc/nginx/sites-enabled/{{nginx_relay_config_name}}.conf 67 | state: link 68 | 69 | - name: "RELAY - NGINX: Set Logrotate to keep logs for a year" 70 | become: yes 71 | ansible.builtin.copy: 72 | src: "nginx.logrotate" 73 | dest: "/etc/logrotate.d/nginx" 74 | force: yes 75 | 76 | - name: "RELAY - NGINX: Make Sure NGINX Service Is Running" 77 | become: yes 78 | ansible.builtin.service: 79 | name: nginx 80 | state: restarted 81 | enabled: yes 82 | changed_when: false # Done always, so no change notification 83 | 84 | -------------------------------------------------------------------------------- /step-3-deploy-infra.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | orange=$(printf '\033[0;33m') 4 | green=$(printf '\033[0;32m') 5 | reset=$(printf '\033[0;00m') 6 | blue=$(printf '\033[0;34m') 7 | red=$(printf '\033[0;31m') 8 | yellow=$(printf '\033[0;93m') 9 | purple=$(printf '\033[0;95m') 10 | cyan=$(printf '\033[1;36m') 11 | 12 | bold=$(printf '\033[1m') 13 | underline=$(printf '\033[4m') 14 | reversed=$(printf '\033[7m') 15 | 16 | if [[ $# -eq 0 ]] ; then 17 | cat <<-EOF 18 | Usage: $0 [] 19 | 20 | Tags are optional and allow you to deploy only certain components 21 | Run ./tools/list-tags.py to see all available tags 22 | 23 | WARNING: Tags assume that the "backend-common" or "relay-common" and "users" 24 | roles are already deployed to the server, if this is not the case 25 | add "backend-common" or "relay-common" and "users" as a tag 26 | EOF 27 | exit 1 28 | fi 29 | 30 | CONFIG_PATH="${PWD}/$1" 31 | HOST_FILE="${CONFIG_PATH}/hosts.yml" 32 | CONFIG_FILE="${CONFIG_PATH}/configuration.yml" 33 | EXPORT_PATH="${CONFIG_PATH}/Exports_Autogenerated/" 34 | VAULT_FILE="${CONFIG_PATH}/vaulted_vars.yml" 35 | 36 | echo 37 | echo "__________ .___ __ __.__ .___" 38 | echo "\______ \ ____ __| _/ / \ / \__|____________ _______ __| _/" 39 | echo " | _// __ \ / __ | \ \/\/ / \___ /\__ \\_ __ \/ __ |" 40 | echo " | | \ ___// /_/ | \ /| |/ / / __ \| | \/ /_/ |" 41 | echo " |____|_ /\___ >____ | \__/\ / |__/_____ \(____ /__| \____ |" 42 | echo " \/ \/ \/ \/ \/ \/ \/" 43 | echo 44 | echo " --- Deploying Infrastructure --- " 45 | echo 46 | echo 47 | 48 | cat <<-EOF 49 | Have you checked all requirements? If they are not met, this will fail. 50 | Check the requirements with ${green}python3 tools/check-prerequisites.py ${CONFIG_PATH}${reset} 51 | EOF 52 | read -p "Do you want to continue? [y/N] " -n 1 -r 53 | echo 54 | 55 | if [[ ! ${REPLY} =~ ^[Yy]$ ]]; then 56 | exit 1 57 | fi 58 | 59 | if [ ! -f "${HOST_FILE}" ]; then 60 | echo "Hosts file (hosts) does not exist in ${CONFIG_PATH}." 61 | exit 1 62 | fi 63 | 64 | if [ ! -f "${CONFIG_FILE}" ]; then 65 | echo "Config file (configuration.yml) file does not exist in ${CONFIG_PATH}." 66 | exit 1 67 | fi 68 | 69 | mkdir -p ${EXPORT_PATH} 70 | 71 | if [[ $# -eq 1 ]] ; then 72 | ansible-playbook -i "${HOST_FILE}" -e "@${CONFIG_FILE}" -e "@${VAULT_FILE}" --ask-vault-pass --extra-vars "export_path=${EXPORT_PATH} config_path=${CONFIG_PATH}" playbook.yml 73 | fi 74 | 75 | if [[ $# -eq 2 ]] ; then 76 | TAGS="$2" 77 | cat <<-EOF 78 | 79 | WARNING: Tags assume that the "backend-common" or "relay-common" and "users" 80 | roles are already deployed to the server, if this is not the case 81 | add "backend-common" or "relay-common" and "users" as a tag or your deployment 82 | will fail 83 | 84 | EOF 85 | ansible-playbook -i "${HOST_FILE}" -e "@${CONFIG_FILE}" -e "@${VAULT_FILE}" --tags "${TAGS}" --ask-vault-pass --extra-vars "export_path=${EXPORT_PATH} config_path=${CONFIG_PATH}" playbook.yml 86 | fi 87 | cat <<-EOF 88 | ------------------------------------- DONE ------------------------------------- 89 | - Consider running ${green}./tools/create-ssh-config.py ${CONFIG_PATH}${reset} to create your SSH Config 90 | - Consider running ${green}./tools/diagram.py ${CONFIG_PATH}${reset} to create a diagram of your infra 91 | - Configure your DNS settings for phishing and CobaltStrike campaigns. Consider running ${green}cat ${CONFIG_PATH}/Exports_Autogenerated/dns_configs/*${reset} 92 | EOF 93 | -------------------------------------------------------------------------------- /playbook.yml: -------------------------------------------------------------------------------- 1 | # RELAY CONFIGURATIONS 2 | 3 | - name: "***** CONFIGURING ALL RELAYS *****" 4 | hosts: relays 5 | gather_facts: yes 6 | roles: 7 | - relay-common 8 | tags: 9 | - relay 10 | - relay-common 11 | 12 | - name: "***** CONFIGURING USERS FOR RELAYS *****" 13 | hosts: relays 14 | gather_facts: yes 15 | roles: 16 | - users 17 | tags: 18 | - relay 19 | - users 20 | - users-relay 21 | 22 | - name: "***** CONFIGURING DROPBOX RELAYS *****" 23 | hosts: relays_dropbox 24 | gather_facts: yes 25 | roles: 26 | - relay-dropbox 27 | tags: 28 | - relay 29 | - relay-dropbox 30 | - dropbox 31 | 32 | - name: "***** CONFIGURING PHISHING RELAYS *****" 33 | hosts: relays_phishing 34 | gather_facts: yes 35 | roles: 36 | - relay-phishing 37 | tags: 38 | - relay 39 | - relay-phishing 40 | - phishing 41 | 42 | # The relays_nginx needs to have serial: 1 set so multiple nginx roles do not interfere 43 | - name: "***** CONFIGURING NGINX RELAYS *****" 44 | hosts: relays_nginx 45 | serial: 1 46 | gather_facts: yes 47 | roles: 48 | - relay-nginx 49 | tags: 50 | - relay 51 | - relay-nginx 52 | - nginx 53 | - stage-one 54 | - cobalt-strike 55 | 56 | # Configure the CobaltStrike DNS relays 57 | - name: "***** CONFIGURING Cobaltstrike RELAYS *****" 58 | hosts: relays_cobalt_strike 59 | gather_facts: yes 60 | roles: 61 | - relay-cobalt-strike 62 | tags: 63 | - relay 64 | - relay-cobalt-strike 65 | - cobalt-strike 66 | 67 | - name: "***** CONFIGURING OSINT RELAYS *****" 68 | hosts: relays_osint 69 | gather_facts: yes 70 | roles: 71 | - relay-osint 72 | tags: 73 | - relay 74 | - relay-osint 75 | - osint 76 | 77 | # BACKEND CONFIGURATIONS 78 | 79 | - name: "***** CONFIGURING BACKENDS *****" 80 | hosts: backends 81 | gather_facts: yes 82 | roles: 83 | - backend-common 84 | tags: 85 | - backend 86 | - backend-common 87 | 88 | - name: "***** CONFIGURING USERS FOR BACKENDS *****" 89 | hosts: backends 90 | gather_facts: yes 91 | roles: 92 | - users 93 | tags: 94 | - users 95 | - backend 96 | - users-backends 97 | 98 | - name: "***** CONFIGURING BACKEND GOPHISH *****" 99 | hosts: backends_gophish 100 | gather_facts: yes 101 | roles: 102 | - backend-gophish 103 | tags: 104 | - backend 105 | - backend-gophish 106 | - phishing 107 | 108 | - name: "***** CONFIGURING BACKEND MANUAL PHISH *****" 109 | hosts: backends_manual_phish 110 | gather_facts: yes 111 | roles: 112 | - backend-manual-phish 113 | tags: 114 | - backend 115 | - backend-manual-phish 116 | - phishing 117 | 118 | - name: "***** CONFIGURING BACKEND COBALT STRIKE *****" 119 | hosts: backends_cobalt_strike 120 | gather_facts: yes 121 | roles: 122 | - backend-cobalt-strike 123 | tags: 124 | - backend 125 | - backend-cobalt-strike 126 | - cobalt-strike 127 | 128 | - name: "***** CONFIGURING BACKEND DROPBOX *****" 129 | hosts: backends_dropbox 130 | gather_facts: yes 131 | roles: 132 | - backend-dropbox 133 | tags: 134 | - backend 135 | - backend-dropbox 136 | - dropbox 137 | 138 | - name: "***** CONFIGURING BACKEND OSINT *****" 139 | hosts: backends_osint 140 | gather_facts: yes 141 | roles: 142 | - backend-osint 143 | tags: 144 | - backend 145 | - backend-osint 146 | - osint 147 | 148 | - name: "***** CONFIGURING BACKEND WEB CATCHER *****" 149 | hosts: backends_web_catcher 150 | gather_facts: yes 151 | roles: 152 | - backend-webcatcher 153 | tags: 154 | - backend 155 | - backend-webcatcher 156 | - webcatcher 157 | -------------------------------------------------------------------------------- /roles/backend-common/templates/sshd_config.j2: -------------------------------------------------------------------------------- 1 | # $OpenBSD: sshd_config,v 1.103 2018/04/09 20:41:22 tj Exp $ 2 | 3 | # This is the sshd server system-wide configuration file. See 4 | # sshd_config(5) for more information. 5 | 6 | # This sshd was compiled with PATH=/usr/bin:/bin:/usr/sbin:/sbin 7 | 8 | # The strategy used for options in the default sshd_config shipped with 9 | # OpenSSH is to specify options with their default value where 10 | # possible, but leave them commented. Uncommented options override the 11 | # default value. 12 | 13 | Include /etc/ssh/sshd_config.d/*.conf 14 | 15 | #Port 22 16 | #AddressFamily any 17 | #ListenAddress 0.0.0.0 18 | #ListenAddress :: 19 | 20 | #HostKey /etc/ssh/ssh_host_rsa_key 21 | #HostKey /etc/ssh/ssh_host_ecdsa_key 22 | #HostKey /etc/ssh/ssh_host_ed25519_key 23 | 24 | # Ciphers and keying 25 | #RekeyLimit default none 26 | 27 | # Logging 28 | #SyslogFacility AUTH 29 | #LogLevel INFO 30 | 31 | # Authentication: 32 | 33 | #LoginGraceTime 2m 34 | PermitRootLogin no 35 | #StrictModes yes 36 | #MaxAuthTries 6 37 | #MaxSessions 10 38 | 39 | #PubkeyAuthentication yes 40 | 41 | # Expect .ssh/authorized_keys2 to be disregarded by default in future. 42 | #AuthorizedKeysFile .ssh/authorized_keys .ssh/authorized_keys2 43 | 44 | #AuthorizedPrincipalsFile none 45 | 46 | #AuthorizedKeysCommand none 47 | #AuthorizedKeysCommandUser nobody 48 | 49 | # For this to work you will also need host keys in /etc/ssh/ssh_known_hosts 50 | #HostbasedAuthentication no 51 | # Change to yes if you don't trust ~/.ssh/known_hosts for 52 | # HostbasedAuthentication 53 | #IgnoreUserKnownHosts no 54 | # Don't read the user's ~/.rhosts and ~/.shosts files 55 | #IgnoreRhosts yes 56 | 57 | # To disable tunneled clear text passwords, change to no here! 58 | PasswordAuthentication no 59 | #PermitEmptyPasswords no 60 | 61 | # Change to yes to enable challenge-response passwords (beware issues with 62 | # some PAM modules and threads) 63 | ChallengeResponseAuthentication no 64 | 65 | # Kerberos options 66 | #KerberosAuthentication no 67 | #KerberosOrLocalPasswd yes 68 | #KerberosTicketCleanup yes 69 | #KerberosGetAFSToken no 70 | 71 | # GSSAPI options 72 | #GSSAPIAuthentication no 73 | #GSSAPICleanupCredentials yes 74 | #GSSAPIStrictAcceptorCheck yes 75 | #GSSAPIKeyExchange no 76 | 77 | # Set this to 'yes' to enable PAM authentication, account processing, 78 | # and session processing. If this is enabled, PAM authentication will 79 | # be allowed through the ChallengeResponseAuthentication and 80 | # PasswordAuthentication. Depending on your PAM configuration, 81 | # PAM authentication via ChallengeResponseAuthentication may bypass 82 | # the setting of "PermitRootLogin without-password". 83 | # If you just want the PAM account and session checks to run without 84 | # PAM authentication, then enable this but set PasswordAuthentication 85 | # and ChallengeResponseAuthentication to 'no'. 86 | UsePAM yes 87 | 88 | #AllowAgentForwarding yes 89 | #AllowTcpForwarding yes 90 | #GatewayPorts no 91 | X11Forwarding yes 92 | #X11DisplayOffset 10 93 | #X11UseLocalhost yes 94 | #PermitTTY yes 95 | PrintMotd no 96 | #PrintLastLog yes 97 | #TCPKeepAlive yes 98 | #PermitUserEnvironment no 99 | #Compression delayed 100 | #ClientAliveInterval 0 101 | #ClientAliveCountMax 3 102 | #UseDNS no 103 | #PidFile /var/run/sshd.pid 104 | #MaxStartups 10:30:100 105 | #PermitTunnel no 106 | #ChrootDirectory none 107 | #VersionAddendum none 108 | 109 | # no default banner path 110 | #Banner none 111 | 112 | # Allow client to pass locale environment variables 113 | AcceptEnv LANG LC_* 114 | 115 | # override default of no subsystems 116 | Subsystem sftp /usr/lib/openssh/sftp-server 117 | 118 | # Example of overriding settings on a per-user basis 119 | #Match User anoncvs 120 | # X11Forwarding no 121 | # AllowTcpForwarding no 122 | # PermitTTY no 123 | # ForceCommand cvs server 124 | -------------------------------------------------------------------------------- /roles/relay-common/templates/sshd_config.j2: -------------------------------------------------------------------------------- 1 | # $OpenBSD: sshd_config,v 1.103 2018/04/09 20:41:22 tj Exp $ 2 | 3 | # This is the sshd server system-wide configuration file. See 4 | # sshd_config(5) for more information. 5 | 6 | # This sshd was compiled with PATH=/usr/bin:/bin:/usr/sbin:/sbin 7 | 8 | # The strategy used for options in the default sshd_config shipped with 9 | # OpenSSH is to specify options with their default value where 10 | # possible, but leave them commented. Uncommented options override the 11 | # default value. 12 | 13 | Include /etc/ssh/sshd_config.d/*.conf 14 | 15 | #Port 22 16 | #AddressFamily any 17 | #ListenAddress 0.0.0.0 18 | #ListenAddress :: 19 | 20 | #HostKey /etc/ssh/ssh_host_rsa_key 21 | #HostKey /etc/ssh/ssh_host_ecdsa_key 22 | #HostKey /etc/ssh/ssh_host_ed25519_key 23 | 24 | # Ciphers and keying 25 | #RekeyLimit default none 26 | 27 | # Logging 28 | #SyslogFacility AUTH 29 | #LogLevel INFO 30 | 31 | # Authentication: 32 | 33 | #LoginGraceTime 2m 34 | PermitRootLogin no 35 | #StrictModes yes 36 | #MaxAuthTries 6 37 | #MaxSessions 10 38 | 39 | #PubkeyAuthentication yes 40 | 41 | # Expect .ssh/authorized_keys2 to be disregarded by default in future. 42 | #AuthorizedKeysFile .ssh/authorized_keys .ssh/authorized_keys2 43 | 44 | #AuthorizedPrincipalsFile none 45 | 46 | #AuthorizedKeysCommand none 47 | #AuthorizedKeysCommandUser nobody 48 | 49 | # For this to work you will also need host keys in /etc/ssh/ssh_known_hosts 50 | #HostbasedAuthentication no 51 | # Change to yes if you don't trust ~/.ssh/known_hosts for 52 | # HostbasedAuthentication 53 | #IgnoreUserKnownHosts no 54 | # Don't read the user's ~/.rhosts and ~/.shosts files 55 | #IgnoreRhosts yes 56 | 57 | # To disable tunneled clear text passwords, change to no here! 58 | PasswordAuthentication no 59 | #PermitEmptyPasswords no 60 | 61 | # Change to yes to enable challenge-response passwords (beware issues with 62 | # some PAM modules and threads) 63 | ChallengeResponseAuthentication no 64 | 65 | # Kerberos options 66 | #KerberosAuthentication no 67 | #KerberosOrLocalPasswd yes 68 | #KerberosTicketCleanup yes 69 | #KerberosGetAFSToken no 70 | 71 | # GSSAPI options 72 | #GSSAPIAuthentication no 73 | #GSSAPICleanupCredentials yes 74 | #GSSAPIStrictAcceptorCheck yes 75 | #GSSAPIKeyExchange no 76 | 77 | # Set this to 'yes' to enable PAM authentication, account processing, 78 | # and session processing. If this is enabled, PAM authentication will 79 | # be allowed through the ChallengeResponseAuthentication and 80 | # PasswordAuthentication. Depending on your PAM configuration, 81 | # PAM authentication via ChallengeResponseAuthentication may bypass 82 | # the setting of "PermitRootLogin without-password". 83 | # If you just want the PAM account and session checks to run without 84 | # PAM authentication, then enable this but set PasswordAuthentication 85 | # and ChallengeResponseAuthentication to 'no'. 86 | UsePAM yes 87 | 88 | #AllowAgentForwarding yes 89 | #AllowTcpForwarding yes 90 | #GatewayPorts no 91 | X11Forwarding yes 92 | #X11DisplayOffset 10 93 | #X11UseLocalhost yes 94 | #PermitTTY yes 95 | PrintMotd no 96 | #PrintLastLog yes 97 | #TCPKeepAlive yes 98 | #PermitUserEnvironment no 99 | #Compression delayed 100 | #ClientAliveInterval 0 101 | #ClientAliveCountMax 3 102 | #UseDNS no 103 | #PidFile /var/run/sshd.pid 104 | #MaxStartups 10:30:100 105 | #PermitTunnel no 106 | #ChrootDirectory none 107 | #VersionAddendum none 108 | 109 | # no default banner path 110 | #Banner none 111 | 112 | # Allow client to pass locale environment variables 113 | AcceptEnv LANG LC_* 114 | 115 | # override default of no subsystems 116 | Subsystem sftp /usr/lib/openssh/sftp-server 117 | 118 | # Example of overriding settings on a per-user basis 119 | #Match User anoncvs 120 | # X11Forwarding no 121 | # AllowTcpForwarding no 122 | # PermitTTY no 123 | # ForceCommand cvs server 124 | -------------------------------------------------------------------------------- /roles/relay-common/tasks/ovpn-setup.yml: -------------------------------------------------------------------------------- 1 | - name: "OpenVPN Server: Create {{ ovpn_config_directory }} if it does not exist" 2 | become: yes 3 | ansible.builtin.file: 4 | path: "{{ ovpn_config_directory }}" 5 | state: directory 6 | mode: "0755" 7 | 8 | - name: "OpenVPN Server: Install the SparkLabs configuration generator" 9 | become: yes 10 | ansible.builtin.apt: 11 | deb: https://github.com/thesparklabs/openvpn-configuration-generator/releases/download/1.0.8/openvpn-configuration-generator_20.04_1.0.8.deb 12 | register: apt_action 13 | retries: 10 14 | until: apt_action is success or ('Failed to lock apt for exclusive operation' not in apt_action.msg and '/var/lib/dpkg/lock' not in apt_action.msg) 15 | # https://github.com/ansible/ansible/issues/51663#issuecomment-752286191 16 | 17 | - name: "OpenVPN Server: Copy visc to ovpn conversion script to {{ ovpn_config_directory }}/python3-convert-visc-to-ovpn.py" 18 | become: yes 19 | ansible.builtin.copy: 20 | src: python3-convert-visc-to-ovpn.py 21 | dest: "{{ ovpn_config_directory }}/python3-convert-visc-to-ovpn.py" 22 | 23 | - name: "OpenVPN Server: Install openvpn-server" 24 | become: yes 25 | ansible.builtin.apt: 26 | name: openvpn 27 | update_cache: yes 28 | cache_valid_time: 3600 29 | state: latest 30 | register: apt_action 31 | retries: 10 32 | until: apt_action is success or ('Failed to lock apt for exclusive operation' not in apt_action.msg and '/var/lib/dpkg/lock' not in apt_action.msg) 33 | # https://github.com/ansible/ansible/issues/51663#issuecomment-752286191 34 | 35 | - name: "OpenVPN Server: Check if ovpn configuration exists in {{ ovpn_config_directory }}" 36 | become: yes 37 | stat: 38 | path: "{{ ovpn_config_directory }}/config.conf" 39 | register: vpn_exists 40 | 41 | - name: "OpenVPN Server: Create ovpn profile (Generating keys take up to 240 seconds, since randomness is low on new installs)" 42 | become: yes 43 | ansible.builtin.expect: 44 | command: "openvpn-generate init --path {{ ovpn_config_directory }}" 45 | responses: 46 | (?i)Server address: "{{ ansible_host }}" 47 | (?i)Server Port: 1194 48 | (?i)Protocol: 1 # UDP 49 | (?i)Redirect all traffic through VPN: Y 50 | (?i)Please select an option: 6 # Don't use DNS for VPN connections 51 | (?i)Would you like to use anonymous defaults for certificate details: Y 52 | echo: yes 53 | timeout: 240 54 | when: vpn_exists.stat.exists == False 55 | 56 | - name: "OpenVPN Server: Delete default ovpn configuration" 57 | become: true 58 | file: 59 | path: "{{ item }}" 60 | state: absent 61 | with_items: 62 | - /etc/openvpn/config.conf 63 | - /etc/openvpn/server 64 | - /etc/openvpn/pki 65 | when: vpn_exists.stat.exists == False 66 | 67 | # Note that we do not make a symlink here, as this will cause the openvpn service to fail 68 | - name: "OpenVPN Server: Copy configuration file {{ ovpn_config_directory }}/server/server.conf to /etc/openvpn" 69 | become: yes 70 | ansible.builtin.copy: 71 | src: "{{ ovpn_config_directory }}/server/{{ item }}" 72 | dest: "/etc/openvpn/{{ item }}" 73 | owner: root 74 | group: root 75 | mode: "0600" 76 | remote_src: yes # The config is already on the target, just not in the right spot 77 | with_items: 78 | - ca.crt 79 | - dh.pem 80 | - server.conf 81 | - server.crt 82 | - server.key 83 | 84 | # TODO: Convert this into a handler that gets called when needed 85 | - name: "OpenVPN Server: Start the systemd service now and on (re)boot" 86 | become: yes 87 | ansible.builtin.systemd: 88 | name: openvpn@server 89 | enabled: yes 90 | state: started 91 | 92 | # Set ip forwarding on in /proc and in the sysctl file and reload if necessary 93 | - name: "Enable IP forwarding for relay functionality" 94 | become: yes 95 | ansible.builtin.sysctl: 96 | name: net.ipv4.ip_forward 97 | value: 1 98 | sysctl_set: yes 99 | state: present 100 | reload: yes 101 | -------------------------------------------------------------------------------- /roles/relay-phishing/files/opendkim.conf: -------------------------------------------------------------------------------- 1 | #Shource: https://github.com/mantvydasb/Red-Team-Infrastructure-Automation/blob/master/configs/opendkim.conf 2 | # This is a basic configuration that can easily be adapted to suit a standard 3 | # installation. For more advanced options, see opendkim.conf(5) and/or 4 | # /usr/share/doc/opendkim/examples/opendkim.conf.sample. 5 | 6 | # Log to syslog 7 | Syslog yes 8 | # Required to use local socket with MTAs that access the socket as a non- 9 | # privileged user (e.g. Postfix) 10 | UMask 007 11 | 12 | # Sign for example.com with key in /etc/dkimkeys/dkim.key using 13 | # selector '2007' (e.g. 2007._domainkey.example.com) 14 | #Domain example.com 15 | #KeyFile /etc/dkimkeys/dkim.key 16 | #Selector 2007 17 | 18 | # Commonly-used options; the commented-out versions show the defaults. 19 | #Canonicalization simple 20 | #Mode sv 21 | #SubDomains no 22 | 23 | # Socket smtp://localhost 24 | # 25 | # ## Socket socketspec 26 | # ## 27 | # ## Names the socket where this filter should listen for milter connections 28 | # ## from the MTA. Required. Should be in one of these forms: 29 | # ## 30 | # ## inet:port@address to listen on a specific interface 31 | # ## inet:port to listen on all interfaces 32 | # ## local:/path/to/socket to listen on a UNIX domain socket 33 | # 34 | #Socket inet:8892@localhost 35 | Socket local:/var/run/opendkim/opendkim.sock 36 | 37 | ## PidFile filename 38 | ### default (none) 39 | ### 40 | ### Name of the file where the filter should write its pid before beginning 41 | ### normal operations. 42 | # 43 | PidFile /var/run/opendkim/opendkim.pid 44 | 45 | 46 | # Always oversign From (sign using actual From and a null From to prevent 47 | # malicious signatures header fields (From and/or others) between the signer 48 | # and the verifier. From is oversigned by default in the Debian pacakge 49 | # because it is often the identity key used by reputation systems and thus 50 | # somewhat security sensitive. 51 | OversignHeaders From 52 | 53 | ## ResolverConfiguration filename 54 | ## default (none) 55 | ## 56 | ## Specifies a configuration file to be passed to the Unbound library that 57 | ## performs DNS queries applying the DNSSEC protocol. See the Unbound 58 | ## documentation at http://unbound.net for the expected content of this file. 59 | ## The results of using this and the TrustAnchorFile setting at the same 60 | ## time are undefined. 61 | ## In Debian, /etc/unbound/unbound.conf is shipped as part of the Suggested 62 | ## unbound package 63 | 64 | # ResolverConfiguration /etc/unbound/unbound.conf 65 | 66 | ## TrustAnchorFile filename 67 | ## default (none) 68 | ## 69 | ## Specifies a file from which trust anchor data should be read when doing 70 | ## DNS queries and applying the DNSSEC protocol. See the Unbound documentation 71 | ## at http://unbound.net for the expected format of this file. 72 | 73 | TrustAnchorFile /usr/share/dns/root.key 74 | 75 | ## Userid userid 76 | ### default (none) 77 | ### 78 | ### Change to user "userid" before starting normal operation? May include 79 | ### a group ID as well, separated from the userid by a colon. 80 | # 81 | UserID opendkim 82 | 83 | AutoRestart Yes 84 | AutoRestartRate 10/1h 85 | UMask 002 86 | Syslog yes 87 | SyslogSuccess Yes 88 | LogWhy Yes 89 | 90 | Canonicalization relaxed/simple 91 | 92 | ExternalIgnoreList refile:/etc/opendkim/TrustedHosts 93 | InternalHosts refile:/etc/opendkim/TrustedHosts 94 | KeyTable refile:/etc/opendkim/KeyTable 95 | SigningTable refile:/etc/opendkim/SigningTable 96 | 97 | Mode sv 98 | PidFile /var/run/opendkim/opendkim.pid 99 | SignatureAlgorithm rsa-sha256 100 | 101 | UserID opendkim:opendkim 102 | 103 | Socket inet:12345@localhost 104 | --------------------------------------------------------------------------------