├── ansible ├── playbooks │ ├── roles │ ├── attackiq.yml │ ├── atomic_red_team.yml │ ├── windows_dc.yml │ ├── windows_workstation.yml │ ├── splunk_server.yml │ └── phantom.yml ├── roles │ ├── sysmon │ │ ├── defaults │ │ │ └── main.yml │ │ ├── handlers │ │ │ └── main.yml │ │ ├── tasks │ │ │ ├── main.yml │ │ │ ├── windows-logging-registry.yml │ │ │ └── windows-sysmon.yml │ │ ├── meta │ │ │ └── main.yml │ │ └── templates │ │ │ ├── SysmonConfig.xml.j2 │ │ │ ├── SysmonConfig-Neo23x0-workstations.xml.j2 │ │ │ ├── SysmonConfig-Neo23x0-server.xml.j2 │ │ │ ├── SysmonConfig-Verbose.xml.j2 │ │ │ └── SysmonConfig-moti.xml.j2 │ ├── firedrill │ │ ├── defaults │ │ │ └── main.yaml │ │ └── tasks │ │ │ ├── main.yml │ │ │ └── install_firedrill.yml │ ├── atomic_red_team │ │ ├── defaults │ │ │ └── main.yaml │ │ ├── tasks │ │ │ ├── main.yml │ │ │ ├── install_art.yml │ │ │ └── run_art_test.yml │ │ └── files │ │ │ └── Install-AtomicRedTeam.ps1 │ ├── universal_forwarder │ │ ├── defaults │ │ │ └── main.yml │ │ ├── files │ │ │ ├── powershell_inputs.conf │ │ │ ├── sysmon_inputs.conf │ │ │ ├── atomic_red_team_execution_inputs.conf │ │ │ └── win_event_log_inputs.conf │ │ ├── handlers │ │ │ └── main.yml │ │ ├── templates │ │ │ └── inputs.conf.j2 │ │ └── tasks │ │ │ ├── collect_sysmon_logs.yml │ │ │ ├── main.yml │ │ │ ├── collect_windows_event_logs.yml │ │ │ ├── collect_powershell_logs.yml │ │ │ ├── collect_attack_simulation_logs.yml │ │ │ ├── install_splunk_sysmon_ta.yml │ │ │ ├── install_splunk_uf.yml │ │ │ ├── install_splunk_windows_ta.yml │ │ │ └── install_splunk_stream.yml │ ├── windows_dns_server │ │ ├── defaults │ │ │ └── main.yml │ │ ├── tasks │ │ │ ├── main.yaml │ │ │ ├── reboot.yml │ │ │ └── features.yml │ │ └── handlers │ │ │ └── main.yml │ ├── windows_domain_controller │ │ ├── defaults │ │ │ └── main.yml │ │ ├── tasks │ │ │ ├── main.yaml │ │ │ ├── reboot.yml │ │ │ └── create.yml │ │ └── handlers │ │ │ └── main.yml │ ├── windows_common │ │ ├── defaults │ │ │ └── main.yml │ │ ├── tasks │ │ │ ├── main.yml │ │ │ ├── chocolatey-components.yml │ │ │ ├── windows-components.yml │ │ │ ├── windows-disable-defender.yml │ │ │ └── windows-enable-ps-logging.yml │ │ └── meta │ │ │ └── main.yml │ ├── search_head │ │ ├── files │ │ │ ├── inputs.conf │ │ │ ├── indexes.conf │ │ │ └── datamodels.conf │ │ ├── handlers │ │ │ └── main.yml │ │ ├── tasks │ │ │ ├── main.yml │ │ │ ├── configure_indexes.yml │ │ │ ├── configure_inputs.yml │ │ │ ├── install_asx_app.yml │ │ │ ├── install_escu_app.yml │ │ │ ├── install_sysmon_ta.yml │ │ │ ├── install_stream_app.yml │ │ │ ├── install_windows_ta.yml │ │ │ ├── install_cim_app.yml │ │ │ └── splunk.yml │ │ └── README.md │ └── phantom │ │ ├── tasks │ │ ├── main.yml │ │ └── phantom.yml │ │ ├── README.md │ │ └── files │ │ └── change_phantom_password.py ├── README.md ├── ansible.cfg ├── inventory │ └── hosts.default └── vars │ ├── vars.yml │ └── vars.yml.default ├── docs ├── range.jpg ├── architecture.png └── CONTRIBUTING.md ├── .attack_range └── README.md ├── terraform ├── terraform.tfvars ├── variables.tf └── main.tf ├── .github ├── auto_assign.yml ├── config.yml └── stale.yml ├── .pre-commit-config.yaml ├── modules ├── logger.py └── parseconfig.py ├── vagrant ├── phantom │ └── Vagrantfile ├── splunk_server │ └── Vagrantfile ├── windows10 │ └── Vagrantfile ├── windows7 │ └── Vagrantfile ├── windows2016_dc │ └── Vagrantfile └── Vagrantfile ├── requirements.txt ├── attack_range.conf ├── default └── attack_range.conf.default ├── .gitignore ├── README.md └── attack_range.py /ansible/playbooks/roles: -------------------------------------------------------------------------------- 1 | ../roles -------------------------------------------------------------------------------- /ansible/roles/sysmon/defaults/main.yml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /ansible/roles/firedrill/defaults/main.yaml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /ansible/roles/atomic_red_team/defaults/main.yaml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /ansible/roles/universal_forwarder/defaults/main.yml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /ansible/roles/windows_dns_server/defaults/main.yml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /ansible/roles/windows_domain_controller/defaults/main.yml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /ansible/roles/windows_common/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | -------------------------------------------------------------------------------- /ansible/roles/firedrill/tasks/main.yml: -------------------------------------------------------------------------------- 1 | - include: install_firedrill.yml 2 | -------------------------------------------------------------------------------- /docs/range.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Agent00049/attack_range/develop/docs/range.jpg -------------------------------------------------------------------------------- /.attack_range/README.md: -------------------------------------------------------------------------------- 1 | #### directory used by ansible runner mainly for execution artifact storage 2 | -------------------------------------------------------------------------------- /ansible/roles/windows_dns_server/tasks/main.yaml: -------------------------------------------------------------------------------- 1 | - include: features.yml 2 | - include: reboot.yml 3 | -------------------------------------------------------------------------------- /ansible/roles/atomic_red_team/tasks/main.yml: -------------------------------------------------------------------------------- 1 | - include: install_art.yml 2 | - include: run_art_test.yml 3 | -------------------------------------------------------------------------------- /ansible/roles/windows_domain_controller/tasks/main.yaml: -------------------------------------------------------------------------------- 1 | - include: create.yml 2 | - include: reboot.yml 3 | -------------------------------------------------------------------------------- /docs/architecture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Agent00049/attack_range/develop/docs/architecture.png -------------------------------------------------------------------------------- /ansible/README.md: -------------------------------------------------------------------------------- 1 | # Attack Range Orchestration 2 | 3 | ### Getting Started 4 | * set variables edit `vars/vars.yml` 5 | -------------------------------------------------------------------------------- /ansible/roles/search_head/files/inputs.conf: -------------------------------------------------------------------------------- 1 | [default] 2 | host = splunk-server 3 | 4 | [splunktcp://9997] 5 | disabled = 0 6 | -------------------------------------------------------------------------------- /ansible/roles/search_head/handlers/main.yml: -------------------------------------------------------------------------------- 1 | - name: restart splunk 2 | service: name=splunk state=restarted 3 | become: yes 4 | -------------------------------------------------------------------------------- /ansible/roles/sysmon/handlers/main.yml: -------------------------------------------------------------------------------- 1 | - name: restart splunk 2 | win_command: C:\Program Files\SplunkUniversalForwarder\bin\splunk.exe restart 3 | 4 | -------------------------------------------------------------------------------- /ansible/ansible.cfg: -------------------------------------------------------------------------------- 1 | [defaults] 2 | roles_path = roles 3 | retry_files_enabled = False # Do not create them 4 | deprecation_warnings=False 5 | ask_pass=False 6 | -------------------------------------------------------------------------------- /ansible/roles/universal_forwarder/files/powershell_inputs.conf: -------------------------------------------------------------------------------- 1 | [WinEventLog://Microsoft-Windows-PowerShell/Operational] 2 | disabled = false 3 | index = win 4 | -------------------------------------------------------------------------------- /ansible/roles/universal_forwarder/files/sysmon_inputs.conf: -------------------------------------------------------------------------------- 1 | [WinEventLog://Microsoft-Windows-Sysmon/Operational] 2 | disabled = false 3 | renderXml = 1 4 | index = win 5 | -------------------------------------------------------------------------------- /ansible/roles/universal_forwarder/handlers/main.yml: -------------------------------------------------------------------------------- 1 | - name: restart splunk 2 | win_service: 3 | name: SplunkForwarder 4 | state: restarted 5 | 6 | - name: restart machine 7 | win_reboot: 8 | -------------------------------------------------------------------------------- /ansible/roles/windows_dns_server/handlers/main.yml: -------------------------------------------------------------------------------- 1 | - name: restart splunk 2 | win_service: 3 | name: SplunkForwarder 4 | state: restarted 5 | 6 | - name: restart machine 7 | win_reboot: 8 | -------------------------------------------------------------------------------- /ansible/roles/windows_domain_controller/handlers/main.yml: -------------------------------------------------------------------------------- 1 | - name: restart splunk 2 | win_service: 3 | name: SplunkForwarder 4 | state: restarted 5 | 6 | - name: restart machine 7 | win_reboot: 8 | -------------------------------------------------------------------------------- /ansible/roles/windows_common/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # need to wrap an if statement around this one 3 | # make it windows specific 4 | - include: windows-disable-defender.yml 5 | - include: windows-enable-ps-logging.yml 6 | -------------------------------------------------------------------------------- /ansible/roles/universal_forwarder/templates/inputs.conf.j2: -------------------------------------------------------------------------------- 1 | [streamfwd://streamfwd] 2 | splunk_stream_app_location = https://{{ splunk_indexer_ip }}:8000/en-us/custom/splunk_app_stream/ 3 | stream_forwarder_id = 4 | disabled = 0 5 | -------------------------------------------------------------------------------- /ansible/playbooks/attackiq.yml: -------------------------------------------------------------------------------- 1 | - hosts: all 2 | gather_facts: False 3 | # tasks: 4 | # - debug: 5 | # msg: "{{ hostvars[inventory_hostname] }}" 6 | roles: 7 | - firedrill 8 | vars_files: 9 | - ../vars/vars.yml 10 | -------------------------------------------------------------------------------- /ansible/roles/universal_forwarder/files/atomic_red_team_execution_inputs.conf: -------------------------------------------------------------------------------- 1 | [monitor://C:\AtomicRedTeam\atomic-red-team-master\execution-frameworks\Invoke-AtomicRedTeam\Invoke-AtomicTest-ExecutionLog.csv] 2 | disabled = false 3 | index = attack 4 | -------------------------------------------------------------------------------- /ansible/playbooks/atomic_red_team.yml: -------------------------------------------------------------------------------- 1 | - hosts: all 2 | gather_facts: False 3 | # tasks: 4 | # - debug: 5 | # msg: "{{ hostvars[inventory_hostname] }}" 6 | roles: 7 | - atomic_red_team 8 | vars_files: 9 | - ../vars/vars.yml 10 | -------------------------------------------------------------------------------- /ansible/roles/windows_dns_server/tasks/reboot.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: reboot | Rebooting Server 3 | win_reboot: 4 | reboot_timeout_sec: 3600 5 | when: > 6 | _windows_dns_server['restart_needed'] is defined and 7 | _windows_dns_server['restart_needed'] 8 | -------------------------------------------------------------------------------- /terraform/terraform.tfvars: -------------------------------------------------------------------------------- 1 | # AWS Keypair name is REQUIRED 2 | key_name = "attack-range-key-pair" 3 | aws_region = "us-west-2" 4 | ip_whitelist = ["0.0.0.0/0"] 5 | win_username = "Administrator" 6 | win_password = "myTempPassword123" 7 | private_key_path = "~/.ssh/id_rsa" 8 | -------------------------------------------------------------------------------- /ansible/playbooks/windows_dc.yml: -------------------------------------------------------------------------------- 1 | - hosts: all 2 | gather_facts: True 3 | roles: 4 | - windows_common 5 | - windows_dns_server 6 | - windows_domain_controller 7 | - universal_forwarder 8 | - sysmon 9 | vars_files: 10 | - ../vars/vars.yml 11 | -------------------------------------------------------------------------------- /ansible/roles/phantom/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # This playbook contains common tasks in this role 3 | 4 | - include: phantom.yml 5 | - name: Finished 6 | debug: msg="Access your Phantom instance at https://10.0.0.11:443 with username 'admin' and password '{{ phantom_pass }}'" 7 | -------------------------------------------------------------------------------- /ansible/roles/windows_dns_server/tasks/features.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: features | Installing Windows DNS Server 3 | win_feature: 4 | name: DNS 5 | state: present 6 | include_management_tools: yes 7 | include_sub_features: yes 8 | register: _windows_dns_server 9 | -------------------------------------------------------------------------------- /ansible/roles/windows_common/tasks/chocolatey-components.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Install Chocolately via Powershell 3 | win_shell: "iex ((new-object net.webclient).DownloadString('https://chocolatey.org/install.ps1'))" 4 | - name: Install notepadplusplus 5 | win_chocolatey: 6 | name: notepadplusplus -------------------------------------------------------------------------------- /ansible/playbooks/windows_workstation.yml: -------------------------------------------------------------------------------- 1 | - hosts: all 2 | gather_facts: True 3 | # tasks: 4 | # - debug: 5 | # msg: "{{ hostvars[inventory_hostname] }}" 6 | roles: 7 | - windows_common 8 | - universal_forwarder 9 | - sysmon 10 | vars_files: 11 | - ../vars/vars.yml 12 | -------------------------------------------------------------------------------- /ansible/roles/sysmon/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: Create ansible directories 4 | win_file: 5 | path: "{{ item }}" 6 | state: directory 7 | with_items: 8 | - "{{ win_temp_dir }}" 9 | - "{{ win_log_dir }}" 10 | 11 | - include: windows-sysmon.yml 12 | - include: windows-logging-registry.yml 13 | -------------------------------------------------------------------------------- /ansible/roles/windows_domain_controller/tasks/reboot.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: reboot | Rebooting Server 3 | win_reboot: 4 | reboot_timeout_sec: 3600 5 | shutdown_timeout_sec: 3600 6 | when: > 7 | _windows_domain_controller['reboot_required'] is defined and 8 | _windows_domain_controller['reboot_required'] 9 | -------------------------------------------------------------------------------- /.github/auto_assign.yml: -------------------------------------------------------------------------------- 1 | # Set to true to add reviewers to pull requests 2 | addReviewers: true 3 | 4 | # Set to true to add assignees to pull requests 5 | addAssignees: false 6 | 7 | # A list of reviewers to be added to pull requests (GitHub user name) 8 | reviewers: 9 | - d1vious 10 | - rvaldez617 11 | - patel-bhavin 12 | 13 | -------------------------------------------------------------------------------- /ansible/roles/firedrill/tasks/install_firedrill.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: Copy FireDrill 4 | win_copy: 5 | src: "{{ firedrill_binary_path }}" 6 | dest: "{{ firedrill_dst_location }}" 7 | when: install_firedrill 8 | 9 | - name: Install FireDrill 10 | win_command: "{{ firedrill_dst_location }} /S" 11 | when: install_firedrill 12 | -------------------------------------------------------------------------------- /ansible/roles/windows_common/tasks/windows-components.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Install the Visual C++ Redistributable 3 | win_package: 4 | path: "https://download.microsoft.com/download/9/3/F/93FCF1E7-E6A4-478B-96E7-D4B285925B00/vc_redist.x64.exe" 5 | product_id: '{CF2BEA3C-26EA-32F8-AA9B-331F7E34BA97}' 6 | arguments: /install /passive /norestart 7 | -------------------------------------------------------------------------------- /ansible/inventory/hosts.default: -------------------------------------------------------------------------------- 1 | aws-win-host ansible_ssh_host=PUBLICIP 2 | 3 | [win] 4 | aws-win-host 5 | 6 | [win:vars] 7 | ansible_connection=winrm 8 | ansible_ssh_port=5986 9 | ansible_ssh_user=Administrator 10 | ansible_ssh_pass=myTempPassword123 11 | ansible_winrm_transport=basic 12 | ansible_winrm_server_cert_validation=ignore 13 | ansible_winrm_read_timeout_sec=600 14 | -------------------------------------------------------------------------------- /ansible/playbooks/splunk_server.yml: -------------------------------------------------------------------------------- 1 | - hosts: all 2 | gather_facts: False 3 | pre_tasks: 4 | - name: Install python for Ansible 5 | raw: test -e /usr/bin/python || (sudo apt -y update && sudo apt install -y python-minimal) 6 | changed_when: False 7 | - setup: # aka gather_facts 8 | become: true 9 | roles: 10 | - search_head 11 | vars_files: 12 | - ../vars/vars.yml 13 | -------------------------------------------------------------------------------- /ansible/roles/sysmon/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | galaxy_info: 3 | role_name: win_sysmon 4 | author: Russ Nolen ported from juju4 5 | description: setup Sysmon on Windows system 6 | license: BSD 7 | min_ansible_version: 2.4 8 | platforms: 9 | - name: Windows 10 | versions: 11 | - 2012R2 12 | - Win10 13 | galaxy_tags: 14 | - system 15 | - security 16 | dependencies: [] 17 | -------------------------------------------------------------------------------- /ansible/roles/windows_common/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | galaxy_info: 3 | role_name: install_misc_software 4 | author: Russ Nolen rnolen@splunk.com 5 | description: Install some basic software 6 | license: BSD 7 | min_ansible_version: 2.4 8 | platforms: 9 | - name: Windows 10 | versions: 11 | - 2012R2 12 | - Win10 13 | galaxy_tags: 14 | - system 15 | - security 16 | dependencies: [] 17 | -------------------------------------------------------------------------------- /ansible/playbooks/phantom.yml: -------------------------------------------------------------------------------- 1 | - hosts: phantom 2 | gather_facts: False 3 | pre_tasks: 4 | - name: Install python for Ansible 5 | raw: test -e /usr/bin/python || (sudo apt -y update && sudo apt install -y python-minimal) 6 | changed_when: False 7 | - setup: # aka gather_facts 8 | become: true 9 | roles: 10 | - common 11 | - phantom 12 | vars_files: 13 | - ../vars/vars.yml 14 | - ~/.attack_range.yml 15 | 16 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | repos: 2 | - repo: https://github.com/pre-commit/pre-commit-hooks 3 | rev: v2.1.0 # Use the ref you want to point at 4 | hooks: 5 | - id: trailing-whitespace 6 | - id: check-executables-have-shebangs 7 | - id: check-json 8 | - id: check-symlinks 9 | - id: check-yaml 10 | - id: pretty-format-json 11 | args: [--autofix] 12 | - id: flake8 13 | args: [--max-line-length=131] 14 | - id: requirements-txt-fixer 15 | -------------------------------------------------------------------------------- /ansible/roles/search_head/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # This playbook contains common tasks in this role 3 | 4 | - include: splunk.yml 5 | - include: configure_inputs.yml 6 | - include: configure_indexes.yml 7 | - include: install_escu_app.yml 8 | - include: install_asx_app.yml 9 | - include: install_windows_ta.yml 10 | - include: install_cim_app.yml 11 | - include: install_sysmon_ta.yml 12 | when: sysmon is defined 13 | - include: install_stream_app.yml 14 | when: stream is defined 15 | -------------------------------------------------------------------------------- /ansible/roles/universal_forwarder/tasks/collect_sysmon_logs.yml: -------------------------------------------------------------------------------- 1 | - name: Create folder directory for inputs configuration 2 | win_file: 3 | path: "{{ item }}" 4 | state: directory 5 | with_items: 6 | - 'C:\Program Files\SplunkUniversalForwarder\etc\apps\sysmon_inputs_app\local' 7 | 8 | - name: Copy inputs.conf configuration 9 | win_copy: 10 | src: sysmon_inputs.conf 11 | dest: 'C:\Program Files\SplunkUniversalForwarder\etc\apps\sysmon_inputs_app\local\inputs.conf' 12 | -------------------------------------------------------------------------------- /ansible/roles/universal_forwarder/tasks/main.yml: -------------------------------------------------------------------------------- 1 | 2 | - include: install_splunk_uf.yml 3 | - include: collect_windows_event_logs.yml 4 | - include: collect_powershell_logs.yml 5 | - include: collect_attack_simulation_logs.yml 6 | - include: collect_sysmon_logs.yml 7 | when: sysmon is defined 8 | # - include: install_splunk_windows_ta.yml 9 | # - include: install_splunk_sysmon_ta.yml 10 | # when: sysmon is defined 11 | # - include: install_splunk_stream.yml 12 | # when: stream is defined 13 | -------------------------------------------------------------------------------- /ansible/roles/universal_forwarder/tasks/collect_windows_event_logs.yml: -------------------------------------------------------------------------------- 1 | - name: Create folder directory for inputs configuration 2 | win_file: 3 | path: "{{ item }}" 4 | state: directory 5 | with_items: 6 | - 'C:\Program Files\SplunkUniversalForwarder\etc\apps\win_inputs_app\local' 7 | 8 | - name: Copy inputs.conf configuration 9 | win_copy: 10 | src: win_event_log_inputs.conf 11 | dest: 'C:\Program Files\SplunkUniversalForwarder\etc\apps\win_inputs_app\local\inputs.conf' 12 | -------------------------------------------------------------------------------- /ansible/roles/universal_forwarder/tasks/collect_powershell_logs.yml: -------------------------------------------------------------------------------- 1 | - name: Create folder directory for inputs configuration 2 | win_file: 3 | path: "{{ item }}" 4 | state: directory 5 | with_items: 6 | - 'C:\Program Files\SplunkUniversalForwarder\etc\apps\powershell_inputs_app\local' 7 | 8 | - name: Copy inputs.conf configuration 9 | win_copy: 10 | src: powershell_inputs.conf 11 | dest: 'C:\Program Files\SplunkUniversalForwarder\etc\apps\powershell_inputs_app\local\inputs.conf' 12 | -------------------------------------------------------------------------------- /ansible/roles/universal_forwarder/tasks/collect_attack_simulation_logs.yml: -------------------------------------------------------------------------------- 1 | - name: Create folder directory for inputs configuration 2 | win_file: 3 | path: "{{ item }}" 4 | state: directory 5 | with_items: 6 | - 'C:\Program Files\SplunkUniversalForwarder\etc\apps\attack_simulation_inputs_app\local' 7 | 8 | - name: Copy inputs.conf configuration 9 | win_copy: 10 | src: atomic_red_team_execution_inputs.conf 11 | dest: 'C:\Program Files\SplunkUniversalForwarder\etc\apps\attack_simulation_inputs_app\local\inputs.conf' 12 | -------------------------------------------------------------------------------- /ansible/roles/search_head/tasks/configure_indexes.yml: -------------------------------------------------------------------------------- 1 | 2 | - name: Create folder directory for indexes configuration 3 | file: 4 | path: "{{ item }}" 5 | state: directory 6 | owner: splunk 7 | group: splunk 8 | recurse: yes 9 | with_items: 10 | - /opt/splunk/etc/apps/indexes_app/local/ 11 | 12 | - name: copy indexes.conf to splunk server 13 | copy: 14 | src: indexes.conf 15 | dest: /opt/splunk/etc/apps/indexes_app/local/indexes.conf 16 | owner: splunk 17 | group: splunk 18 | notify: restart splunk 19 | -------------------------------------------------------------------------------- /ansible/roles/search_head/tasks/configure_inputs.yml: -------------------------------------------------------------------------------- 1 | 2 | - name: Create folder directory for inputs configuration 3 | file: 4 | path: "{{ item }}" 5 | state: directory 6 | owner: splunk 7 | group: splunk 8 | recurse: yes 9 | with_items: 10 | - /opt/splunk/etc/apps/inputs_app/local/ 11 | 12 | - name: copy inputs.conf 13 | tags: 14 | - install 15 | - security 16 | copy: 17 | src: inputs.conf 18 | dest: /opt/splunk/etc/apps/inputs_app/local/inputs.conf 19 | owner: splunk 20 | group: splunk 21 | notify: restart splunk 22 | -------------------------------------------------------------------------------- /ansible/roles/atomic_red_team/tasks/install_art.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: Check we have installed Atomic Red Team 4 | win_stat: 5 | path: "{{ art_module_dst_location }}" 6 | register: atr_folder 7 | 8 | - name: Copy Atomic Red Team PS module 9 | win_copy: 10 | src: "{{ art_module_path }}" 11 | dest: "{{ art_module_dst_location }}" 12 | when: install_art and atr_folder.stat.exists == False 13 | 14 | - name: Install Atomic Red Team PS Module 15 | win_shell: "{{art_module_dst_location}} -Verbose" 16 | when: install_art and atr_folder.stat.exists == False 17 | 18 | -------------------------------------------------------------------------------- /.github/config.yml: -------------------------------------------------------------------------------- 1 | # Configuration for request-info - https://github.com/behaviorbot/request-info 2 | 3 | # *Required* Comment to reply with 4 | requestInfoReplyComment: > 5 | We would appreciate it if you could provide us with more info about this issue/pr! 6 | 7 | # *OPTIONAL* default titles to check against for lack of descriptiveness 8 | # MUST BE ALL LOWERCASE 9 | requestInfoDefaultTitles: 10 | - update readme.md 11 | - updates 12 | 13 | 14 | # *OPTIONAL* Label to be added to Issues and Pull Requests with insufficient information given 15 | requestInfoLabelToAdd: needs-more-info 16 | -------------------------------------------------------------------------------- /ansible/roles/universal_forwarder/tasks/install_splunk_sysmon_ta.yml: -------------------------------------------------------------------------------- 1 | 2 | - name: download Sysmon TA from S3 bucket 3 | win_get_url: 4 | url: 'https://attack-range-appbinaries.s3-us-west-2.amazonaws.com/{{ splunk_sysmon_ta }}' 5 | dest: C:\sysmon-ta.tgz 6 | 7 | - name: untar Sysmon TA 8 | win_unzip: 9 | src: C:\sysmon-ta.tgz 10 | dest: C:\Program Files\SplunkUniversalForwarder\etc\apps\ 11 | 12 | - name: Install Sysmon TA 13 | win_unzip: 14 | src: C:\Program Files\SplunkUniversalForwarder\etc\apps\sysmon-ta.tar 15 | dest: C:\Program Files\SplunkUniversalForwarder\etc\apps\ 16 | delete_archive: yes 17 | notify: restart machine 18 | -------------------------------------------------------------------------------- /ansible/roles/universal_forwarder/tasks/install_splunk_uf.yml: -------------------------------------------------------------------------------- 1 | 2 | - name: Download Splunk UF from Splunk website 3 | win_shell: | 4 | [Net.ServicePointManager]::SecurityProtocol = "tls12, tls11, tls" 5 | (New-Object System.Net.WebClient).DownloadFile("{{ splunk_uf_win_url }}", "C:\splunkuf.msi") 6 | 7 | - name: Install Splunk_UF MSI 8 | win_package: 9 | path: C:\splunkuf.msi 10 | arguments: 'WINEVENTLOG_SEC_ENABLE=0 WINEVENTLOG_SYS_ENABLE=0 WINEVENTLOG_APP_ENABLE=0 SPLUNKPASSWORD={{ splunk_pass }} RECEIVING_INDEXER="{{ splunk_indexer_ip }}:9997" AGREETOLICENSE=YES /quiet' 11 | 12 | - name: Start Splunk 13 | win_service: 14 | name: SplunkForwarder 15 | state: started 16 | -------------------------------------------------------------------------------- /.github/stale.yml: -------------------------------------------------------------------------------- 1 | # Number of days of inactivity before an issue becomes stale 2 | daysUntilStale: 60 3 | # Number of days of inactivity before a stale issue is closed 4 | daysUntilClose: 7 5 | # Issues with these labels will never be considered stale 6 | exemptLabels: 7 | - pinned 8 | - security 9 | # Label to use when marking an issue as stale 10 | staleLabel: wontfix 11 | # Comment to post when marking an issue as stale. Set to `false` to disable 12 | markComment: > 13 | This issue has been automatically marked as stale because it has not had 14 | recent activity. It will be closed if no further activity occurs. Thank you 15 | for your contributions. 16 | # Comment to post when closing a stale issue. Set to `false` to disable 17 | closeComment: false 18 | -------------------------------------------------------------------------------- /ansible/roles/universal_forwarder/tasks/install_splunk_windows_ta.yml: -------------------------------------------------------------------------------- 1 | 2 | - name: download Windows TA from S3 bucket 3 | win_get_url: 4 | url: '{{s3_bucket_url}}/{{ splunk_windows_ta }}' 5 | dest: C:\windows-ta.tgz 6 | 7 | - name: Add powershell module PSCX required by Ansible's win_unzip 8 | win_psmodule: 9 | name: Pscx 10 | state: present 11 | allow_clobber: True 12 | 13 | - name: untar windows TA 14 | win_unzip: 15 | src: C:\windows-ta.tgz 16 | dest: C:\Program Files\SplunkUniversalForwarder\etc\apps\ 17 | 18 | - name: Install windows TA 19 | win_unzip: 20 | src: C:\Program Files\SplunkUniversalForwarder\etc\apps\windows-ta.tar 21 | dest: C:\Program Files\SplunkUniversalForwarder\etc\apps\ 22 | delete_archive: yes 23 | notify: restart machine 24 | -------------------------------------------------------------------------------- /ansible/roles/search_head/tasks/install_asx_app.yml: -------------------------------------------------------------------------------- 1 | # - name: Check if ESCU App exists 2 | # stat: 3 | # path: /opt/splunk/etc/apps/DA-ESS-ContentUpdate 4 | # register: escu_app 5 | 6 | - name: download ASX app from S3 bucket 7 | get_url: 8 | url: '{{ s3_bucket_url }}/{{ splunk_asx_app }}' 9 | dest: /tmp/asx_app.tgz 10 | # when: escu_app.stat.exists == False 11 | 12 | - name: Install asx app via REST 13 | uri: 14 | url: "https://127.0.0.1:8089/services/apps/local" 15 | method: POST 16 | user: "admin" 17 | password: "{{ splunk_pass }}" 18 | validate_certs: false 19 | body: "name=/tmp/asx_app.tgz&update=true&filename=true" 20 | headers: 21 | Content-Type: "application/x-www-form-urlencoded" 22 | status_code: [ 200, 201 ] 23 | timeout: 30 24 | notify: restart splunk 25 | # when: escu_app.stat.exists == False 26 | -------------------------------------------------------------------------------- /ansible/roles/search_head/tasks/install_escu_app.yml: -------------------------------------------------------------------------------- 1 | - name: Check if ESCU App exists 2 | stat: 3 | path: /opt/splunk/etc/apps/DA-ESS-ContentUpdate 4 | register: escu_app 5 | 6 | - name: download ESCU app from S3 bucket 7 | get_url: 8 | url: '{{ s3_bucket_url }}/{{ splunk_escu_app }}' 9 | dest: /tmp/escu_app.tgz 10 | when: escu_app.stat.exists == False 11 | 12 | - name: Install escu app via REST 13 | uri: 14 | url: "https://127.0.0.1:8089/services/apps/local" 15 | method: POST 16 | user: "admin" 17 | password: "{{ splunk_pass }}" 18 | validate_certs: false 19 | body: "name=/tmp/escu_app.tgz&update=true&filename=true" 20 | headers: 21 | Content-Type: "application/x-www-form-urlencoded" 22 | status_code: [ 200, 201 ] 23 | timeout: 30 24 | when: escu_app.stat.exists == False 25 | notify: restart splunk 26 | -------------------------------------------------------------------------------- /modules/logger.py: -------------------------------------------------------------------------------- 1 | import logging 2 | 3 | def setup_logging(LOG_PATH,LOG_LEVEL): 4 | """Creates a shared logging object for the application""" 5 | 6 | # create logging object 7 | logger = logging.getLogger('attack_range') 8 | logger.setLevel(LOG_LEVEL) 9 | # create a file and console handler 10 | fh = logging.FileHandler(LOG_PATH) 11 | fh.setLevel(LOG_LEVEL) 12 | ch = logging.StreamHandler() 13 | ch.setLevel(LOG_LEVEL) 14 | # create a logging format 15 | formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(name)s - %(message)s') 16 | fh.setFormatter(formatter) 17 | ch.setFormatter(formatter) 18 | # add the handlers to the logger 19 | logger.addHandler(fh) 20 | logger.addHandler(ch) 21 | return logger 22 | 23 | def get(): 24 | logger = logging.getLogger('attack_range') 25 | return logger 26 | -------------------------------------------------------------------------------- /ansible/roles/search_head/tasks/install_sysmon_ta.yml: -------------------------------------------------------------------------------- 1 | - name: Check if sysmon ta exists 2 | stat: 3 | path: /opt/splunk/etc/apps/TA-microsoft-sysmon 4 | register: sysmon_ta 5 | 6 | - name: download Sysmon TA from S3 bucket 7 | get_url: 8 | url: '{{ s3_bucket_url }}/{{ splunk_sysmon_ta }}' 9 | dest: /tmp/sysmon_ta.tgz 10 | when: sysmon_ta.stat.exists == False 11 | 12 | - name: Install sysmon ta app via REST 13 | uri: 14 | url: "https://127.0.0.1:8089/services/apps/local" 15 | method: POST 16 | user: "admin" 17 | password: "{{ splunk_pass }}" 18 | validate_certs: false 19 | body: "name=/tmp/sysmon_ta.tgz&update=true&filename=true" 20 | headers: 21 | Content-Type: "application/x-www-form-urlencoded" 22 | status_code: [ 200, 201 ] 23 | timeout: 30 24 | when: sysmon_ta.stat.exists == False 25 | notify: restart splunk 26 | -------------------------------------------------------------------------------- /ansible/roles/search_head/tasks/install_stream_app.yml: -------------------------------------------------------------------------------- 1 | - name: Check if stream app exists 2 | stat: 3 | path: /opt/splunk/etc/apps/Splunk_TA_stream 4 | register: stream_app 5 | 6 | - name: download Stream app from S3 bucket 7 | get_url: 8 | url: '{{ s3_bucket_url }}/{{ splunk_stream_app }}' 9 | dest: /tmp/stream_app.tgz 10 | when: stream_app.stat.exists == False 11 | 12 | - name: Install stream app via REST 13 | uri: 14 | url: "https://127.0.0.1:8089/services/apps/local" 15 | method: POST 16 | user: "admin" 17 | password: "{{ splunk_pass }}" 18 | validate_certs: false 19 | body: "name=/tmp/stream_app.tgz&update=true&filename=true" 20 | headers: 21 | Content-Type: "application/x-www-form-urlencoded" 22 | status_code: [ 200, 201 ] 23 | timeout: 30 24 | when: stream_app.stat.exists == False 25 | notify: restart splunk 26 | -------------------------------------------------------------------------------- /ansible/roles/search_head/tasks/install_windows_ta.yml: -------------------------------------------------------------------------------- 1 | - name: Check if windows ta exists 2 | stat: 3 | path: /opt/splunk/etc/apps/Splunk_TA_windows 4 | register: windows_ta 5 | 6 | - name: download Windows TA from S3 bucket 7 | get_url: 8 | url: '{{ s3_bucket_url }}/{{ splunk_windows_ta }}' 9 | dest: /tmp/windows_ta.tgz 10 | when: windows_ta.stat.exists == False 11 | 12 | - name: Install windows TA app via REST 13 | uri: 14 | url: "https://127.0.0.1:8089/services/apps/local" 15 | method: POST 16 | user: "admin" 17 | password: "{{ splunk_pass }}" 18 | validate_certs: false 19 | body: "name=/tmp/windows_ta.tgz&update=true&filename=true" 20 | headers: 21 | Content-Type: "application/x-www-form-urlencoded" 22 | status_code: [ 200, 201 ] 23 | timeout: 30 24 | when: windows_ta.stat.exists == False 25 | notify: restart splunk 26 | -------------------------------------------------------------------------------- /vagrant/phantom/Vagrantfile: -------------------------------------------------------------------------------- 1 | VM_NAME= "phantom" 2 | Vagrant.configure("2") do |config| 3 | config.vm.define "phantom" do |config| 4 | config.vm.box = "centos/7" 5 | config.vm.hostname = "#{VM_NAME}" 6 | config.vm.boot_timeout = 600 7 | #config.vm.network "forwarded_port", guest: 443, host: 8443, protocol: "tcp" 8 | config.vm.network :private_network, ip: "10.0.0.11" 9 | 10 | config.vm.provision "ansible" do |ansible| 11 | ansible.playbook = "../../ansible/playbooks/phantom.yml" 12 | ansible.config_file = "../../ansible/ansible.cfg" 13 | ansible.compatibility_mode = "2.0" 14 | end 15 | 16 | config.vm.provider "virtualbox" do |vb, override| 17 | vb.gui = true 18 | vb.name = "#{VM_NAME}" 19 | vb.customize ["modifyvm", :id, "--memory", 4096] 20 | vb.customize ["modifyvm", :id, "--cpus", 2] 21 | end 22 | end 23 | end 24 | -------------------------------------------------------------------------------- /ansible/roles/windows_common/tasks/windows-disable-defender.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | # - name: Collect only facts returned by facter 4 | # setup: 5 | # register: ansible_facts 6 | # 7 | # - name: Print anisble_facts 8 | # debug: 9 | # var: ansible_facts 10 | 11 | - debug: 12 | msg: "{{ ansible_distribution }}" 13 | 14 | - name: Disable Windows Defender 15 | ignore_errors: yes 16 | win_regedit: 17 | key: "HKLM:\\SOFTWARE\\Policies\\Microsoft\\Windows Defender\\Real-Time Protection" 18 | value: DisableRealTimeMonitoring 19 | datatype: dword 20 | data: 1 21 | when: ansible_distribution == "Microsoft Windows 10 Enterprise Evaluation" 22 | 23 | - name: Disbale Windows Defender in Windows Server windows_2016_dc 24 | win_shell: 'Uninstall-WindowsFeature -Name Windows-Defender' 25 | when: ansible_distribution == "Microsoft Windows Server 2016 Datacenter" 26 | 27 | - name: restart machine 28 | win_reboot: 29 | -------------------------------------------------------------------------------- /vagrant/splunk_server/Vagrantfile: -------------------------------------------------------------------------------- 1 | VM_NAME= "splunk-server-#{SecureRandom.hex(2)}" 2 | Vagrant.configure("2") do |config| 3 | config.vm.define "splunk-server" do |config| 4 | config.vm.box = "generic/ubuntu1804" 5 | config.vm.hostname = "#{VM_NAME}" 6 | config.vm.boot_timeout = 600 7 | config.vm.network "forwarded_port", guest: 8000, host: 8000, protocol: "tcp" 8 | config.vm.network :private_network, ip: "10.0.0.10" 9 | 10 | config.vm.provision "ansible" do |ansible| 11 | ansible.playbook = "../../ansible/playbooks/splunk_server.yml" 12 | ansible.config_file = "../../ansible/ansible.cfg" 13 | ansible.compatibility_mode = "2.0" 14 | end 15 | 16 | config.vm.provider "virtualbox" do |vb, override| 17 | vb.gui = true 18 | vb.name = "#{VM_NAME}" 19 | vb.customize ["modifyvm", :id, "--memory", 6000] 20 | vb.customize ["modifyvm", :id, "--cpus", 4] 21 | end 22 | end 23 | end 24 | -------------------------------------------------------------------------------- /modules/parseconfig.py: -------------------------------------------------------------------------------- 1 | import configparser 2 | import collections 3 | import sys 4 | 5 | class parser: 6 | def __init__(self): 7 | self.settings = collections.defaultdict(dict) 8 | 9 | def load_conf(self,CONFIG_PATH): 10 | """Provided a config file path and a collections of type dict, 11 | will return that collections with all the settings in it""" 12 | config = configparser.RawConfigParser() 13 | config.read('default/attack_range.conf.default') 14 | config.read(CONFIG_PATH) 15 | sections = config.sections() 16 | 17 | for section in config.sections(): 18 | for key in config[section]: 19 | try: 20 | self.settings[key] = config.get(section, key) 21 | except Exception as e: 22 | print("ERROR - with configuration file at {0} failed with error {1}".format(CONFIG_PATH, e)) 23 | sys.exit(1) 24 | return self.settings 25 | -------------------------------------------------------------------------------- /ansible/roles/atomic_red_team/tasks/run_art_test.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: Run all Atomic Red Team Tests 4 | win_shell: | 5 | Import-Module c:\AtomicRedTeam\atomic-red-team-master\execution-frameworks\Invoke-AtomicRedTeam\Invoke-AtomicRedTeam\Invoke-AtomicRedTeam.psm1 6 | cd c:\AtomicRedTeam\atomic-red-team-master\execution-frameworks\Invoke-AtomicRedTeam\ 7 | Invoke-AtomicTest All -Force -PathToAtomicsFolder C:\AtomicRedTeam\atomic-red-team-master\atomics 8 | when: art_run_all_test 9 | 10 | - name: Run specified Atomic Red Team Technique 11 | win_shell: | 12 | Import-Module c:\AtomicRedTeam\atomic-red-team-master\execution-frameworks\Invoke-AtomicRedTeam\Invoke-AtomicRedTeam\Invoke-AtomicRedTeam.psm1 13 | cd c:\AtomicRedTeam\atomic-red-team-master\execution-frameworks\Invoke-AtomicRedTeam\ 14 | Invoke-AtomicTest "{{ item }}" -PathToAtomicsFolder C:\AtomicRedTeam\atomic-red-team-master\atomics 15 | with_items: "{{ art_run_technique }}" 16 | when: art_run_technique is defined and (art_run_technique|length>0) 17 | -------------------------------------------------------------------------------- /ansible/roles/universal_forwarder/tasks/install_splunk_stream.yml: -------------------------------------------------------------------------------- 1 | - name: Check we have downloaded stream 2 | win_stat: 3 | path: C:\splunk-stream.zip 4 | register: stream_zip 5 | 6 | - name: Download Stream TA from S3 bucket 7 | when: stream_zip.stat.exists == False 8 | win_shell: | 9 | [Net.ServicePointManager]::SecurityProtocol = "tls12, tls11, tls" 10 | (New-Object System.Net.WebClient).DownloadFile("{{ s3_bucket_url }}/{{ splunk_stream_ta }}", "C:\splunk-stream.zip") 11 | 12 | - name: Check we have unzip streams TA 13 | win_stat: 14 | path: "C:\\Program Files\\SplunkUniversalForwarder\\etc\\apps\\Splunk_TA_stream" 15 | register: stream_ta 16 | 17 | - name: Unzip Stream App 18 | win_unzip: 19 | src: C:\splunk-stream.zip 20 | dest: "C:\\Program Files\\SplunkUniversalForwarder\\etc\\apps\\" 21 | when: stream_ta.stat.exists == False 22 | 23 | - name: Copy Stream Config File 24 | win_template: 25 | src: inputs.conf.j2 26 | dest: "C:\\Program Files\\SplunkUniversalForwarder\\etc\\apps\\Splunk_TA_stream\\local\\inputs.conf" 27 | -------------------------------------------------------------------------------- /ansible/roles/windows_common/tasks/windows-enable-ps-logging.yml: -------------------------------------------------------------------------------- 1 | # - name: Enable Windows Scriptblock Logging 2 | # win_shell: | 3 | # New-Item -Path "HKLM:\SOFTWARE\Wow6432Node\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging" -Force 4 | # Set-ItemProperty -Path "HKLM:\SOFTWARE\Wow6432Node\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging" -Name "EnableScriptBlockLogging" -Value 1 -Force 5 | # # when: ansible_distribution == "Microsoft Windows Server 2016 Datacenter" 6 | 7 | - name: Enable Windows Scriptblock Logging 8 | ignore_errors: yes 9 | win_regedit: 10 | key: "HKLM:\\Software\\Policies\\Microsoft\\Windows\\PowerShell\\ScriptBlockLogging" 11 | value: EnableScriptBlockLogging 12 | datatype: dword 13 | data: 1 14 | 15 | - name: Enable Windows Scriptblock Logging 16 | ignore_errors: yes 17 | win_regedit: 18 | key: "HKLM:\\Software\\Policies\\Microsoft\\Windows\\PowerShell\\ScriptBlockLogging" 19 | value: EnableScriptBlockInvocationLogging 20 | datatype: dword 21 | data: 1 22 | 23 | - name: restart machine 24 | win_reboot: 25 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | ansible==2.9.2 2 | ansible-runner==1.4.4 3 | apipkg==1.5 4 | atomicwrites==1.3.0 5 | attrs==19.3.0 6 | bcrypt==3.1.7 7 | boto3==1.10.35 8 | botocore==1.13.35 9 | certifi==2019.9.11 10 | cffi==1.13.2 11 | chardet==3.0.4 12 | configparser==4.0.2 13 | contextlib2==0.6.0.post1 14 | cryptography==2.8 15 | docutils==0.15.2 16 | execnet==1.7.1 17 | idna==2.8 18 | importlib-metadata==0.23 19 | Jinja2==2.10.3 20 | jmespath==0.9.4 21 | lockfile==0.12.2 22 | MarkupSafe==1.1.1 23 | mock==3.0.5 24 | more-itertools==8.0.2 25 | ntlm-auth==1.4.0 26 | packaging==19.2 27 | paramiko==2.6.0 28 | path.py==12.4.0 29 | pexpect==4.7.0 30 | pluggy==0.13.1 31 | psutil==5.6.7 32 | ptyprocess==0.6.0 33 | py==1.8.0 34 | pycparser==2.19 35 | PyNaCl==1.3.0 36 | pyparsing==2.4.5 37 | pytest==5.3.1 38 | python-daemon==2.2.4 39 | python-dateutil==2.8.1 40 | python-terraform==0.10.1 41 | python-vagrant==0.5.15 42 | pywinrm==0.4.1 43 | PyYAML==5.1.2 44 | requests==2.22.0 45 | requests-ntlm==1.1.0 46 | s3transfer==0.2.1 47 | six==1.13.0 48 | tabulate==0.8.6 49 | termcolor==1.1.0 50 | urllib3==1.25.7 51 | wcwidth==0.1.7 52 | wget==3.2 53 | xmltodict==0.12.0 54 | zipp==0.6.0 55 | -------------------------------------------------------------------------------- /attack_range.conf: -------------------------------------------------------------------------------- 1 | [global] 2 | log_path = attack_range.log 3 | log_level = INFO 4 | 5 | [range_settings] 6 | key_name = attack-range-key-pair 7 | ip_whitelist = ["0.0.0.0/0"] 8 | win_password = myTempPassword123 9 | private_key_path = ~/.ssh/id_rsa 10 | 11 | [splunk_settings] 12 | splunk_admin_password = changeme 13 | splunk_url = https://www.splunk.com/page/download_track?file=7.3.2/linux/splunk-7.3.2-c60db69f8e32-Linux-x86_64.tgz&ac=&wget=true&name=wget&platform=Linux&architecture=x86_64&version=7.3.2&product=splunk&typed=release 14 | splunk_binary = splunk-7.3.2-c60db69f8e32-Linux-x86_64.tgz 15 | 16 | # s3 bucket where the Splunk TA's are located 17 | s3_bucket_url = https://attack-range-appbinaries.s3-us-west-2.amazonaws.com 18 | splunk_windows_ta = splunk-add-on-for-microsoft-windows_600.tgz 19 | splunk_sysmon_ta = add-on-for-microsoft-sysmon_800.tgz 20 | splunk_stream_ta = Splunk_TA_stream.zip 21 | splunk_stream_app = splunk-stream_713.tgz 22 | splunk_cim_app = splunk-common-information-model-cim_4130.tgz 23 | splunk_escu_app = DA-ESS-ContentUpdate-v1.0.41.tar.gz 24 | splunk_asx_app = Splunk_Analytic_Story_Execution-latest.tar.gz 25 | 26 | 27 | [simulation] 28 | simulation_engine = atomic_red_team 29 | simulation_technique = '' 30 | -------------------------------------------------------------------------------- /ansible/roles/phantom/tasks/phantom.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Install Phantom on CentOS/RHEL using RPMs from repo.phantom.us 3 | 4 | - name: checking if phantom is installed in /opt/ 5 | tags: install 6 | stat: path=/opt/phantom 7 | register: phantom_path 8 | 9 | - name: is phantom installed? 10 | tags: install 11 | debug: msg='phantom is already installed under /opt/phantom' 12 | when: phantom_path.stat.exists 13 | 14 | - name: install phantom repo 15 | shell: rpm -Uvh {{phantom_repo_url}} 16 | when: phantom_path.stat.exists == false 17 | 18 | - name: install phantom packages 19 | # we need to pipe my.phantom.us creds into the install script to do yum authentication 20 | # expect this to take about 5 minutes to install phantom (even without any apps) 21 | shell: printf '{{phantom_community_user}}\n{{phantom_community_pass}}' | /opt/phantom/bin/phantom_setup.sh install --no-prompt --without-apps 22 | args: 23 | creates: /var/log/phantom/initialize_log 24 | 25 | - name: drop password changer 26 | copy: 27 | src: change_phantom_password.py 28 | dest: /root/change_phantom_password.py 29 | 30 | - name: change phantom password 31 | shell: phenv python /root/change_phantom_password.py --new-pass {{phantom_pass}} 32 | 33 | -------------------------------------------------------------------------------- /ansible/roles/sysmon/tasks/windows-logging-registry.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: WINEVT Channels Event Log Enabled 4 | win_regedit: 5 | key: "HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\WINEVT\\Channels\\{{ item }}" 6 | value: Enabled 7 | datatype: dword 8 | data: 1 9 | with_items: "{{ win_sysmon_eventlog_channels }}" 10 | 11 | - debug: var=win_eventlog_maxsize 12 | - name: WINEVT Channels Event Log size review 13 | win_regedit: 14 | key: "HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\WINEVT\\Channels\\{{ item }}" 15 | value: MaxSize 16 | datatype: dword 17 | data: "{{ win_eventlog_maxsize }}" 18 | with_items: "{{ win_sysmon_eventlog_channels }}" 19 | 20 | - name: WINEVT Channels Event Log retention review 21 | win_regedit: 22 | key: "HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\WINEVT\\Channels\\{{ item }}" 23 | value: Retention 24 | datatype: dword 25 | data: "{{ win_eventlog_retention }}" 26 | with_items: "{{ win_sysmon_eventlog_channels }}" 27 | 28 | - name: Check Sysmon Logs channel registry entry 29 | win_reg_stat: 30 | path: "HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\WINEVT\\Channels\\{{ item }}" 31 | with_items: "{{ win_sysmon_eventlog_channels }}" 32 | register: logreg 33 | -------------------------------------------------------------------------------- /default/attack_range.conf.default: -------------------------------------------------------------------------------- 1 | # DO NOT CHANGE THIS FILE 2 | 3 | [global] 4 | log_path = attack_range.log 5 | log_level = INFO 6 | 7 | [range_settings] 8 | key_name = attack-range-key-pair 9 | ip_whitelist = ["0.0.0.0/0"] 10 | win_password = myTempPassword123 11 | private_key_path = ~/.ssh/id_rsa 12 | 13 | [splunk_settings] 14 | splunk_url = https://www.splunk.com/page/download_track?file=7.3.2/linux/splunk-7.3.2-c60db69f8e32-Linux-x86_64.tgz&ac=&wget=true&name=wget&platform=Linux&architecture=x86_64&version=7.3.2&product=splunk&typed=release 15 | splunk_binary = splunk-7.3.2-c60db69f8e32-Linux-x86_64.tgz 16 | splunk_pass = changeme 17 | 18 | # s3 bucket where the Splunk TA's are located 19 | s3_bucket_url = https://attack-range-appbinaries.s3-us-west-2.amazonaws.com 20 | splunk_admin_password = changeme 21 | splunk_windows_ta = splunk-add-on-for-microsoft-windows_600.tgz 22 | splunk_sysmon_ta = add-on-for-microsoft-sysmon_800.tgz 23 | splunk_stream_ta = Splunk_TA_stream.zip 24 | splunk_stream_app = splunk-stream_713.tgz 25 | splunk_cim_app = splunk-common-information-model-cim_4130.tgz 26 | splunk_escu_app = DA-ESS-ContentUpdate-v1.0.41.tar.gz 27 | splunk_asx_app = Splunk_Analytic_Story_Execution-latest.tar.gz 28 | 29 | 30 | [simulation] 31 | simulation_engine = atomic_red_team 32 | simulation_technique = '' 33 | -------------------------------------------------------------------------------- /vagrant/windows10/Vagrantfile: -------------------------------------------------------------------------------- 1 | VM_NAME= "win10-workstation-#{SecureRandom.hex(2)}" 2 | Vagrant.configure("2") do |config| 3 | config.vm.define "win10" do |config| 4 | config.vm.box = "d1vious/windows10" 5 | config.vm.hostname = "#{VM_NAME}" 6 | config.vm.boot_timeout = 600 7 | config.vm.communicator = "winrm" 8 | config.winrm.basic_auth_only = true 9 | config.winrm.timeout = 300 10 | config.winrm.retry_limit = 20 11 | config.vm.network "forwarded_port", guest: 5985, host: 5985 12 | config.vm.network :private_network, ip: "10.0.0.50" 13 | 14 | config.vm.provision "ansible" do |ansible| 15 | ansible.playbook = "../../ansible/playbooks/windows_workstation.yml" 16 | ansible.config_file = "../../ansible/ansible.cfg" 17 | ansible.compatibility_mode = "2.0" 18 | end 19 | 20 | config.vm.provider "virtualbox" do |vb, override| 21 | vb.gui = true 22 | vb.name = "#{VM_NAME}" 23 | vb.default_nic_type = "82545EM" 24 | vb.customize ["modifyvm", :id, "--memory", 2048] 25 | vb.customize ["modifyvm", :id, "--cpus", 1] 26 | vb.customize ["modifyvm", :id, "--vram", "32"] 27 | vb.customize ["modifyvm", :id, "--clipboard", "bidirectional"] 28 | vb.customize ["setextradata", "global", "GUI/SuppressMessages", "all" ] 29 | end 30 | end 31 | end 32 | -------------------------------------------------------------------------------- /ansible/roles/search_head/tasks/install_cim_app.yml: -------------------------------------------------------------------------------- 1 | - name: Check if cim app exists 2 | stat: 3 | path: /opt/splunk/etc/apps/Splunk_TA_cim 4 | register: cim_app 5 | 6 | - name: download CIM app from S3 bucket 7 | get_url: 8 | url: '{{ s3_bucket_url }}/{{ splunk_cim_app }}' 9 | dest: /tmp/cim_app.tgz 10 | when: cim_app.stat.exists == False 11 | 12 | - name: Install cim app via REST 13 | uri: 14 | url: "https://127.0.0.1:8089/services/apps/local" 15 | method: POST 16 | user: "admin" 17 | password: "{{ splunk_pass }}" 18 | validate_certs: false 19 | body: "name=/tmp/cim_app.tgz&update=true&filename=true" 20 | headers: 21 | Content-Type: "application/x-www-form-urlencoded" 22 | status_code: [ 200, 201 ] 23 | timeout: 30 24 | when: cim_app.stat.exists == False 25 | 26 | - name: Create folder directory for local in CIM 27 | file: 28 | path: "{{ item }}" 29 | state: directory 30 | owner: splunk 31 | group: splunk 32 | recurse: yes 33 | with_items: 34 | - /opt/splunk/etc/apps/Splunk_SA_CIM/local/ 35 | when: cim_app.stat.exists == False 36 | 37 | - name: copy datamodels.conf to splunk server 38 | copy: 39 | src: datamodels.conf 40 | dest: /opt/splunk/etc/apps/Splunk_SA_CIM/local/datamodels.conf 41 | owner: splunk 42 | group: splunk 43 | when: cim_app.stat.exists == False 44 | notify: restart splunk 45 | -------------------------------------------------------------------------------- /vagrant/windows7/Vagrantfile: -------------------------------------------------------------------------------- 1 | VM_NAME= "win7-workstation-#{SecureRandom.hex(2)}" 2 | Vagrant.configure("2") do |config| 3 | config.vm.define "win7" do |config| 4 | config.vm.box = "d1vious/windows_7" 5 | config.vm.hostname = "#{VM_NAME}" 6 | config.vm.boot_timeout = 600 7 | config.vm.communicator = "winrm" 8 | config.winrm.basic_auth_only = true 9 | config.winrm.timeout = 300 10 | config.winrm.retry_limit = 20 11 | config.vm.network "forwarded_port", guest: 5985, host: 5985 12 | config.vm.network "forwarded_port", guest: 3389, host: 3389 13 | config.vm.network :private_network, ip: "10.0.0.51" 14 | config.vm.provision "ansible" do |ansible| 15 | ansible.playbook = "../../ansible/playbooks/windows_workstation.yml" 16 | ansible.config_file = "../../ansible/ansible.cfg" 17 | ansible.compatibility_mode = "2.0" 18 | end 19 | 20 | config.vm.provider "virtualbox" do |vb, override| 21 | vb.gui = true 22 | vb.name = "#{VM_NAME}" 23 | vb.default_nic_type = "82545EM" 24 | vb.customize ["modifyvm", :id, "--memory", 2048] 25 | vb.customize ["modifyvm", :id, "--cpus", 1] 26 | vb.customize ["modifyvm", :id, "--vram", "32"] 27 | vb.customize ["modifyvm", :id, "--clipboard", "bidirectional"] 28 | vb.customize ["setextradata", "global", "GUI/SuppressMessages", "all" ] 29 | end 30 | end 31 | end 32 | -------------------------------------------------------------------------------- /ansible/roles/search_head/README.md: -------------------------------------------------------------------------------- 1 | Role Name 2 | ======== 3 | 4 | A brief description of the role goes here. 5 | 6 | Requirements 7 | ------------ 8 | 9 | Any pre-requisites that may not be covered by Ansible itself or the role should be mentioned here. For instance, if the role uses the EC2 module, it may be a good idea to mention in this section that the boto package is required. 10 | 11 | Role Variables 12 | -------------- 13 | 14 | A description of the settable variables for this role should go here, including any variables that are in defaults/main.yml, vars/main.yml, and any variables that can/should be set via parameters to the role. Any variables that are read from other roles and/or the global scope (ie. hostvars, group vars, etc.) should be mentioned here as well. 15 | 16 | Dependencies 17 | ------------ 18 | 19 | A list of other roles hosted on Galaxy should go here, plus any details in regards to parameters that may need to be set for other roles, or variables that are used from other roles. 20 | 21 | Example Playbook 22 | ------------------------- 23 | 24 | Including an example of how to use your role (for instance, with variables passed in as parameters) is always nice for users too: 25 | 26 | - hosts: servers 27 | roles: 28 | - { role: username.rolename, x: 42 } 29 | 30 | License 31 | ------- 32 | 33 | BSD 34 | 35 | Author Information 36 | ------------------ 37 | 38 | An optional section for the role authors to include contact information, or a website (HTML is not allowed). 39 | -------------------------------------------------------------------------------- /ansible/roles/phantom/README.md: -------------------------------------------------------------------------------- 1 | Role Name 2 | ======== 3 | 4 | Install a Phantom server from RPMs on CentOS/RHEL 7 5 | 6 | Requirements 7 | ------------ 8 | 9 | The user-specific file ~/.attack_range.yml must be created and populated with my.phantom.us credentials and a user-specified initial password for the Phantom instance. If you don't have an account on my.phantom.us go ahead and sign up for free: https://my.phantom.us/signup/ 10 | 11 | Role Variables 12 | -------------- 13 | 14 | The following variables must be declared in ~/.attack_range.yml: 15 | * `phantom_community_user` - the username for my.phantom.us which is need to install Phantom 16 | * `phantom_community_pass` - the password for my.phantom.us which is needed to install Phantom 17 | * `phantom_pass` - pick a random password which will be applied as the initial password of the admin user on the Phantom web interface 18 | 19 | The following variable in vars/vars.yml is required: 20 | * `phantom_repo_url` - the URL of the phantom yum repository installer package for the Phantom version that will be used by this role 21 | 22 | Dependencies 23 | ------------ 24 | 25 | No known Ansible dependencies 26 | 27 | Example Playbook 28 | ------------------------- 29 | 30 | To use this role just populate vars/vars.yml and apply the role like so: 31 | 32 | - hosts: servers 33 | roles: 34 | - common 35 | - phantom 36 | 37 | License 38 | ------- 39 | 40 | BSD 41 | 42 | Author Information 43 | ------------------ 44 | 45 | https://www.splunk.com 46 | -------------------------------------------------------------------------------- /vagrant/windows2016_dc/Vagrantfile: -------------------------------------------------------------------------------- 1 | VM_NAME= "windows-2016-dc-#{SecureRandom.hex(2)}" 2 | Vagrant.configure("2") do |config| 3 | config.vm.define "dc" do |config| 4 | config.vm.box = "d1vious/windows2016" 5 | config.vm.hostname = "#{VM_NAME}" 6 | config.vm.boot_timeout = 600 7 | config.winrm.transport = :plaintext 8 | config.vm.communicator = "winrm" 9 | config.winrm.basic_auth_only = true 10 | config.winrm.timeout = 300 11 | config.winrm.retry_limit = 20 12 | config.vm.network "forwarded_port", guest: 5985, host: 5985 13 | config.vm.network :private_network, ip: "10.0.0.5", gateway: "10.0.0.1" 14 | 15 | config.vm.provision "ansible" do |ansible| 16 | ansible.playbook = "../../ansible/playbooks/windows_dc.yml" 17 | ansible.config_file = "../../ansible/ansible.cfg" 18 | ansible.compatibility_mode = "2.0" 19 | ansible.groups = { 20 | "win" => ["10.0.0.5"], 21 | "win:vars" => {"ansible_winrm_read_timeout_sec" => "600", 22 | "ansible_connection" => "winrm"} 23 | } 24 | end 25 | 26 | 27 | config.vm.provider "virtualbox" do |vb, override| 28 | vb.gui = true 29 | vb.name = "#{VM_NAME}" 30 | vb.default_nic_type = "82545EM" 31 | vb.customize ["modifyvm", :id, "--memory", 3072] 32 | vb.customize ["modifyvm", :id, "--cpus", 2] 33 | vb.customize ["modifyvm", :id, "--vram", "32"] 34 | vb.customize ["modifyvm", :id, "--clipboard", "bidirectional"] 35 | vb.customize ["setextradata", "global", "GUI/SuppressMessages", "all" ] 36 | end 37 | end 38 | end 39 | -------------------------------------------------------------------------------- /ansible/roles/windows_domain_controller/tasks/create.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # tasks file for ansible-windows-domain-controller 3 | # 4 | 5 | 6 | - name: set local admin password 7 | win_user: 8 | name: Administrator 9 | password: "{{ windows_domain_controller_info['domain_admin_password'] }}" 10 | state: present 11 | 12 | - name: features | Installing RSAT AD Admin Center 13 | win_feature: 14 | name: RSAT-AD-AdminCenter 15 | state: present 16 | 17 | - name: features | Installing AD Domain Services 18 | win_feature: 19 | name: AD-Domain-Services 20 | include_management_tools: yes 21 | include_sub_features: yes 22 | state: present 23 | 24 | - name: Creating a windows domain 25 | win_domain: 26 | dns_domain_name: "{{ windows_domain_controller_info['dns_domain_name'] }}" 27 | safe_mode_password: "{{ windows_domain_controller_info['safe_mode_password'] }}" 28 | 29 | - name: Setting DNS Servers 30 | win_dns_client: 31 | adapter_names: "*" 32 | ipv4_addresses: "127.0.0.1" 33 | 34 | - name: reboot | Rebooting Server 35 | win_reboot: 36 | 37 | - name: Managing Domain Controller Membership 38 | win_domain_controller: 39 | dns_domain_name: "{{ windows_domain_controller_info['dns_domain_name'] }}" 40 | domain_admin_user: "{{ windows_domain_controller_info['domain_admin_user'] }}" 41 | domain_admin_password: "{{ windows_domain_controller_info['domain_admin_password'] }}" 42 | safe_mode_password: "{{ windows_domain_controller_info['safe_mode_password'] }}" 43 | state: "{{ windows_domain_controller_info['state'] }}" 44 | register: _windows_domain_controller 45 | -------------------------------------------------------------------------------- /ansible/roles/universal_forwarder/files/win_event_log_inputs.conf: -------------------------------------------------------------------------------- 1 | 2 | ###### OS Logs ###### 3 | [WinEventLog://Application] 4 | disabled = 0 5 | start_from = oldest 6 | current_only = 0 7 | checkpointInterval = 5 8 | renderXml=true 9 | index = win 10 | 11 | [WinEventLog://Security] 12 | disabled = 0 13 | start_from = oldest 14 | current_only = 0 15 | evt_resolve_ad_obj = 1 16 | checkpointInterval = 5 17 | blacklist1 = EventCode="4662" Message="Object Type:(?!\s*groupPolicyContainer)" 18 | blacklist2 = EventCode="566" Message="Object Type:(?!\s*groupPolicyContainer)" 19 | renderXml=true 20 | index = win 21 | 22 | [WinEventLog://System] 23 | disabled = 0 24 | start_from = oldest 25 | current_only = 0 26 | checkpointInterval = 5 27 | renderXml=true 28 | index = win 29 | 30 | ###### WinEventLog Inputs for Active Directory ###### 31 | 32 | ## Application and Services Logs - DFS Replication 33 | [WinEventLog://DFS Replication] 34 | disabled = 0 35 | renderXml=true 36 | index = win 37 | 38 | ## Application and Services Logs - Directory Service 39 | [WinEventLog://Directory Service] 40 | disabled = 0 41 | renderXml=true 42 | index = win 43 | 44 | ## Application and Services Logs - File Replication Service 45 | [WinEventLog://File Replication Service] 46 | disabled = 0 47 | renderXml=true 48 | index = win 49 | 50 | ## Application and Services Logs - Key Management Service 51 | [WinEventLog://Key Management Service] 52 | disabled = 0 53 | renderXml=true 54 | index = win 55 | 56 | 57 | ###### WinEventLog Inputs for DNS ###### 58 | [WinEventLog://DNS Server] 59 | disabled=0 60 | renderXml=true 61 | index = dns 62 | 63 | 64 | ###### DHCP ###### 65 | [monitor://$WINDIR\System32\DHCP] 66 | disabled = 0 67 | whitelist = DhcpSrvLog* 68 | crcSalt = 69 | sourcetype = DhcpSrvLog 70 | -------------------------------------------------------------------------------- /ansible/roles/search_head/tasks/splunk.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # This playbook install the apps required in a server 3 | 4 | - name: add splunk group 5 | tags: 6 | - install 7 | - security 8 | group: name=splunk state=present 9 | 10 | - name: add splunk user 11 | tags: 12 | - install 13 | - security 14 | user: name=splunk comment="Splunk service user" shell=/usr/sbin/nologin groups=splunk createhome=yes 15 | 16 | - name: make /opt writetable by splunk 17 | tags: 18 | - install 19 | file: path=/opt mode=777 20 | 21 | - name: checking if splunk is install 22 | tags: install 23 | stat: path=/opt/splunk 24 | register: splunk_path 25 | 26 | - name: is splunk installed? 27 | tags: install 28 | debug: msg='splunk is already installed under /opt/splunk' 29 | when: splunk_path.stat.exists 30 | 31 | - name: download splunk 32 | tags: install 33 | get_url: 34 | url: '{{ splunk_url }}' 35 | dest: /opt/ 36 | when: splunk_path.stat.exists == false 37 | 38 | - name: install splunk binary 39 | tags: 40 | - install 41 | unarchive: remote_src=yes src=/opt/{{splunk_binary}} dest=/opt/ owner=splunk group=splunk creates=yes 42 | become: yes 43 | become_user: splunk 44 | when: splunk_path.stat.exists == false 45 | 46 | - name: accept license and start splunk 47 | tags: 48 | - install 49 | shell: /opt/splunk/bin/splunk start --accept-license --answer-yes --no-prompt --seed-passwd {{splunk_pass}} 50 | become: yes 51 | become_user: splunk 52 | when: splunk_path.stat.exists == false 53 | 54 | - name: enable boot-start 55 | tags: 56 | - install 57 | shell: /opt/splunk/bin/splunk enable boot-start -user splunk 58 | when: splunk_path.stat.exists == false 59 | 60 | - name: restart splunk 61 | service: 62 | name: splunkd 63 | state: restarted 64 | when: splunk_path.stat.exists == false 65 | -------------------------------------------------------------------------------- /ansible/roles/sysmon/tasks/windows-sysmon.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - block: 4 | - name: check if sysmon archive is present 5 | win_stat: path="{{ win_temp_dir }}\\{{ win_sysmon_url | basename }}" 6 | register: sysmondl 7 | - name: download sysmon 8 | win_get_url: 9 | url: "{{ win_sysmon_url }}" 10 | dest: "{{ win_temp_dir }}\\{{ win_sysmon_url | basename }}" 11 | timeout: 60 12 | when: not sysmondl.stat.exists 13 | - name: unzip sysmon 14 | win_unzip: 15 | src: "{{ win_temp_dir }}\\{{ win_sysmon_url | basename }}" 16 | dest: "{{ win_temp_dir }}\\sysmon" 17 | creates: "{{ win_temp_dir }}\\sysmon\\sysmon.exe" 18 | - set_fact: 19 | sysmon_path: "{{ win_temp_dir }}\\sysmon\\sysmon64.exe" 20 | - debug: 21 | msg: '{{ sysmon_path }}' 22 | when: win_sysmon_direct 23 | 24 | - block: 25 | - name: install sysmon with chocolatey 26 | win_chocolatey: 27 | name: sysmon 28 | state: present 29 | ignore_checksums: yes 30 | ## FIXME! 31 | #install_args: "--checksum {{ win_sysmon_sha256 }}" 32 | - set_fact: 33 | sysmon_path: "c:\\ProgramData\\chocolatey\\lib\\sysmon\\tools\\sysmon" 34 | when: not win_sysmon_direct 35 | 36 | - block: 37 | - name: Copy Sysmon template 38 | win_template: 39 | src: "{{ win_sysmon_template }}.j2" 40 | dest: "{{ win_temp_dir }}\\{{ win_sysmon_template }}" 41 | - debug: 42 | msg: '"{{ sysmon_path }}" -n -accepteula -i "{{ win_temp_dir }}\\{{ win_sysmon_template }}"' 43 | - name: install sysmon with defined config 44 | win_command: '"{{ sysmon_path }}" -n -accepteula -i "{{ win_temp_dir }}\\{{ win_sysmon_template }}"' 45 | ignore_errors: true 46 | notify: restart machine 47 | when: win_sysmon_template != '' 48 | 49 | - block: 50 | - name: install sysmon 51 | win_command: "{{ sysmon_path }} -i -n -accepteula" 52 | ignore_errors: true 53 | notify: restart machine 54 | when: win_sysmon_template == '' 55 | -------------------------------------------------------------------------------- /vagrant/Vagrantfile: -------------------------------------------------------------------------------- 1 | Vagrant.configure("2") do |config| 2 | 3 | config.vm.define "splunk-server" do |config| 4 | VM_NAME= "splunk-server" 5 | config.vm.box = "generic/ubuntu1804" 6 | config.vm.hostname = "#{VM_NAME}" 7 | config.vm.boot_timeout = 600 8 | config.vm.network "forwarded_port", guest: 8000, host: 8000, protocol: "tcp" 9 | config.vm.network :private_network, ip: "10.0.0.10" 10 | 11 | config.vm.provision "ansible" do |ansible| 12 | ansible.playbook = "../ansible/playbooks/splunk_server.yml" 13 | ansible.config_file = "../ansible/ansible.cfg" 14 | ansible.compatibility_mode = "2.0" 15 | end 16 | 17 | config.vm.provider "virtualbox" do |vb, override| 18 | vb.gui = true 19 | vb.name = "#{VM_NAME}" 20 | vb.customize ["modifyvm", :id, "--memory", 6000] 21 | vb.customize ["modifyvm", :id, "--cpus", 4] 22 | end 23 | end 24 | 25 | 26 | config.vm.define "win10" do |config| 27 | VM_NAME_WIN= "win10" 28 | config.vm.box = "d1vious/windows10" 29 | config.vm.hostname = "#{VM_NAME_WIN}" 30 | config.vm.boot_timeout = 600 31 | config.vm.communicator = "winrm" 32 | config.winrm.basic_auth_only = true 33 | config.winrm.timeout = 300 34 | config.winrm.retry_limit = 20 35 | config.vm.network "forwarded_port", guest: 5985, host: 5985 36 | config.vm.network :private_network, ip: "10.0.0.50" 37 | 38 | config.vm.provision "ansible" do |ansible| 39 | ansible.extra_vars = { 40 | splunk_indexer_ip: "10.0.0.10" 41 | } 42 | ansible.playbook = "../ansible/playbooks/windows_workstation.yml" 43 | ansible.config_file = "../ansible/ansible.cfg" 44 | ansible.compatibility_mode = "2.0" 45 | end 46 | 47 | config.vm.provider "virtualbox" do |vb, override| 48 | vb.gui = true 49 | vb.name = "#{VM_NAME_WIN}" 50 | vb.default_nic_type = "82545EM" 51 | vb.customize ["modifyvm", :id, "--memory", 2048] 52 | vb.customize ["modifyvm", :id, "--cpus", 1] 53 | vb.customize ["modifyvm", :id, "--vram", "32"] 54 | vb.customize ["modifyvm", :id, "--clipboard", "bidirectional"] 55 | vb.customize ["setextradata", "global", "GUI/SuppressMessages", "all" ] 56 | end 57 | end 58 | 59 | end 60 | -------------------------------------------------------------------------------- /ansible/roles/phantom/files/change_phantom_password.py: -------------------------------------------------------------------------------- 1 | # -- 2 | # copied from file: insert_to_db.py 3 | # 4 | # Copyright (c) 2014-2019 Splunk, Inc. 5 | # 6 | # This unpublished material is proprietary to Splunk, Inc. 7 | # All rights reserved. The methods and 8 | # techniques described herein are considered trade secrets 9 | # and/or confidential. Reproduction or distribution, in whole 10 | # or in part, is forbidden except by express written permission 11 | # of Splunk, Inc. 12 | # 13 | # -- 14 | import sys 15 | import os 16 | import json 17 | import random 18 | import pytz 19 | import argparse 20 | 21 | from collections import defaultdict 22 | from dateutil.parser import parse as parse_datetime 23 | from datetime import datetime, timedelta 24 | from traceback import format_exc 25 | 26 | django_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', 'www')) 27 | sys.path.insert(0, django_path) 28 | lib_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'lib')) 29 | sys.path.insert(0, lib_path) 30 | 31 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'phantom_ui.settings') 32 | import django 33 | from django.db import transaction 34 | from django.apps import apps as django_apps 35 | django.setup() 36 | 37 | import phantom_ui.ui.models as p_models 38 | from phantom_ui.ui.shared import json_to_model, DatetimeJson 39 | from phantom_ui.product_version import PRODUCT_VERSION 40 | 41 | admin_user = None 42 | 43 | def create_default_superuser(password='password'): 44 | u = p_models.PhUser.objects.filter(username='admin').first() 45 | 46 | if u: 47 | u.profile.delete() 48 | u.delete() 49 | 50 | u = p_models.PhUser.objects.create_superuser(username='admin', password=password, 51 | email='root@localhost') 52 | u.profile = p_models.Profile() 53 | u.profile.set_ui_state(u.profile.get_default_ui_state()) 54 | u.profile.save() 55 | u.save() 56 | r = p_models.Role.objects.get(name='Administrator') 57 | r.users.add(u) 58 | r.save() 59 | global admin_user 60 | admin_user = u 61 | 62 | 63 | if __name__ == '__main__': 64 | parser = argparse.ArgumentParser() 65 | parser.add_argument('--new-pass', 66 | help='New password for admin user') 67 | args = parser.parse_args() 68 | 69 | create_default_superuser(password=args.new_pass) -------------------------------------------------------------------------------- /terraform/variables.tf: -------------------------------------------------------------------------------- 1 | variable "private_key_path" { 2 | description = < 9 | 10 | * 11 | 12 | 13 | 14 | microsoft 15 | windows 16 | 17 | 18 | 19 | 20 | 21 | 22 | chrome.exe 23 | iexplore.exe 24 | firefox.exe 25 | OUTLOOK.EXE 26 | Skype.exe 27 | lync.exe 28 | *internal domain servers 29 | proxy port 30 | proxy port 31 | 32 | 33 | 80 34 | 443 35 | 36 | 37 | 38 | 39 | C:\Windows 40 | C:\Users 41 | C:\temp 42 | 43 | 48 | 49 | 50 | 51 | 224.0.0.252 52 | 53 | .255 54 | 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /ansible/vars/vars.yml: -------------------------------------------------------------------------------- 1 | ## Variables for Splunk Search Head 2 | splunk_url: https://www.splunk.com/page/download_track?file=7.3.2/linux/splunk-7.3.2-c60db69f8e32-Linux-x86_64.tgz&ac=&wget=true&name=wget&platform=Linux&architecture=x86_64&version=7.3.2&product=splunk&typed=release 3 | splunk_binary: splunk-7.3.2-c60db69f8e32-Linux-x86_64.tgz 4 | splunk_pass: changeme 5 | 6 | # Apps 7 | sysmon: true 8 | stream: true 9 | 10 | ## Variables for Splunk Universal Forwarders 11 | splunk_uf_win_url: https://www.splunk.com/page/download_track?file=7.3.2/windows/splunkforwarder-7.3.2-c60db69f8e32-x64-release.msi&ac=&wget=true&name=wget&platform=Windows&architecture=x86_64&version=7.3.2&product=universalforwarder&typed=release 12 | 13 | # Apps and TAs 14 | s3_bucket_url: https://attack-range-appbinaries.s3-us-west-2.amazonaws.com 15 | splunk_windows_ta: splunk-add-on-for-microsoft-windows_600.tgz 16 | splunk_sysmon_ta: add-on-for-microsoft-sysmon_800.tgz 17 | splunk_stream_ta: Splunk_TA_stream.zip 18 | splunk_stream_app: splunk-stream_713.tgz 19 | splunk_cim_app: splunk-common-information-model-cim_4130.tgz 20 | splunk_escu_app: DA-ESS-ContentUpdate-v1.0.41.tar.gz 21 | splunk_asx_app: Splunk_Analytic_Story_Execution-latest.tar.gz 22 | 23 | #Variables for Firedrill 24 | #install_firedrill: false 25 | #firedrill_dst_location: C:\fd.exe 26 | #firedrill_binary_path: ../../../../appbinaries/FiredrillAgent-installer-2.2.389.exe 27 | 28 | #Variables for Atomic Red Team 29 | install_art: true 30 | art_module_dst_location: C:\Install-AtomicRedTeam.ps1 31 | art_module_path: Install-AtomicRedTeam.ps1 32 | art_run_all_test: false 33 | # array of techniques to run 34 | art_run_technique: [''] 35 | 36 | #Variables for Sysmon 37 | win_temp_dir: 'c:\Program Files\ansible' 38 | win_log_dir: 'c:\ProgramData\ansible\log' 39 | 40 | win_sysmon: true 41 | ## as sysmon link is updated and hash change, chocolatey install can fails 42 | ## ansible win_get_url currently does not support checksum option 43 | win_sysmon_direct: true 44 | win_sysmon_url: 'https://download.sysinternals.com/files/Sysmon.zip' 45 | win_sysmon_sha256: '848c3323324e8fa849024f87a2764f8575513463f339690056664861f99e4c5f' 46 | ## note: file should be in current or template directory with .j2 extension 47 | #win_sysmon_template: SysmonConfig-Neo23x0-workstations.xml 48 | #win_sysmon_template: SysmonConfig-moti.xml 49 | #win_sysmon_template: SysmonConfig-TSwift.xml 50 | win_sysmon_template: SysmonConfig-Verbose.xml 51 | 52 | win_eventlog_maxsize: 315801600 53 | win_eventlog_retention: 0 54 | win_sysmon_eventlog_channels: 55 | - Microsoft-Windows-Sysmon/Operational 56 | 57 | # Domain Controller 58 | windows_domain_controller_info: 59 | dns_domain_name: splunkresearch.local 60 | domain_admin_password: myTempPassword123 61 | domain_admin_user: Administrator@splunkresearch.local 62 | safe_mode_password: myTempPassword123 63 | state: domain_controller 64 | -------------------------------------------------------------------------------- /ansible/vars/vars.yml.default: -------------------------------------------------------------------------------- 1 | ## Variables for Splunk Search Head 2 | splunk_url: https://www.splunk.com/page/download_track?file=7.3.2/linux/splunk-7.3.2-c60db69f8e32-Linux-x86_64.tgz&ac=&wget=true&name=wget&platform=Linux&architecture=x86_64&version=7.3.2&product=splunk&typed=release 3 | splunk_binary: splunk-7.3.2-c60db69f8e32-Linux-x86_64.tgz 4 | splunk_pass: changeme 5 | 6 | # Apps 7 | sysmon: true 8 | stream: true 9 | 10 | ## Variables for Splunk Universal Forwarders 11 | splunk_uf_win_url: https://www.splunk.com/page/download_track?file=7.3.2/windows/splunkforwarder-7.3.2-c60db69f8e32-x64-release.msi&ac=&wget=true&name=wget&platform=Windows&architecture=x86_64&version=7.3.2&product=universalforwarder&typed=release 12 | 13 | # Apps and TAs 14 | s3_bucket_url: https://attack-range-appbinaries.s3-us-west-2.amazonaws.com 15 | splunk_windows_ta: splunk-add-on-for-microsoft-windows_600.tgz 16 | splunk_sysmon_ta: add-on-for-microsoft-sysmon_800.tgz 17 | splunk_stream_ta: Splunk_TA_stream.zip 18 | splunk_stream_app: splunk-stream_713.tgz 19 | splunk_cim_app: splunk-common-information-model-cim_4130.tgz 20 | splunk_escu_app: DA-ESS-ContentUpdate-v1.0.41.tar.gz 21 | splunk_asx_app: Splunk_Analytic_Story_Execution-latest.tar.gz 22 | 23 | #Variables for Firedrill 24 | #install_firedrill: false 25 | #firedrill_dst_location: C:\fd.exe 26 | #firedrill_binary_path: ../../../../appbinaries/FiredrillAgent-installer-2.2.389.exe 27 | 28 | #Variables for Atomic Red Team 29 | install_art: true 30 | art_module_dst_location: C:\Install-AtomicRedTeam.ps1 31 | art_module_path: Install-AtomicRedTeam.ps1 32 | art_run_all_test: false 33 | # array of techniques to run 34 | art_run_technique: ['T1117'] 35 | 36 | #Variables for Sysmon 37 | win_temp_dir: 'c:\Program Files\ansible' 38 | win_log_dir: 'c:\ProgramData\ansible\log' 39 | 40 | win_sysmon: true 41 | ## as sysmon link is updated and hash change, chocolatey install can fails 42 | ## ansible win_get_url currently does not support checksum option 43 | win_sysmon_direct: true 44 | win_sysmon_url: 'https://download.sysinternals.com/files/Sysmon.zip' 45 | win_sysmon_sha256: '848c3323324e8fa849024f87a2764f8575513463f339690056664861f99e4c5f' 46 | ## note: file should be in current or template directory with .j2 extension 47 | #win_sysmon_template: SysmonConfig-Neo23x0-workstations.xml 48 | #win_sysmon_template: SysmonConfig-moti.xml 49 | #win_sysmon_template: SysmonConfig-TSwift.xml 50 | win_sysmon_template: SysmonConfig-Verbose.xml 51 | 52 | win_eventlog_maxsize: 315801600 53 | win_eventlog_retention: 0 54 | win_sysmon_eventlog_channels: 55 | - Microsoft-Windows-Sysmon/Operational 56 | 57 | # Domain Controller 58 | windows_domain_controller_info: 59 | dns_domain_name: splunkresearch.local 60 | domain_admin_password: myTempPassword123 61 | domain_admin_user: Administrator@splunkresearch.local 62 | safe_mode_password: myTempPassword123 63 | state: domain_controller 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # ignore appbinaries directory we don't want this uploaded 3 | ansible/roles/*/files/splunk*.tgz 4 | ansible/roles/*/files/splunk*.msi 5 | ansible/inventory/hosts 6 | ansible/vars/vars.yml 7 | 8 | # log file 9 | attack_range.log 10 | .attack_range/artifacts 11 | 12 | ## Terraform ignores 13 | # Local .terraform directories 14 | terraform/.terraform/ 15 | 16 | # .tfstate files 17 | *.tfstate 18 | *.tfstate.* 19 | 20 | # Crash log files 21 | crash.log 22 | 23 | # Ignore any .tfvars files that are generated automatically for each Terraform run. Most 24 | # .tfvars files are managed as part of configuration and so should be included in 25 | # version control. 26 | # 27 | # example.tfvars 28 | 29 | # Ignore override files as they are usually used to override resources locally and so 30 | # are not checked in 31 | override.tf 32 | override.tf.json 33 | *_override.tf 34 | *_override.tf.json 35 | 36 | # Include override files you do wish to add to version control using negated pattern 37 | # 38 | # !example_override.tf 39 | 40 | # Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan 41 | # example: *tfplan* 42 | # 43 | 44 | # dont want entire box files 45 | # # Vagrant stuff 46 | acceptance_config.yml 47 | boxes/* 48 | .vagrant 49 | /website/.vagrant 50 | /website/build 51 | /vagrant-spec.config.rb 52 | test/vagrant-spec/.vagrant/ 53 | 54 | # packer cache 55 | packer/packer_cache 56 | 57 | # usual mac files 58 | .DS_Store 59 | 60 | # Byte-compiled / optimized / DLL files 61 | __pycache__/ 62 | *.py[cod] 63 | *$py.class 64 | 65 | # C extensions 66 | *.so 67 | 68 | # Distribution / packaging 69 | .Python 70 | build/ 71 | develop-eggs/ 72 | dist/ 73 | downloads/ 74 | eggs/ 75 | .eggs/ 76 | lib/ 77 | lib64/ 78 | parts/ 79 | sdist/ 80 | var/ 81 | wheels/ 82 | *.egg-info/ 83 | .installed.cfg 84 | *.egg 85 | MANIFEST 86 | 87 | # PyInstaller 88 | # Usually these files are written by a python script from a template 89 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 90 | *.manifest 91 | 92 | # Installer logs 93 | pip-log.txt 94 | pip-delete-this-directory.txt 95 | 96 | # Unit test / coverage reports 97 | htmlcov/ 98 | .tox/ 99 | .coverage 100 | .coverage.* 101 | .cache 102 | nosetests.xml 103 | coverage.xml 104 | *.cover 105 | .hypothesis/ 106 | .pytest_cache/ 107 | 108 | # Translations 109 | *.mo 110 | *.pot 111 | 112 | # Django stuff: 113 | *.log 114 | local_settings.py 115 | db.sqlite3 116 | 117 | # Flask stuff: 118 | instance/ 119 | .webassets-cache 120 | 121 | # Scrapy stuff: 122 | .scrapy 123 | 124 | # Sphinx documentation 125 | docs/_build/ 126 | 127 | # PyBuilder 128 | target/ 129 | 130 | # Jupyter Notebook 131 | .ipynb_checkpoints 132 | 133 | # pyenv 134 | .python-version 135 | 136 | # celery beat schedule file 137 | celerybeat-schedule 138 | 139 | # SageMath parsed files 140 | *.sage.py 141 | 142 | # Environments 143 | .env 144 | .venv 145 | env/ 146 | venv/ 147 | ENV/ 148 | env.bak/ 149 | venv.bak/ 150 | 151 | # Spyder project settings 152 | .spyderproject 153 | .spyproject 154 | 155 | # Rope project settings 156 | .ropeproject 157 | 158 | # mkdocs documentation 159 | /site 160 | 161 | # mypy 162 | .mypy_cache/ 163 | -------------------------------------------------------------------------------- /ansible/roles/atomic_red_team/files/Install-AtomicRedTeam.ps1: -------------------------------------------------------------------------------- 1 | #Requires -RunAsAdministrator 2 | [CmdletBinding()] 3 | Param( 4 | [Parameter(Mandatory=$False,Position=0)] 5 | [string]$InstallPath = 'C:\AtomicRedTeam', 6 | 7 | [Parameter(Mandatory=$False,Position=0)] 8 | [string]$DownloadPath = 'C:\AtomicRedTeam' 9 | 10 | ) 11 | 12 | function Install-AtomicRedTeam { 13 | <# 14 | .SYNOPSIS 15 | 16 | This is a simple script to download and install Atomic Red Team Invoke-AtomicRedTeam Powershell Framework. 17 | 18 | Atomic Function: Install-AtomicRedTeam 19 | Author: Red Canary Research 20 | License: MIT License 21 | Required Dependencies: powershell-yaml 22 | Optional Dependencies: None 23 | 24 | .PARAMETER DownloadPath 25 | 26 | Specifies the desired path to download Atomic Red Team. 27 | 28 | .PARAMETER InstallPath 29 | 30 | Specifies the desired path for where to install Atomic Red Team. 31 | 32 | .EXAMPLE 33 | 34 | Install Atomic Red Team 35 | PS> Install-AtomicRedTeam.ps1 36 | 37 | .EXAMPLE 38 | 39 | Execute a single test 40 | $T1117 = Get-AtomicTechnique -Path ..\..\atomics\T1117\T1117.yaml 41 | Invoke-AtomicTest $T1117 42 | 43 | .EXAMPLE 44 | 45 | Informational Stream 46 | Invoke-AtomicTest $T1117 -InformationAction Continue 47 | 48 | .EXAMPLE 49 | 50 | Verbose Stream 51 | Invoke-AtomicTest $T1117 -Verbose 52 | 53 | .EXAMPLE 54 | 55 | Debug Stream 56 | Invoke-AtomicTest $T1117 -Debug 57 | 58 | .EXAMPLE 59 | 60 | What if 61 | If you would like to see what would happen without running the test 62 | Invoke-AtomicTest $T1117 -WhatIf 63 | 64 | .EXAMPLE 65 | 66 | 67 | To run all tests without confirming them run using the Confirm switch to false 68 | 69 | Invoke-AtomicTest $T1117 -Confirm:$false 70 | Or you can set your $ConfirmPreference to 'Medium' 71 | 72 | $ConfirmPreference = 'Medium' 73 | Invoke-AtomicTest $T1117 74 | 75 | .EXAMPLE 76 | 77 | Invoke-AllAtomicTests -GenerateOnly 78 | 79 | .NOTES 80 | 81 | Use the '-Verbose' option to print detailed information. 82 | 83 | #> 84 | 85 | 86 | write-verbose "Directory Creation" 87 | 88 | if(!(Test-Path -Path $InstallPath )){ 89 | New-Item -ItemType directory -Path $InstallPath 90 | write-verbose "Setting Execution Policy to Unrestricted" 91 | set-executionpolicy Unrestricted 92 | 93 | write-verbose "Setting variables for remote URL and download Path" 94 | $url = "https://github.com/redcanaryco/atomic-red-team/archive/master.zip" 95 | $path = "$DownloadPath\master.zip" 96 | [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 97 | $webClient = new-object System.Net.WebClient 98 | write-verbose "Beginning download from Github" 99 | $webClient.DownloadFile( $url, $path ) 100 | 101 | write-verbose "Extracting ART to C:\AtomicRedTeam\" 102 | Expand-Archive -LiteralPath "$DownloadPath\master.zip" "C:\AtomicRedTeam" 103 | 104 | write-verbose "Installing NuGet PackageProvider" 105 | Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force 106 | 107 | write-verbose "Installing powershell-yaml" 108 | Install-Module -Name powershell-yaml -Force 109 | 110 | write-verbose "Importing invoke-atomicRedTeam module" 111 | Import-Module "C:\AtomicRedTeam\atomic-red-team-master\execution-frameworks\Invoke-AtomicRedTeam\Invoke-AtomicRedTeam\Invoke-AtomicRed 112 | Team.psm1" 113 | 114 | write-verbose "Changing current work directory Invoke-AtomicRedTeam" 115 | cd "C:\AtomicRedTeam\atomic-red-team-master\execution-frameworks\Invoke-AtomicRedTeam\Invoke-AtomicRedTeam\" 116 | 117 | write-verbose "Clearing screen" 118 | clear 119 | 120 | Write-Host "Installation of Invoke-AtomicRedTeam is complete" -Fore Yellow 121 | 122 | } 123 | else 124 | { 125 | Write-Verbose "Atomic Already exists at $InstallPath" 126 | exit 127 | 128 | 129 | } 130 | } 131 | Install-AtomicRedTeam 132 | -------------------------------------------------------------------------------- /ansible/roles/search_head/files/indexes.conf: -------------------------------------------------------------------------------- 1 | [default] 2 | # Without repFactor = auto (or a number, dictating the number of copies), 3 | # indexes won't be replicated from one peer to another. This setting applies 4 | # a global setting of "auto". Without this, the default repFactor is zero (0). 5 | repFactor = auto 6 | # Default for each index. Can be overridden per index based upon the volume of data received by that index. 7 | # 300GB 8 | #homePath.maxDataSizeMB = 300000 9 | # 200GB 10 | #coldPath.maxDataSizeMB = 200000 11 | 12 | # Retention Time 1 year 13 | frozenTimePeriodInSecs = 31536000 14 | 15 | 16 | # VOLUME SETTINGS 17 | # One Volume for Hot and Cold 18 | [volume:primary] 19 | path = /opt/splunk/var/lib/splunk 20 | # 1000GB 21 | maxVolumeDataSizeMB = 20000 22 | 23 | # Two volumes for a "tiered storage" solution--fast and slow disk. 24 | # [volume:home] 25 | # path = /path/to/fast/disk 26 | # maxVolumeDataSizeMB = 256000 27 | # 28 | # Longer term storage on slower disk. 29 | #[volume:cold] 30 | #path = /opt/splunk/var/lib/splunk 31 | # 5TB with some headroom leftover (data summaries, etc) 32 | #maxVolumeDataSizeMB = 4600000 33 | 34 | # SPLUNK INDEXES 35 | # Note, many of these use historical directory names which don't match the 36 | # name of the index. A common mistake is to automatically generate a new 37 | # indexes.conf from the existing names, thereby "losing" (hiding from Splunk) 38 | # the existing data. 39 | [main] 40 | homePath = volume:primary/defaultdb/db 41 | coldPath = volume:primary/defaultdb/colddb 42 | thawedPath = $SPLUNK_DB/defaultdb/thaweddb 43 | 44 | [history] 45 | homePath = volume:primary/historydb/db 46 | coldPath = volume:primary/historydb/colddb 47 | thawedPath = $SPLUNK_DB/historydb/thaweddb 48 | 49 | [summary] 50 | homePath = volume:primary/summarydb/db 51 | coldPath = volume:primary/summarydb/colddb 52 | thawedPath = $SPLUNK_DB/summarydb/thaweddb 53 | 54 | [_internal] 55 | homePath = volume:primary/_internaldb/db 56 | coldPath = volume:primary/_internaldb/colddb 57 | thawedPath = $SPLUNK_DB/_internaldb/thaweddb 58 | 59 | # For version 6.1 and higher 60 | [_introspection] 61 | homePath = volume:primary/_introspection/db 62 | coldPath = volume:primary/_introspection/colddb 63 | thawedPath = $SPLUNK_DB/_introspection/thaweddb 64 | 65 | # For version 6.5 and higher 66 | [_telemetry] 67 | homePath = volume:primary/_telemetry/db 68 | coldPath = volume:primary/_telemetry/colddb 69 | thawedPath = $SPLUNK_DB/_telemetry/thaweddb 70 | 71 | [_audit] 72 | homePath = volume:primary/audit/db 73 | coldPath = volume:primary/audit/colddb 74 | thawedPath = $SPLUNK_DB/audit/thaweddb 75 | 76 | [_thefishbucket] 77 | homePath = volume:primary/fishbucket/db 78 | coldPath = volume:primary/fishbucket/colddb 79 | thawedPath = $SPLUNK_DB/fishbucket/thaweddb 80 | 81 | 82 | # CUSTOM INDEXES 83 | 84 | [test] 85 | homePath = volume:primary/testdb/db 86 | coldPath = volume:primary/testdb/colddb 87 | thawedPath = $SPLUNK_DB/testdb/thaweddb 88 | frozenTimePeriodInSecs = 604800 89 | 90 | [unix] 91 | homePath = volume:primary/unixdb/db 92 | coldPath = volume:primary/unixdb/colddb 93 | thawedPath = $SPLUNK_DB/unixdb/thaweddb 94 | 95 | [win] 96 | homePath = volume:primary/windb/db 97 | coldPath = volume:primary/windb/colddb 98 | thawedPath = $SPLUNK_DB/windb/thaweddb 99 | 100 | [fw] 101 | homePath = volume:primary/fwdb/db 102 | coldPath = volume:primary/fwdb/colddb 103 | thawedPath = $SPLUNK_DB/fwdb/thaweddb 104 | 105 | [dns] 106 | homePath = volume:primary/dnsdb/db 107 | coldPath = volume:primary/dnsdb/colddb 108 | thawedPath = $SPLUNK_DB/dnsdb/thaweddb 109 | 110 | [mail] 111 | homePath = volume:primary/maildb/db 112 | coldPath = volume:primary/maildb/colddb 113 | thawedPath = $SPLUNK_DB/maildb/thaweddb 114 | 115 | [proxy] 116 | homePath = volume:primary/proxydb/db 117 | coldPath = volume:primary/proxydb/colddb 118 | thawedPath = $SPLUNK_DB/proxydb/thaweddb 119 | 120 | [attack] 121 | homePath = volume:primary/attackdb/db 122 | coldPath = volume:primary/attackdb/colddb 123 | thawedPath = $SPLUNK_DB/attackdb/thaweddb 124 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | ![](docs/range.jpg) 3 | # Splunk Attack Range 4 | 5 | ## Purpose 6 | The Attack Range solves two main challenges in development of detections. First, it allows the user to quickly build a small lab infrastructure as close as possible to your production environment. This lab infrastructure contains a Windows Domain Controller, Windows Workstation and Linux server, which comes pre-configured with multiple security tools and logging configuration. The infrastructure comes with a Splunk server collecting multiple log sources from the different servers. 7 | 8 | Second, this framework allows the user to perform attack simulation using different engines. Therefore, the user can repeatedly replicate and generate data as close to "ground truth" as possible, in a format that allows the creation of detections, investigations, knowledge objects, and playbooks in Splunk. 9 | 10 | 11 | ## Architecture 12 | Attack Range can be used in two different ways: 13 | - local using vagrant and virtualbox 14 | - in the cloud using terraform and AWS 15 | 16 | In order to make Attack Range work on almost every laptop, the local version using Vagrant and Virtualbox consists of a subset of the full-blown cloud infrastructure in AWS using Terraform. The local version consists of a Splunk single instance and a Windows 10 workstation pre-configured with best practice logging configuration according to Splunk. The cloud infrastructure in AWS using Terraform consists of a Windows 10 workstation, a Windows 2016 server and a Splunk server. More information can be found in the wiki 17 | 18 | ![Logical Diagram](docs/architecture.png) 19 | 20 | 21 | ## Configuration 22 | - [vagrant and virtualbox](https://github.com/splunk/attack_range/wiki/Configure-Attack-Range-for-Vagrant) 23 | - [terraform and AWS](https://github.com/splunk/attack_range/wiki/Configure-Attack-Range-for-Terraform) 24 | 25 | ## Running 26 | Attack Range supports different actions: 27 | - Build Attack Range 28 | - Perform Attack Simulation 29 | - Destroy Attack Range 30 | - Stop Attack Range 31 | - Resume Attack Range 32 | 33 | ### Build Attack Range 34 | - Build Attack Range using **Terraform** 35 | ``` 36 | python attack_range.py -m terraform -a build 37 | ``` 38 | - Build Attack Range using **Vagrant** 39 | ``` 40 | python attack_range.py -m vagrant -a build 41 | ``` 42 | 43 | ### Perform Attack Simulation 44 | - Perform Attack Simulation using **Terraform** 45 | ``` 46 | python attack_range.py -m terraform -a simulate -st T1117,T1003 -t attack-range_windows_2016_dc 47 | ``` 48 | - Perform Attack Simulation using **Vagrant** 49 | ``` 50 | python attack_range.py -m vagrant -a simulate -st T1117,T1003 -t win10 51 | ``` 52 | 53 | ### Destroy Attack Range 54 | - Destroy Attack Range using **Terraform** 55 | ``` 56 | python attack_range.py -m terraform -a destroy 57 | ``` 58 | - Destroy Attack Range using **Vagrant** 59 | ``` 60 | python attack_range.py -m vagrant -a destroy 61 | ``` 62 | 63 | ### Stop Attack Range 64 | - Stop Attack Range using **Terraform** 65 | ``` 66 | python attack_range.py -m terraform -a stop 67 | ``` 68 | - Stop Attack Range using **Vagrant** 69 | ``` 70 | python attack_range.py -m vagrant -a stop 71 | ``` 72 | 73 | ### Resume Attack Range 74 | - Resume Attack Range using **Terraform** 75 | ``` 76 | python attack_range.py -m terraform -a resume 77 | ``` 78 | - Resume Attack Range using **Vagrant** 79 | ``` 80 | python attack_range.py -m vagrant -a resume 81 | ``` 82 | 83 | ## Support 84 | Please use the [GitHub issue tracker](https://github.com/splunk/attack_range/issues) to submit bugs or request features. 85 | 86 | If you have questions or need support, you can: 87 | 88 | * Post a question to [Splunk Answers](http://answers.splunk.com) 89 | * Join the [#security-research](https://splunk-usergroups.slack.com/messages/C1RH09ERM/) room in the [Splunk Slack channel](http://splunk-usergroups.slack.com) 90 | * If you are a Splunk Enterprise customer with a valid support entitlement contract and have a Splunk-related question, you can also open a support case on the https://www.splunk.com/ support portal 91 | 92 | 93 | ## Author 94 | * [Jose Hernandez](https://twitter.com/d1vious) 95 | 96 | ## Contributors 97 | * [Rod Soto](https://twitter.com/rodsoto) 98 | * [Bhavin Patel](https://twitter.com/hackpsy) 99 | * [Patrick Bareiß](https://twitter.com/bareiss_patrick) 100 | * Russ Nolen 101 | * Phil Royer 102 | 103 | ## Contributing 104 | We welcome feedback and contributions from the community! Please see our [contribution guidelines](docs/CONTRIBUTING.md) for more information on how to get involved. 105 | 106 | ## Acknowledgements 107 | - [DetectionLab](https://github.com/clong/DetectionLab) 108 | - Atomic Red team 109 | - Sysmon configuration 110 | -------------------------------------------------------------------------------- /terraform/main.tf: -------------------------------------------------------------------------------- 1 | provider "aws" { 2 | profile = var.aws_profile 3 | region = var.aws_region 4 | } 5 | 6 | resource "aws_vpc" "default" { 7 | cidr_block = "${var.vpc_cidr}" 8 | } 9 | 10 | 11 | # Create an internet gateway to give our subnet access to the outside world 12 | resource "aws_internet_gateway" "default" { 13 | vpc_id = "${aws_vpc.default.id}" 14 | } 15 | 16 | # Create a subnet to launch our instances into 17 | resource "aws_subnet" "default" { 18 | count = "${length(var.subnets)}" 19 | vpc_id = "${aws_vpc.default.id}" 20 | cidr_block = "${element(values(var.subnets), count.index)}" 21 | map_public_ip_on_launch = true 22 | availability_zone = "${element(keys(var.subnets), count.index)}" 23 | depends_on = ["aws_internet_gateway.default"] 24 | } 25 | 26 | # Grant the VPC internet access on its main route table 27 | resource "aws_route" "internet_access" { 28 | route_table_id = "${aws_vpc.default.main_route_table_id}" 29 | destination_cidr_block = "0.0.0.0/0" 30 | gateway_id = "${aws_internet_gateway.default.id}" 31 | } 32 | 33 | resource "aws_security_group" "default" { 34 | name = "allow_whitelist" 35 | description = "Allow all inbound traffic from whilisted IPs in vars file of terraform attack range" 36 | vpc_id = "${aws_vpc.default.id}" 37 | ingress { 38 | from_port = 0 39 | to_port = 0 40 | protocol = "-1" 41 | cidr_blocks = var.ip_whitelist 42 | } 43 | 44 | egress { 45 | from_port = 0 46 | to_port = 0 47 | protocol = "-1" 48 | cidr_blocks = ["0.0.0.0/0"] 49 | } 50 | } 51 | 52 | # standup splunk server 53 | resource "aws_instance" "splunk-server" { 54 | ami = var.splunk_ami 55 | instance_type = "t2.2xlarge" 56 | key_name = var.key_name 57 | subnet_id = "${aws_subnet.default.1.id}" 58 | vpc_security_group_ids = ["${aws_security_group.default.id}"] 59 | root_block_device { 60 | volume_type = "gp2" 61 | volume_size = "30" 62 | delete_on_termination = "true" 63 | } 64 | tags = { 65 | Name = "attack-range_splunk-server" 66 | } 67 | 68 | provisioner "remote-exec" { 69 | inline = ["echo booted"] 70 | 71 | connection { 72 | type = "ssh" 73 | user = "ubuntu" 74 | host = "${aws_instance.splunk-server.public_ip}" 75 | private_key = "${file(var.private_key_path)}" 76 | } 77 | } 78 | 79 | provisioner "local-exec" { 80 | working_dir = "../ansible" 81 | command = "ANSIBLE_HOST_KEY_CHECKING=False ansible-playbook -u ubuntu --private-key ${var.private_key_path} -i '${aws_instance.splunk-server.public_ip},' playbooks/splunk_server.yml" 82 | } 83 | } 84 | 85 | resource "aws_eip" "splunk_ip" { 86 | instance = aws_instance.splunk-server.id 87 | } 88 | 89 | resource "aws_ebs_volume" "win2016_volume" { 90 | availability_zone = "us-west-2a" 91 | size = 50 92 | 93 | } 94 | 95 | 96 | # standup windows 2016 domain controller 97 | resource "aws_instance" "windows_2016_dc" { 98 | ami = var.windows_2016_dc_ami 99 | instance_type = "t2.2xlarge" 100 | key_name = var.key_name 101 | subnet_id = "${aws_subnet.default.0.id}" 102 | vpc_security_group_ids = ["${aws_security_group.default.id}"] 103 | tags = { 104 | Name = "attack-range_windows_2016_dc" 105 | } 106 | user_data = < 108 | $admin = [adsi]("WinNT://./${var.win_username}, user") 109 | $admin.PSBase.Invoke("SetPassword", "${var.win_password}") 110 | Invoke-Expression ((New-Object System.Net.Webclient).DownloadString('https://raw.githubusercontent.com/ansible/ansible/devel/examples/scripts/ConfigureRemotingForAnsible.ps1')) 111 | 112 | EOF 113 | 114 | provisioner "remote-exec" { 115 | inline = ["echo booted"] 116 | 117 | connection { 118 | type = "winrm" 119 | user = "${var.win_username}" 120 | password = "${var.win_password}" 121 | host = "${aws_instance.windows_2016_dc.public_ip}" 122 | port = 5986 123 | insecure = true 124 | https = true 125 | } 126 | } 127 | 128 | provisioner "local-exec" { 129 | working_dir = "../ansible" 130 | command = "sed -i '' 's/PUBLICIP/${aws_instance.windows_2016_dc.public_ip}/g' inventory/hosts;ansible-playbook -i inventory/hosts playbooks/windows_dc.yml --extra-vars 'splunk_indexer_ip=${aws_instance.splunk-server.private_ip}'" 131 | } 132 | 133 | } 134 | 135 | 136 | output "splunk_server" { 137 | value = "http://${aws_eip.splunk_ip.public_ip}:8000" 138 | } 139 | 140 | output "splunk_username" { 141 | value = "admin" 142 | } 143 | 144 | output "splunk_password" { 145 | value = "please use password configured under attack_range.conf -> splunk_admin_password" 146 | } 147 | 148 | output "windows_dc_ip" { 149 | value = "connect using an RDP client to ${aws_instance.windows_2016_dc.public_ip} on 3389" 150 | } 151 | 152 | output "windows_dc_user" { 153 | value = "${var.win_username}" 154 | } 155 | 156 | output "windows_dc_password" { 157 | value = "${var.win_password}" 158 | } 159 | -------------------------------------------------------------------------------- /ansible/roles/sysmon/templates/SysmonConfig-Neo23x0-workstations.xml.j2: -------------------------------------------------------------------------------- 1 | {{ ansible_managed | comment('xml') }} 2 | 16 | 17 | 18 | MD5,SHA1,SHA256,IMPHASH 19 | 20 | 21 | 22 | 23 | microsoft 24 | windows 25 | 26 | 27 | 28 | System 29 | 30 | 31 | 32 | WmiPrvSE.exe 33 | FireSvc.exe 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | Windows\CurrentVersion\Run 44 | Windows\CurrentVersion\Image File Execution Options 45 | CurrentControlSet\Services 46 | Microsoft\Windows NT\CurrentVersion\Winlogon 47 | Microsoft\Windows\CurrentVersion\Policies\Explorer 48 | Microsoft\Windows\CurrentVersion\RunOnce 49 | System\CurrentControlSet\Services\Tcpip\parameters 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | chrome.exe 58 | iexplore.exe 59 | firefox.exe 60 | 8080 61 | 62 | 65 | 66 | 67 | 68 | 69 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /docs/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to the Project 2 | 3 | This document is the single source of truth on how to contribute to this codebase. Please feel free to browse the open issues and file new ones. All feedback is welcome! 4 | 5 | ---- 6 | 7 | ## Topics 8 | 9 | * [Prerequisites](#prerequisites) 10 | * [Contributor License Agreement](#contributor-license-agreement) 11 | * [Code of Conduct](#code-of-conduct) 12 | * [Contribution Workflow](#contribution-workflow) 13 | * [Feature Requests and Bug Reports](#feature-requests-and-bug-reports) 14 | * [Fixing Issues](#fixing-issues) 15 | * [Pull Requests](#pull-requests) 16 | * [Code Review](#code-review) 17 | * [Documentation](#documentation) 18 | * [Maintainers](#maintainers) 19 | 20 | ---- 21 | 22 | ## Prerequisites 23 | When contributing to this repository, please first discuss the change you wish to make via a GitHub issue, Slack message, email, or via other channels with the owners of this repository. 24 | 25 | ##### Contributor License Agreement 26 | At the moment, we can only accept pull requests submitted from either: 27 | * Splunk employees or 28 | * Individuals that have signed our contributors' agreement 29 | 30 | If you wish to be a contributing member of our community, please see the agreement [for individuals](https://www.splunk.com/goto/individualcontributions) or [for organizations](https://www.splunk.com/goto/contributions). 31 | 32 | ##### Code of Conduct 33 | Please make sure to read and observe our [Code of Conduct](contributing/code-of-conduct.md). Please follow it in all of your interactions involving the project. 34 | 35 | ## Contribution Workflow 36 | Help is always welcome! For example, documentation can always use improvement. There's always code that can be clarified, functionality that can be extended, and tests to be added to guarantee behavior. If you see something you think should be fixed, don't be afraid to own it. 37 | 38 | ##### Feature Requests and Bug Reports 39 | Have ideas on improvements? See something that needs work? While the community encourages everyone to contribute code, it is also appreciated when someone reports an issue. Please report any issues or bugs you find through [GitHub's issue tracker](https://github.com/splunk/attack_range/issues). 40 | 41 | If you are reporting a bug, please include: 42 | 43 | * Your operating system name and version 44 | * Any details about your local setup that might be helpful in troubleshooting (ex. Python interpreter version, Splunk version, etc.) 45 | * Detailed steps to reproduce the bug 46 | 47 | We'd also like to hear about your propositions and suggestions. Feel free to submit them as issues and: 48 | 49 | * Explain in detail how they should work 50 | * Note that keeping the scope as narrow as possible will make the suggestion easier to implement 51 | 52 | ##### Fixing Issues 53 | Look through our [issue tracker](https://github.com/splunk/attack_range/issues) to find problems to fix! Feel free to comment and tag corresponding stakeholders or full-time maintainers of this project with any questions or concerns. 54 | 55 | ##### Pull Requests 56 | What is a "pull request"? It informs the project's core developers about the changes you want to review and merge. Once you submit a pull request, it enters a stage of code review where you and others can discuss its potential modifications and maybe even add more commits to it later on. 57 | 58 | If you want to learn more, please consult this [tutorial on how pull requests work](https://help.github.com/articles/using-pull-requests/) in the [GitHub Help Center](https://help.github.com/). 59 | 60 | Here's an overview of how you can make a pull request against this project: 61 | 62 | 1. Fork the [analytic\_story\_execution GitHub repository](https://github.com/splunk/attack_range/issues) 63 | 2. Clone your fork using git and create a branch off of master 64 | 65 | ``` 66 | $ git clone git@github.com:YOUR_GITHUB_USERNAME/attack_range.git 67 | $ cd attack_range 68 | 69 | # This project uses 'master' for all development activity, so create your branch off that 70 | $ git checkout -b your-bugfix-branch-name master 71 | ``` 72 | 73 | 3. Make your changes, commit, and push (once your tests have passed) 74 | 75 | ``` 76 | $ cd attack_range 77 | $ git commit -m "" 78 | $ git push 79 | ``` 80 | 81 | 4. Submit a pull request through the GitHub website, using the changes from your forked codebase 82 | 83 | ##### Code Review 84 | There are two aspects of code review: giving and receiving. 85 | 86 | To make it easier for your PR to receive reviews, keep in mind that the reviewers will need you to: 87 | * Follow the project coding conventions 88 | * Write good commit messages 89 | * Break large changes into a logical series of smaller patches which individually make easily understandable changes, and in aggregate solve a broader issue 90 | 91 | Reviewers, the people providing the review, are highly encouraged to revisit the [Code of Conduct](contributing/code-of-conduct.md) and must go above and beyond to promote a collaborative, respectful community. 92 | 93 | When reviewing PRs from others, [The Gentle Art of Patch Review](http://sage.thesharps.us/2014/09/01/the-gentle-art-of-patch-review/) suggests an iterative series of focuses designed to lead new contributors to positive collaboration, such as: 94 | 95 | * Is the idea behind the contribution sound? 96 | * Is the contribution architected correctly? 97 | * Is the contribution polished? 98 | 99 | For this project, we require at least one approval. A build from our continuous integration system must also be successful off of your branch. Please note that any new changes made with your existing pull request during review will automatically unapprove and retrigger another build/round of tests. 100 | 101 | ##### Documentation 102 | We can always use improvements to our documentation! Anyone can contribute to these docs--whether you’re new to the project, you’ve been around a long time, or if you just can’t stand seeing typos. 103 | 104 | Here's what's needed? 105 | 106 | 1. More complementary documentation. Have you something unclear? 107 | 2. More examples or generic templates that others can use. 108 | 3. Blog posts, articles, and such are all very appreciated. 109 | 110 | You can also edit documentation files directly in the GitHub web interface, without creating a local copy. This can be convenient for small typos or grammar fixes. 111 | 112 | ## Maintainers 113 | 114 | If you need help, feel free to tag one of the active maintainers of this project in a post or comment. We'll do our best to reach out to you as quickly as we can. 115 | 116 | ``` 117 | # Active maintainers marked with (*) 118 | 119 | (*) Bhavin Patel 120 | (*) David Dorsey 121 | (*) Jose Hernandez 122 | ``` 123 | 124 | -------------------------------------------------------------------------------- /ansible/roles/sysmon/templates/SysmonConfig-Neo23x0-server.xml.j2: -------------------------------------------------------------------------------- 1 | {{ ansible_managed | comment('xml') }} 2 | 15 | 16 | 17 | MD5,SHA1,SHA256,IMPHASH 18 | 19 | 20 | 21 | 22 | microsoft 23 | windows 24 | 25 | 26 | 27 | splunk 28 | btool.exe 29 | SnareCore 30 | nxlog 31 | Microsoft Monitoring Agent\Agent\MonitoringHost.exe 32 | ClearMyTracksByProcess 33 | 34 | 35 | 36 | lsass.exe 37 | winlogon.exe 38 | svchost.exe 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | Windows\CurrentVersion\Run 49 | Windows\CurrentVersion\Image File Execution Options 50 | CurrentControlSet\Services 51 | Microsoft\Windows NT\CurrentVersion\Winlogon 52 | Microsoft\Windows\CurrentVersion\Policies\Explorer 53 | Microsoft\Windows\CurrentVersion\RunOnce 54 | System\CurrentControlSet\Services\Tcpip\parameters 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 80 63 | 443 64 | 8080 65 | 3389 66 | cmd.exe 67 | PsExe 68 | winexe 69 | powershell 70 | cscript 71 | mstsc 72 | RTS2App 73 | RTS3App 74 | wmic 75 | 76 | 77 | 78 | 79 | 80 | lsass.exe 81 | 82 | 83 | wmiprvse.exe 84 | GoogleUpdate.exe 85 | LTSVC.exe 86 | taskmgr.exe 87 | VBoxService.exe # Virtual Box 88 | vmtoolsd.exe 89 | taskmgr.exe 90 | \Citrix\System32\wfshell.exe #Citrix process in C:\Program Files (x86)\Citrix\System32\wfshell.exe 91 | C:\Windows\System32\lsm.exe # System process under C:\Windows\System32\lsm.exe 92 | Microsoft.Identity.AadConnect.Health.AadSync.Host.exe # Microsoft Azure AD Connect Health Sync Agent 93 | C:\Program Files (x86)\Symantec\Symantec Endpoint Protection # Symantec 94 | 95 | 99 | 100 | 101 | verclsid.exe 102 | svchost.exe 103 | 104 | 106 | 107 | 0x1F0FFF 108 | 0x1F1FFF 109 | 0x1F2FFF 110 | 0x1F3FFF 111 | 112 | 0x1FFFFF 113 | unknown 114 | 115 | 116 | 117 | -------------------------------------------------------------------------------- /ansible/roles/sysmon/templates/SysmonConfig-Verbose.xml.j2: -------------------------------------------------------------------------------- 1 | {{ ansible_managed | comment('xml') }} 2 | 5 | 6 | 7 | 8 | * 9 | 10 | 11 | 12 | splunk 13 | btool.exe 14 | SnareCore 15 | nxlog 16 | winlogbeat 17 | Microsoft Monitoring Agent\Agent\MonitoringHost.exe 18 | C:\Program Files\NVIDIA Corporation\Display\ 19 | C:\Program Files\Dell\SupportAssist\pcdrcui.exe 20 | C:\Program Files\Dell\SupportAssist\koala.exe 21 | C:\Program Files\Windows Defender 22 | C:\Windows\System32\audiodg.exe 23 | C:\Windows\SysWOW64\Macromed\Flash\FlashPlayerUpdateService.exe 24 | C:\Program Files (x86)\Google\Update\GoogleUpdate.exe 25 | \Sysmon.exe 26 | C:\WIndows\System32\poqexec.exe /noreboot /transaction 27 | 28 | 29 | 30 | 31 | 32 | C:\Program Files\Microsoft Office\Office15\ONENOTE.EXE 33 | Spotify.exe 34 | OneDrive.exe 35 | AppData\Roaming\Dashlane\Dashlane.exe 36 | AppData\Roaming\Dashlane\DashlanePlugin.exe 37 | winlogbeat.exe 38 | C:\Windows\System32\spoolsv.exe 39 | C:\Program Files\Common Files\microsoft shared\ClickToRun\OfficeClickToRun.exe 40 | C:\Program Files (x86)\Common Files\Acronis\SyncAgent\syncagentsrv.exe 41 | C:\Windows\SystemApps\Microsoft.Windows.Cortana_cw5n1h2txyewy\SearchUI.exe 42 | C:\Windows\System32\CompatTelRunner.exe 43 | C:\Program Files (x86)\Intel\Intel(R) Management Engine Components\LMS\LMS.exe 44 | C:\Program Files (x86)\Google\Chrome\Application\chrome.exe 45 | C:\Windows\System32\mmc.exe 46 | C:\Program Files\Microsoft VS Code\Code.exe 47 | 48 | 49 | 50 | 51 | 52 | microsoft 53 | windows 54 | VMware 55 | Intel 56 | 57 | 58 | 59 | chrome.exe 60 | vmtoolsd.exe 61 | Sysmon.exe 62 | mmc.exe 63 | C:\Program Files (x86)\Google\Update\GoogleUpdate.exe 64 | C:\Windows\System32\taskeng.exe 65 | C:\Program Files\VMware\VMware Tools\TPAutoConnect.exe 66 | C:\Program Files\Windows Defender\NisSrv.exe 67 | C:\Program Files\Windows Defender\MsMpEng.exe 68 | 69 | 70 | 71 | 72 | 73 | C:\Program Files\VMware\VMware Tools\vmtoolsd.exe 74 | C:\Program Files (x86)\Google\Update\GoogleUpdate.exe 75 | \Sysmon.exe 76 | 77 | 78 | 79 | C:\Program Files\VMware\VMware Tools\vmtoolsd.exe 80 | C:\Windows\system32\taskeng.exe 81 | C:\Windows\system32\lsass.exe 82 | Sysmon.exe 83 | GoogleUpdate.exe 84 | C:\Program Files (x86)\Google\Chrome\Application\chrome.exe 85 | C:\Program Files\Windows Defender\MsMpEng.exe 86 | C:\Program Files\Microsoft VS Code\Code.exe 87 | C:\Program Files\VMware\VMware Tools\TPAutoConnSvc.exe 88 | C:\Program Files\VMware\VMware Tools\TPAutoConnect.exe 89 | C:\Windows\system32\mmc.exe 90 | C:\Program Files\Microsoft VS Code\Code.exe 91 | C:\Windows\system32\sihost.exe 92 | C:\Program Files\Windows Defender\MsMpEng.exe 93 | c:\Program Files\Microsoft VS Code\resources\app\out\vs\workbench\services\files\node\watcher\win32\CodeHelper.exe 94 | C:\Windows\system32\ApplicationFrameHost.exe 95 | C:\Windows\System32\taskhostw.exe 96 | C:\Windows\System32\RuntimeBroker.exe 97 | 98 | 99 | 100 | SearchIndexer.exe 101 | winlogbeat.exe 102 | C:\Windows\system32\mmc.exe 103 | C:\Program Files (x86)\Google\Chrome\Application\chrome.exe 104 | C:\Program Files\Microsoft VS Code\Code.exe 105 | 106 | 107 | 108 | C:\Program Files\VMware\VMware Tools\vmtoolsd.exe 109 | C:\Windows\system32\mmc.exe 110 | C:\Windows\system32\taskeng.exe 111 | C:\Windows\System32\svchost.exe 112 | C:\Windows\system32\lsass.exe 113 | C:\Windows\Sysmon.exe 114 | GoogleUpdate.exe 115 | C:\Program Files\VMware\VMware Tools\TPAutoConnect.exe 116 | C:\Program Files\Windows Defender\NisSrv.exe 117 | \REGISTRY\MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Print\Printers\Microsoft Print to PDF\PrinterDriverData 118 | LanguageList 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | -------------------------------------------------------------------------------- /ansible/roles/search_head/files/datamodels.conf: -------------------------------------------------------------------------------- 1 | ##################### 2 | ## Alerts 3 | ##################### 4 | [Alerts] 5 | acceleration = true 6 | acceleration.allow_old_summaries = true 7 | acceleration.manual_rebuilds = true 8 | acceleration.schedule_priority = highest 9 | tags_whitelist = pci 10 | 11 | 12 | ##################### 13 | ## Application State (Deprecated) 14 | ##################### 15 | [Application_State] 16 | acceleration = true 17 | acceleration.allow_old_summaries = true 18 | acceleration.cron_schedule = 3-58/5 * * * * 19 | acceleration.earliest_time = -1mon 20 | acceleration.manual_rebuilds = true 21 | acceleration.schedule_priority = highest 22 | tags_whitelist = pci,listening,port,process,report,service,time,synchronize,update 23 | 24 | 25 | ##################### 26 | ## Authentication 27 | ##################### 28 | [Authentication] 29 | acceleration = true 30 | acceleration.allow_old_summaries = true 31 | acceleration.cron_schedule = 3-58/5 * * * * 32 | acceleration.earliest_time = -1y 33 | acceleration.manual_rebuilds = true 34 | acceleration.schedule_priority = highest 35 | tags_whitelist = pci,default,insecure,cleartext,privileged,multifactor 36 | 37 | 38 | ##################### 39 | ## Certificates 40 | ##################### 41 | [Certificates] 42 | acceleration = true 43 | acceleration.allow_old_summaries = true 44 | acceleration.cron_schedule = 3-58/5 * * * * 45 | acceleration.earliest_time = -1y 46 | acceleration.manual_rebuilds = true 47 | acceleration.schedule_priority = highest 48 | tags_whitelist = pci,ssl,tls,network,communicate 49 | 50 | 51 | ##################### 52 | ## Change 53 | ##################### 54 | [Change] 55 | acceleration = true 56 | acceleration.allow_old_summaries = true 57 | acceleration.cron_schedule = 2-57/5 * * * * 58 | acceleration.earliest_time = -1y 59 | acceleration.manual_rebuilds = true 60 | acceleration.schedule_priority = highest 61 | tags_whitelist = pci,account,audit,endpoint,network,delete 62 | 63 | ## This datamodel has been deprecated 64 | [Change_Analysis] 65 | acceleration = true 66 | acceleration.allow_old_summaries = true 67 | acceleration.cron_schedule = 2-57/5 * * * * 68 | acceleration.earliest_time = -1y 69 | acceleration.manual_rebuilds = true 70 | acceleration.schedule_priority = highest 71 | tags_whitelist = pci,account,audit,endpoint,network,delete 72 | 73 | 74 | ########################## 75 | ## Compute Inventory 76 | ########################## 77 | [Compute_Inventory] 78 | acceleration = true 79 | acceleration.allow_old_summaries = true 80 | acceleration.manual_rebuilds = true 81 | acceleration.schedule_priority = highest 82 | tags_whitelist = pci,cpu,default,interactive,memory,network,snapshot,storage,system,version,tools,user,virtual 83 | 84 | 85 | ########################## 86 | ## Databases 87 | ########################## 88 | [Databases] 89 | acceleration = true 90 | acceleration.allow_old_summaries = true 91 | acceleration.manual_rebuilds = true 92 | acceleration.schedule_priority = highest 93 | tags_whitelist = pci,instance,lock,query,session,stats,tablespace 94 | 95 | 96 | ########################## 97 | ## DLP 98 | ########################## 99 | [DLP] 100 | acceleration = true 101 | acceleration.allow_old_summaries = true 102 | acceleration.cron_schedule = 2-57/5 * * * * 103 | acceleration.earliest_time = -1y 104 | acceleration.manual_rebuilds = true 105 | acceleration.schedule_priority = highest 106 | tags_whitelist = pci 107 | 108 | 109 | ##################### 110 | ## Endpoint 111 | ##################### 112 | [Endpoint] 113 | acceleration = true 114 | acceleration.allow_old_summaries = true 115 | acceleration.cron_schedule = 3-58/5 * * * * 116 | acceleration.earliest_time = -1mon 117 | acceleration.manual_rebuilds = true 118 | acceleration.max_concurrent = 1 119 | acceleration.schedule_priority = highest 120 | tags_whitelist = pci,change,listening,port,process,report,service,time,synchronize,update 121 | 122 | 123 | ##################### 124 | ## Email 125 | ##################### 126 | [Email] 127 | acceleration = true 128 | acceleration.allow_old_summaries = true 129 | acceleration.cron_schedule = 3-58/5 * * * * 130 | acceleration.earliest_time = -1y 131 | acceleration.manual_rebuilds = true 132 | acceleration.schedule_priority = highest 133 | tags_whitelist = pci,delivery,content,filter 134 | 135 | 136 | ########################## 137 | ## Interprocess Messaging 138 | ########################## 139 | [Interprocess_Messaging] 140 | acceleration = true 141 | acceleration.allow_old_summaries = true 142 | acceleration.cron_schedule = 4-59/5 * * * * 143 | acceleration.earliest_time = -1y 144 | acceleration.manual_rebuilds = true 145 | acceleration.schedule_priority = highest 146 | tags_whitelist = pci 147 | 148 | 149 | ########################## 150 | ## Intrusion Detection 151 | ########################## 152 | [Intrusion_Detection] 153 | acceleration = true 154 | acceleration.allow_old_summaries = true 155 | acceleration.cron_schedule = 4-59/5 * * * * 156 | acceleration.earliest_time = -1y 157 | acceleration.manual_rebuilds = true 158 | acceleration.schedule_priority = highest 159 | tags_whitelist = pci,misconfiguration,pii,rogue,unauthorized-device,unencrypted,wireless 160 | 161 | 162 | ########################## 163 | ## JVM 164 | ########################## 165 | [JVM] 166 | acceleration = true 167 | acceleration.allow_old_summaries = true 168 | acceleration.manual_rebuilds = true 169 | acceleration.schedule_priority = highest 170 | tags_whitelist = pci,classloading,compilation,memory,os,runtime,threading 171 | 172 | 173 | ########################## 174 | ## Malware 175 | ########################## 176 | [Malware] 177 | acceleration = true 178 | acceleration.allow_old_summaries = true 179 | acceleration.cron_schedule = 1-56/5 * * * * 180 | acceleration.earliest_time = -1y 181 | acceleration.manual_rebuilds = true 182 | acceleration.schedule_priority = highest 183 | tags_whitelist = pci 184 | 185 | 186 | ########################## 187 | ## Network Resolution 188 | ########################## 189 | [Network_Resolution] 190 | acceleration = true 191 | acceleration.allow_old_summaries = true 192 | acceleration.cron_schedule = 2-57/5 * * * * 193 | acceleration.earliest_time = -3mon 194 | acceleration.manual_rebuilds = true 195 | acceleration.schedule_priority = highest 196 | tags_whitelist = pci 197 | 198 | 199 | ########################## 200 | ## Network Sessions 201 | ########################## 202 | [Network_Sessions] 203 | acceleration = true 204 | acceleration.allow_old_summaries = true 205 | acceleration.cron_schedule = 2-57/5 * * * * 206 | acceleration.earliest_time = -3mon 207 | acceleration.manual_rebuilds = true 208 | acceleration.schedule_priority = highest 209 | tags_whitelist = pci,start,end,dhcp,vpn 210 | 211 | 212 | ########################## 213 | ## Network Traffic 214 | ########################## 215 | [Network_Traffic] 216 | acceleration = true 217 | acceleration.allow_old_summaries = true 218 | acceleration.cron_schedule = 1-56/5 * * * * 219 | acceleration.earliest_time = -3mon 220 | acceleration.manual_rebuilds = true 221 | acceleration.schedule_priority = highest 222 | tags_whitelist = pci 223 | 224 | 225 | ########################## 226 | ## Performance 227 | ########################## 228 | [Performance] 229 | acceleration = true 230 | acceleration.allow_old_summaries = true 231 | acceleration.cron_schedule = 4-59/5 * * * * 232 | acceleration.earliest_time = -1mon 233 | acceleration.manual_rebuilds = true 234 | acceleration.schedule_priority = highest 235 | tags_whitelist = cpu,facilities,failure,memory,network,storage,success,os,time,synchronize,uptime 236 | 237 | 238 | ########################## 239 | ## Splunk Audit 240 | ########################## 241 | [Splunk_Audit] 242 | acceleration = true 243 | acceleration.allow_old_summaries = true 244 | acceleration.cron_schedule = */5 * * * * 245 | acceleration.earliest_time = -1y 246 | acceleration.manual_rebuilds = true 247 | acceleration.schedule_priority = highest 248 | tags_whitelist = pci,invocation 249 | 250 | 251 | ########################## 252 | ## Ticket Management 253 | ########################## 254 | [Ticket_Management] 255 | acceleration = true 256 | acceleration.allow_old_summaries = true 257 | acceleration.cron_schedule = */5 * * * * 258 | acceleration.earliest_time = -1y 259 | acceleration.manual_rebuilds = true 260 | acceleration.schedule_priority = highest 261 | tags_whitelist = pci,change,incident,problem 262 | 263 | 264 | ########################## 265 | ## Updates 266 | ########################## 267 | [Updates] 268 | acceleration = true 269 | acceleration.allow_old_summaries = true 270 | acceleration.cron_schedule = 2-57/5 * * * * 271 | acceleration.earliest_time = -1y 272 | acceleration.manual_rebuilds = true 273 | acceleration.schedule_priority = highest 274 | tags_whitelist = pci,system 275 | 276 | 277 | ########################## 278 | ## Vulnerabilities 279 | ########################## 280 | [Vulnerabilities] 281 | acceleration = true 282 | acceleration.allow_old_summaries = true 283 | acceleration.cron_schedule = 1-56/5 * * * * 284 | acceleration.earliest_time = -1y 285 | acceleration.manual_rebuilds = true 286 | acceleration.schedule_priority = highest 287 | tags_whitelist = pci,misconfiguration 288 | 289 | 290 | ########################## 291 | ## Web 292 | ########################## 293 | [Web] 294 | acceleration = true 295 | acceleration.allow_old_summaries = true 296 | acceleration.cron_schedule = */5 * * * * 297 | acceleration.earliest_time = -3mon 298 | acceleration.manual_rebuilds = true 299 | acceleration.schedule_priority = highest 300 | tags_whitelist = pci,proxy,web_watchlist 301 | -------------------------------------------------------------------------------- /ansible/roles/sysmon/templates/SysmonConfig-moti.xml.j2: -------------------------------------------------------------------------------- 1 | {{ ansible_managed | comment('xml') }} 2 | 14 | 15 | SHA256,IMPHASH 16 | 17 | 18 | 19 | \Startup\ 20 | 21 | 22 | 23 | Software\Microsoft\Windows\CurrentVersion\Run 24 | CurrentControlSet\Control\Session Manager\BootExecute 25 | Software\Microsoft\Windows\CurrentVersion\RunServicesOnce 26 | Software\Microsoft\Windows\CurrentVersion\RunServices 27 | SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\Notify 28 | Software\Microsoft\Windows NT\CurrentVersion\Winlogon\Userinit 29 | Software\Microsoft\Windows NT\CurrentVersion\Winlogon 30 | SOFTWARE\Microsoft\Windows\CurrentVersion\ShellServiceObjectDelayLoad 31 | Software\Microsoft\Windows\CurrentVersion\RunOnce 32 | Software\Microsoft\Windows\CurrentVersion\RunOnceEx 33 | Software\Microsoft\Windows\CurrentVersion\Policies\Explorer\Run 34 | Software\Microsoft\Windows NT\CurrentVersion\Windows\load 35 | Software\Microsoft\Windows NT\CurrentVersion\Windows\\AppInit_DLLs 36 | SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs 37 | 38 | System\CurrentControlSet\Control\Lsa\Security Packages 39 | 40 | 41 | 42 | False 43 | 44 | 45 | C:\Windows\assembly\NativeImages 46 | 47 | 48 | Microsoft Windows 49 | Microsoft Corporation 50 | NVIDIA Corporation 51 | 52 | 53 | 54 | C:\Windows\system32\lsass.exe 55 | C:\Windows\system32\winlogon.exe 56 | C:\Windows\system32\svchost.exe 57 | "C:\Program Files\Google\Chrome\Application\chrome.exe" 58 | "C:\Program Files\Internet Explorer\iexplore.exe" 59 | "C:\Program Files (x86)\Mozilla Firefox\firefox.exe" 60 | 61 | 62 | 63 | c:\Program Files\Windows Defender\MsMpEng.exe 64 | Program Files\Windows Defender\MsMpEng.exe 65 | 66 | 67 | 68 | System 69 | C:\Windows\CCM\CcmExec.exe 70 | C:\Windows\System32\svchost.exe 71 | C:\Program Files\Windows Defender\MsMpEng.exe 72 | C:\Windows\System32\SrTasks.exe 73 | C:\Windows\System32\MRT.exe 74 | C:\Windows\System32\SearchIndexer.exe 75 | C:\Windows\System32\winlogon.exe 76 | C:\Windows\System32\smss.exe 77 | C:\Windows\System32\autochk.exe 78 | C:\Windows\System32\CompatTelRunner.exe 79 | C:\Windows\System32\DeviceCensus.exe 80 | C:\Windows\System32\wininit.exe 81 | C:\Windows\System32\VSSVC.exe 82 | C:\Windows\System32\bcdedit.exe 83 | C:\Windows\System32\WinSAT.exe 84 | C:\Windows\SysWOW64\msiexec.exe 85 | C:\Windows\explorer.exe 86 | C:\Windows\System32\DiskSnapshot.exe 87 | 88 | 89 | 90 | 91 | C:\Windows\system32\lsass.exe 92 | C:\Windows\system32\winlogon.exe 93 | "C:\Program Files\Google\Chrome\Application\chrome.exe" 94 | "C:\Program Files\Internet Explorer\iexplore.exe" 95 | "C:\Program Files (x86)\Mozilla Firefox\firefox.exe" 96 | 97 | 98 | 99 | c:\windows\system32\svchost.exe 100 | C:\WINDOWS\system32\wbem\wmiprvse.exe 101 | C:\WINDOWS\System32\perfmon.exe 102 | C:\WINDOWS\system32\LogonUI.exe 103 | C:\WINDOWS\system32\MRT.exe 104 | C:\Windows\System32\MsiExec.exe 105 | C:\windows\CCM\CcmExec.exe 106 | C:\WINDOWS\system32\taskmgr.exe 107 | C:\WINDOWS\system32\lsass.exe 108 | C:\WINDOWS\system32\services.exe 109 | C:\WINDOWS\system32\wininit.exe 110 | C:\WINDOWS\system32\csrss.exe 111 | C:\WINDOWS\System32\smss.exe 112 | C:\Program Files\Windows Defender Advanced Threat Protection\MsSense.exe 113 | C:\Windows\syswow64\MsiExec.exe 114 | C:\Program Files (x86)\Common Files\Adobe\ARM\1.0\AdobeARMHelper.exe 115 | Program Files\Windows Defender\MsMpEng.exe 116 | 117 | 118 | 119 | AppContainer 120 | 121 | C:\Windows\System32\audiodg.exe 122 | System32\backgroundTaskHost.exe 123 | System32\BackgroundTransferHost.exe 124 | System32\dllhost.exe 125 | System32\smartscreen.exe 126 | System32\SearchFilterHost.exe 127 | System32\audiodg.exe 128 | System32\conhost.exe 129 | System32\SearchProtocolHost.exe 130 | SysWOW64\msiexec.exe 131 | system32\msiexec.exe 132 | microsoft shared\ClickToRun\OfficeClickToRun.exe 133 | System32\consent.exe 134 | System32\LogonUI.exe 135 | System32\taskhostw.exe 136 | System32\LockAppHost.exe 137 | Chrome\Application\chrome.exe 138 | Internet Explorer\iexplorer.exe 139 | Mozilla Firefox\firefox.exe 140 | 141 | 142 | 143 | C:\Windows\System32\RuntimeBroker.exe 144 | c:\windows\system32\svchost.exe 145 | C:\WINDOWS\system32\MpSigStub.exe 146 | C:\WINDOWS\System32\LogonUI.exe 147 | C:\WINDOWS\ImmersiveControlPanel\SystemSettings.exe 148 | C:\WINDOWS\system32\SettingSyncHost.exe 149 | C:\WINDOWS\explorer.exe 150 | C:\WINDOWS\system32\mmc.exe 151 | C:\windows\CCM\CcmExec.exe 152 | C:\WINDOWS\system32\msiexec.exe 153 | C:\WINDOWS\system32\taskmgr.exe 154 | WINDOWS\system32\WindowsPowerShell\v1.0\PowerShell_ISE.exe 155 | WINDOWS\system32\backgroundTaskHost.exe 156 | Mozilla Firefox\firefox.exe 157 | Google\Chrome\Application\chrome.exe 158 | 159 | 160 | 161 | 162 | 163 | C:\Users 164 | C:\ProgramData 165 | powershell.exe 166 | cmd.exe 167 | wmic.exe 168 | cscript.exe 169 | wscript.exe 170 | rundll32.exe 171 | 172 | 173 | chrome.exe 174 | iexplore.exe 175 | firefox.exe 176 | outlook.exe 177 | Skype.exe 178 | lync.exe 179 | GoogleUpdate.exe 180 | qbittorrent.exe 181 | OfficeClickToRun.exe 182 | Windows\SystemApps\Microsoft.Windows.Cortana 183 | OneDrive.exe 184 | Windows\System32\svchost.exe 185 | System32\backgroundTaskHost.exe 186 | Skype\Browser\SkypeBrowserHost.exe 187 | Free Download Manager\fdm.exe 188 | 172. 189 | 10. 190 | 192. 191 | 0.0.0.0 192 | 193 | 194 | 195 | -------------------------------------------------------------------------------- /attack_range.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import re 3 | import vagrant 4 | import ansible_runner 5 | import subprocess 6 | import boto3 7 | from python_terraform import * 8 | from modules import logger, parseconfig 9 | from pathlib import Path 10 | from tabulate import tabulate 11 | 12 | # need to set this ENV var due to a OSX High Sierra forking bug 13 | # see this discussion for more details: https://github.com/ansible/ansible/issues/34056#issuecomment-352862252 14 | os.environ['OBJC_DISABLE_INITIALIZE_FORK_SAFETY'] = 'YES' 15 | 16 | VERSION = 1 17 | 18 | 19 | # could be improved by directly use extra-vars 20 | def config_simulation(simulation_engine, simulation_technique, log): 21 | 22 | # Read in the ansible vars file 23 | with open('ansible/vars/vars.yml.default', 'r') as file: 24 | ansiblevars = file.read() 25 | 26 | # now set the simulation engine and mitre techniques to run 27 | if simulation_engine == "atomic_red_team": 28 | ansiblevars = re.sub(r'install_art: \w+', 'install_art: true', ansiblevars, re.M) 29 | log.info("execution simulation using engine: {0}".format(simulation_engine)) 30 | 31 | if simulation_technique[0] != '' or len(simulation_technique) > 1: 32 | technique = "art_run_technique: " + str(simulation_technique) 33 | ansiblevars = re.sub(r'art_run_technique: .+', technique, ansiblevars, re.M) 34 | ansiblevars = re.sub(r'art_run_all_test: \w+', 'art_run_all_test: false', ansiblevars, re.M) 35 | log.info("executing specific ATT&CK technique ID: {0}".format(simulation_technique)) 36 | else: 37 | ansiblevars = re.sub(r'art_run_all_test: \w+', 'art_run_all_test: true', ansiblevars, re.M) 38 | log.info("executing ALL Atomic Red Team ATT&CK techniques see: https://github.com/redcanaryco/atomic-red-team/tree/master/atomics".format( 39 | simulation_technique)) 40 | 41 | # Write the file out again 42 | with open('ansible/vars/vars.yml', 'w') as file: 43 | file.write(ansiblevars) 44 | 45 | 46 | def run_simulation(mode, simulation_engine, simulation_techniques, target, log): 47 | 48 | if mode == "terraform": 49 | with open('ansible/inventory/hosts', 'r') as file: 50 | hosts_file = file.read() 51 | hosts_file = hosts_file.replace('PUBLICIP', target) 52 | with open('ansible/inventory/hosts', 'w') as file: 53 | file.write(hosts_file) 54 | 55 | 56 | # execute atomic red team simulation 57 | if simulation_engine == "atomic_red_team": 58 | r = ansible_runner.run(private_data_dir='.attack_range/', 59 | inventory=os.path.dirname(os.path.realpath( 60 | __file__)) + '/ansible/inventory/hosts', 61 | roles_path="../roles", 62 | playbook=os.path.dirname(os.path.realpath(__file__)) + '/ansible/playbooks/atomic_red_team.yml', 63 | verbosity=0) 64 | 65 | if r.status == "successful": 66 | log.info("successfully executed technique ID {0} against target: {1}".format(simulation_techniques, target)) 67 | else: 68 | log.error("failed to executed technique ID {0} against target: {1}".format(simulation_techniques, target)) 69 | sys.exit(1) 70 | 71 | 72 | def prep_ansible(settings): 73 | # prep ansible for configuration 74 | # Read in the ansible vars file 75 | with open('ansible/vars/vars.yml.default', 'r') as file: 76 | ansiblevars = file.read() 77 | 78 | # Replace the ansible variables 79 | ansiblevars = re.sub(r'domain_admin_password: .+', 'domain_admin_password: ' + str(settings['win_password']), 80 | ansiblevars, re.M) 81 | ansiblevars = re.sub(r'splunk_pass: .+', 'splunk_pass: ' + str(settings['splunk_admin_password']), 82 | ansiblevars, re.M) 83 | ansiblevars = re.sub(r's3_bucket_url: .+', 's3_bucket_url: ' + str(settings['s3_bucket_url']), 84 | ansiblevars, re.M) 85 | ansiblevars = re.sub(r'splunk_windows_ta: .+', 'splunk_windows_ta: ' + str(settings['splunk_windows_ta']), 86 | ansiblevars, re.M) 87 | ansiblevars = re.sub(r'splunk_sysmon_ta: .+', 'splunk_sysmon_ta: ' + str(settings['splunk_sysmon_ta']), 88 | ansiblevars, re.M) 89 | ansiblevars = re.sub(r'splunk_stream_ta: .+', 'splunk_stream_ta: ' + str(settings['splunk_stream_ta']), 90 | ansiblevars, re.M) 91 | ansiblevars = re.sub(r'splunk_stream_app: .+', 'splunk_stream_app: ' + str(settings['splunk_stream_app']), 92 | ansiblevars, re.M) 93 | ansiblevars = re.sub(r'splunk_cim_app: .+', 'splunk_cim_app: ' + str(settings['splunk_cim_app']), 94 | ansiblevars, re.M) 95 | ansiblevars = re.sub(r'splunk_escu_app: .+', 'splunk_escu_app: ' + str(settings['splunk_escu_app']), 96 | ansiblevars, re.M) 97 | ansiblevars = re.sub(r'splunk_asx_app:: .+', 'splunk_asx_app: ' + str(settings['splunk_asx_app']), 98 | ansiblevars, re.M) 99 | ansiblevars = re.sub(r'splunk_url: .+', 'splunk_url: ' + str(settings['splunk_url']), 100 | ansiblevars, re.M) 101 | ansiblevars = re.sub(r'splunk_binary: .+', 'splunk_binary: ' + str(settings['splunk_binary']), 102 | ansiblevars, re.M) 103 | 104 | # Write the file out again 105 | with open('ansible/vars/vars.yml', 'w') as file: 106 | file.write(ansiblevars) 107 | 108 | 109 | with open('ansible/inventory/hosts.default', 'r') as file: 110 | hosts_file = file.read() 111 | 112 | 113 | if mode == "vagrant": 114 | hosts_file = re.sub(r'ansible_ssh_port=.+', 'ansible_ssh_port=5985', 115 | hosts_file, re.M) 116 | hosts_file = re.sub(r'ansible_ssh_user=.+', 'ansible_ssh_user=vagrant', 117 | hosts_file, re.M) 118 | hosts_file = re.sub(r'ansible_ssh_pass=.+', 'ansible_ssh_pass=vagrant', 119 | hosts_file, re.M) 120 | hosts_file = hosts_file.replace('PUBLICIP', '127.0.0.1') 121 | else: 122 | hosts_file = re.sub(r'ansible_ssh_port=.+', 'ansible_ssh_port=5986', 123 | hosts_file, re.M) 124 | hosts_file = re.sub(r'ansible_ssh_user=.+', 'ansible_ssh_user=Administrator', 125 | hosts_file, re.M) 126 | hosts_file = re.sub(r'ansible_ssh_pass=.+', 'ansible_ssh_pass=' + str(settings['win_password']), 127 | hosts_file, re.M) 128 | 129 | 130 | # write hosts file to run from 131 | with open('ansible/inventory/hosts', 'w') as file: 132 | file.write(hosts_file) 133 | 134 | 135 | 136 | def prep_terraform(settings): 137 | # prep terraform for configuration 138 | # Read in the ansible vars file 139 | with open('terraform/terraform.tfvars', 'r') as file: 140 | terraformvars = file.read() 141 | 142 | # Replace the ansible variables 143 | terraformvars = re.sub(r'key_name = .+', 'key_name = "' + str(settings['key_name']) + '"', terraformvars, re.M) 144 | terraformvars = re.sub(r'ip_whitelist = .+', 'ip_whitelist = ' + str(settings['ip_whitelist']), 145 | terraformvars, re.M) 146 | terraformvars = re.sub(r'win_password = .+', 'win_password = "' + str(settings['win_password']) + '"', 147 | terraformvars, re.M) 148 | terraformvars = re.sub(r'private_key_path = .+', 'private_key_path = "' + str(settings['private_key_path']) + '"', 149 | terraformvars, re.M) 150 | # Write the file out again 151 | with open('terraform/terraform.tfvars', 'w') as file: 152 | file.write(terraformvars) 153 | 154 | 155 | def vagrant_mode(action, log): 156 | 157 | vagrantfile = 'vagrant/' 158 | 159 | if action == "build": 160 | log.info("building splunk-server and windows10 workstation boxes WARNING MAKE SURE YOU HAVE 8GB OF RAM free otherwise you will have a bad time") 161 | log.info("[action] > build\n") 162 | v1 = vagrant.Vagrant(vagrantfile, quiet_stdout=False) 163 | v1.up(provision=True) 164 | log.info("attack_range has been built using vagrant successfully") 165 | 166 | if action == "destroy": 167 | log.info("[action] > destroy\n") 168 | v1 = vagrant.Vagrant(vagrantfile, quiet_stdout=False) 169 | v1.destroy() 170 | log.info("attack_range has been destroy using vagrant successfully") 171 | 172 | if action == "stop": 173 | print("[action] > stop\n") 174 | v1 = vagrant.Vagrant(vagrantfile, quiet_stdout=False) 175 | v1.halt() 176 | 177 | if action == "resume": 178 | print("[action] > resume\n") 179 | v1 = vagrant.Vagrant(vagrantfile, quiet_stdout=False) 180 | v1.up() 181 | 182 | 183 | def attack_simulation(mode, target, simulation_engine, simulation_techniques, log): 184 | if mode == 'vagrant': 185 | v1 = vagrant.Vagrant('vagrant/', quiet_stdout=False) 186 | status = v1.status() 187 | # Check if target exist and if it is running 188 | check_targets_running_vagrant(target, log) 189 | config_simulation(simulation_engine, simulation_techniques, log) 190 | run_simulation('vagrant', simulation_engine, simulation_techniques, target, log) 191 | 192 | if mode == 'terraform': 193 | target_IP = check_targets_running_terraform(target, log) 194 | config_simulation(simulation_engine, simulation_techniques, log) 195 | run_simulation('terraform', simulation_engine, simulation_techniques, target_IP, log) 196 | 197 | 198 | def check_targets_running_terraform(target, log): 199 | with open('terraform/terraform.tfvars', 'r') as file: 200 | terraformvars = file.read() 201 | 202 | pattern = 'key_name = \"([^\"]*)' 203 | a = re.search(pattern, terraformvars) 204 | client = boto3.client('ec2') 205 | response = client.describe_instances( 206 | Filters=[ 207 | { 208 | 'Name': "tag:Name", 209 | 'Values': [target] 210 | }, 211 | { 212 | 'Name': "key-name", 213 | 'Values': [a.group(1)] 214 | } 215 | ] 216 | ) 217 | 218 | if len(response['Reservations']) == 0: 219 | log.error(target + ' not found as AWS EC2 instance.') 220 | sys.exit(1) 221 | 222 | # iterate through reservations and instances 223 | found_running_instance = False 224 | for reservation in response['Reservations']: 225 | 226 | for instance in reservation['Instances']: 227 | if instance['State']['Name'] == 'running': 228 | found_running_instance = True 229 | return instance['NetworkInterfaces'][0]['Association']['PublicIp'] 230 | 231 | if not found_running_instance: 232 | log.error(target + ' not running.') 233 | sys.exit(1) 234 | 235 | 236 | def check_targets_running_vagrant(target, log): 237 | v1 = vagrant.Vagrant('vagrant/', quiet_stdout=False) 238 | status = v1.status() 239 | 240 | found_box = False 241 | for stat in status: 242 | if stat.name == target: 243 | found_box = True 244 | if not (stat.state == 'running'): 245 | log.error(target + ' not running.') 246 | sys.exit(1) 247 | break 248 | if not found_box: 249 | log.error(target + ' not found as vagrant box.') 250 | sys.exit(1) 251 | 252 | 253 | 254 | def terraform_mode(action, log): 255 | if action == "build": 256 | log.info("[action] > build\n") 257 | t = Terraform(working_dir='terraform') 258 | return_code, stdout, stderr = t.apply( 259 | capture_output='yes', skip_plan=True, no_color=IsNotFlagged) 260 | log.info("attack_range has been built using terraform successfully") 261 | 262 | if action == "destroy": 263 | log.info("[action] > destroy\n") 264 | t = Terraform(working_dir='terraform') 265 | return_code, stdout, stderr = t.destroy(capture_output='yes', no_color=IsNotFlagged) 266 | log.info("attack_range has been destroy using terraform successfully") 267 | 268 | if action == "stop" or action == "resume": 269 | instances, key_name = find_terraform_instances() 270 | change_terraform_state(instances, action, key_name, log) 271 | 272 | 273 | def change_terraform_state(instances, action, key_name, log): 274 | client = boto3.client('ec2') 275 | # iterate through reservations and instances 276 | found_instance = False 277 | for instance in instances: 278 | if action == 'stop': 279 | if instance['State']['Name'] == 'running': 280 | found_instance = True 281 | response = client.stop_instances( 282 | InstanceIds=[instance['InstanceId']] 283 | ) 284 | log.info('Successfully stopped instance with ID ' + 285 | instance['InstanceId'] + ' .') 286 | else: 287 | if instance['State']['Name'] == 'stopped': 288 | found_instance = True 289 | response = client.start_instances( 290 | InstanceIds=[instance['InstanceId']] 291 | ) 292 | log.info('Successfully started instance with ID ' + instance['InstanceId'] + ' .') 293 | 294 | if not found_instance: 295 | sys.exit('ERROR: No AWS EC2 instances with the key_name ' + key_name + ' found.') 296 | 297 | 298 | def find_terraform_instances(): 299 | with open('terraform/terraform.tfvars', 'r') as file: 300 | terraformvars = file.read() 301 | 302 | pattern = 'key_name = \"([^\"]*)' 303 | a = re.search(pattern, terraformvars) 304 | 305 | client = boto3.client('ec2') 306 | response = client.describe_instances( 307 | Filters=[ 308 | { 309 | 'Name': "key-name", 310 | 'Values': [a.group(1)] 311 | } 312 | ] 313 | ) 314 | instances = [] 315 | for reservation in response['Reservations']: 316 | for instance in reservation['Instances']: 317 | str = instance['Tags'][0]['Value'] 318 | if str.startswith('attack-range'): 319 | instances.append(instance) 320 | 321 | return instances, a.group(1) 322 | 323 | 324 | def list_all_machines(mode): 325 | if mode == 'vagrant': 326 | print() 327 | print('Vagrant Status\n') 328 | v1 = vagrant.Vagrant('vagrant/', quiet_stdout=False) 329 | response = v1.status() 330 | print(tabulate(response, headers=['Name','Status','Provider'])) 331 | print() 332 | 333 | if mode == 'terraform': 334 | instances, key_name = find_terraform_instances() 335 | response = [] 336 | for instance in instances: 337 | response.append([instance['Tags'][0]['Value'], instance['State']['Name']]) 338 | print() 339 | print('Terraform Status\n') 340 | if len(response) > 0: 341 | print(tabulate(response, headers=['Name','Status'])) 342 | else: 343 | print("ERROR: Can't find configured EC2 Attack Range Instances in AWS.") 344 | sys.exit(1) 345 | print() 346 | 347 | 348 | if __name__ == "__main__": 349 | # grab arguments 350 | parser = argparse.ArgumentParser( 351 | description="starts a attack range ready to collect attack data into splunk") 352 | parser.add_argument("-m", "--mode", required=False, choices=['vagrant', 'terraform'], 353 | help="mode of operation, terraform/vagrant, please see configuration for each at: https://github.com/splunk/attack_range") 354 | parser.add_argument("-a", "--action", required=False, choices=['build', 'destroy', 'simulate', 'stop', 'resume'], 355 | help="action to take on the range, defaults to \"build\", build/destroy/simulate/stop/resume allowed") 356 | parser.add_argument("-t", "--target", required=False, 357 | help="target for attack simulation. For mode vagrant use name of the vbox. For mode terraform use the name of the aws EC2 name") 358 | parser.add_argument("-st", "--simulation_technique", required=False, type=str, default="", 359 | help="comma delimited list of MITRE ATT&CK technique ID to simulate in the attack_range, example: T1117, T1118, requires --simulation flag") 360 | parser.add_argument("-c", "--config", required=False, default="attack_range.conf", 361 | help="path to the configuration file of the attack range") 362 | parser.add_argument("-ls", "--list_machines", required=False, default=False, action="store_true", help="prints out all avaiable machines") 363 | parser.add_argument("-v", "--version", default=False, action="store_true", required=False, 364 | help="shows current attack_range version") 365 | 366 | # parse them 367 | args = parser.parse_args() 368 | ARG_VERSION = args.version 369 | mode = args.mode 370 | action = args.action 371 | target = args.target 372 | config = args.config 373 | simulation_techniques = [str(item) for item in args.simulation_technique.split(',')] 374 | list_machines = args.list_machines 375 | 376 | print(""" 377 | starting program loaded for B1 battle droid 378 | ||/__'`. 379 | |//()'-.: 380 | |-.|| 381 | |o(o) 382 | |||\\\ .==._ 383 | |||(o)==::' 384 | `|T "" 385 | () 386 | |\\ 387 | ||\\ 388 | ()() 389 | ||// 390 | |// 391 | .'=`=. 392 | """) 393 | 394 | # parse config 395 | attack_range_config = Path(config) 396 | if attack_range_config.is_file(): 397 | print("attack_range is using config at path {0}".format(attack_range_config)) 398 | configpath = str(attack_range_config) 399 | else: 400 | print("attack_range failed to find a config file at {0} or {1}..exiting".format(attack_range_config)) 401 | sys.exit(1) 402 | 403 | # Parse config 404 | parse = parseconfig.parser() 405 | settings = parse.load_conf(configpath) 406 | 407 | log = logger.setup_logging(settings['log_path'], settings['log_level']) 408 | log.info("INIT - attack_range v" + str(VERSION)) 409 | 410 | if ARG_VERSION: 411 | log.info("version: {0}".format(VERSION)) 412 | sys.exit(0) 413 | 414 | if not args.mode: 415 | log.info('ERROR: Specify Attack Range Mode with -m ') 416 | sys.exit(1) 417 | 418 | if args.mode and not action and not list_machines: 419 | log.info('ERROR: Use -a to perform an action or -ls to list avaiable machines') 420 | sys.exit(1) 421 | 422 | if args.mode and action == 'simulate' and not target: 423 | log.info('ERROR: Specify target for attack simulation') 424 | sys.exit(1) 425 | 426 | if list_machines: 427 | list_all_machines(mode) 428 | sys.exit(0) 429 | 430 | # lets give CLI priority over config file for pre-configured techniques 431 | if simulation_techniques[0] != '' or len(simulation_techniques) > 1: 432 | pass 433 | else: 434 | simulation_techniques = settings['simulation_technique'] 435 | 436 | 437 | # lets prep our config files base on provided settings 438 | prep_ansible(settings) 439 | 440 | if mode == "terraform": 441 | prep_terraform(settings) 442 | 443 | 444 | # to do: define which arguments are needed for build and which for simulate 445 | 446 | # lets process modes 447 | if mode == "vagrant": 448 | log.info("[mode] > vagrant") 449 | if action == "build" or action == "destroy" or action == "stop" or action == "resume": 450 | vagrant_mode(action, log) 451 | else: 452 | attack_simulation('vagrant', target, settings['simulation_engine'], simulation_techniques, log) 453 | 454 | elif mode == "terraform": 455 | log.info("[mode] > terraform ") 456 | if action == "build" or action == "destroy" or action == "stop" or action == "resume": 457 | terraform_mode(action, log) 458 | else: 459 | attack_simulation('terraform', target, settings['simulation_engine'], simulation_techniques, log) 460 | 461 | else: 462 | log.error("incorrect mode, please set flag --mode to \"terraform\" or \"vagrant\"") 463 | sys.exit(1) 464 | --------------------------------------------------------------------------------