A Feedback-driven GUI master / actuator orchestration framework for the OpenC2 language, written in Python
This project is proof of concept code to show how OpenC2 can be deployed on geographically disparate networks. Please report bugs via git issues, pull requests are welcome.
This project is built on top of OrchID's code base:
OrchID is an OpenC2 proxy built in Django 1.10.2. OrchID aims to provide a simple, modular API to begin accepting OpenC2 commands and converting them into Python actions.
OpenC2 OrchID was built by Adam Bradbury (Zepko Architect), so is used extensively in Zepko's response architecture. This document explains the usage for the onboarded profiles for this version of OrchID, for general documentation on how OrchID functions you should refer to the official repository.
This codebase provides a modified version of OrchID that can be administrated by non-technical staff. It allows the end user to link profile code, to OpenC2 commands and actuators, and handles credential storage.
The relay is called by an upstream Orchestrator (See ReactorMaster), the idea is, that an MSSP has multiple sites and clients, with different capabilities and network layouts, buy allowing engineers to create a topology of "Relays" commands can be routed to multiple sites from a central server, without the need for that central server to connect into each actuator directly. (e.g. Remoting in as root to a webserver from the internet).
Relays provide a way for us to define specific use cases and actuators per client, and provide a secure ip-locked TLS channel to execute those actions.
```shell
yum install -y git wget python-pip python-devel gcc mariadb mariadb-server mariadb-devel MySQL-python libffi-devel
```
systemctl status mariadb.service
systemctl start mariadb.service
systemctl enable mariadb.service
mysql_secure_installation
NOTE: RUNNING ALL PARTS OF THIS SCRIPT IS RECOMMENDED FOR ALL MariaDB
SERVERS IN PRODUCTION USE! PLEASE READ EACH STEP CAREFULLY!
In order to log into MariaDB to secure it, we'll need the current
password for the root user. If you've just installed MariaDB, and
you haven't set the root password yet, the password will be blank,
so you should just press enter here.
Enter current password for root (enter for none):
Press enter for first time installs
Change the root password? [Y/n]
It's recommended that you set a strong password for the root account By default the password for Reactor is
correcthorsebatterystaple
Remove anonymous users? [Y/n]
It is recommended that all anonymous remote logins be disabled
Disallow root login remotely? [Y/n]
It is recommended that the root account only login from
localhost
Remove test database and access to it? [Y/n]
It is recommended that the test database is removed for security
Reload privilege tables now? [Y/n]
Choose Y to apply the new settings
Cleaning up...
All done! If you've completed all of the above steps, your MariaDB
installation should now be secure.
Thanks for using MariaDB!
Either create port rules for the necessary ports required by Reactor, or disable the firewall altogether (not recommended)
systemctl stop firewall-cmd
systemctl disable firewall-cmd
firewall-cmd --state
running
systemctl status firewall-cmd
systemctl start firewall-cmd
systemctl enable firewall-cmd
firewall-cmd --add-port=8000/tcp --zone=public --permanent # ReactorRelay
firewall-cmd --reload
git clone https://User:Token@github.com/User/ReactorRelay.git
OR...
git clone https://github.com/User/ReactorRelay.git
Enter username and password...
Familiarise yourself with the code base. If you're familiar with Django projects then this will be very familiar.
cd ReactorRelay && ls
LICENSE main manage.py reactor_relay README.md requirements.txt samples static
pip install --upgrade pip
pip install virtualenv
If you are testing both ReactorRelay and ReactorMaster on the same system, you can use one virtual environment for both
virtualenv env/ -p python --prompt="[ReactorRelay]"
source env/bin/activate
deactivate
pip install -r requirements.txt
For database migrations, you may need to first create the schema specified on line 90 in
main/settings.py
mysql -uroot -p # provide password when prompted
MariaDB [(none)]> show schemas;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
+--------------------+
3 rows in set (0.00 sec)
create schema reactor_relay;
Query OK, 1 row affected (0.00 sec)
MariaDB [(none)]> show schemas;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| reactor_relay |
+--------------------+
4 rows in set (0.00 sec)
exit
Bye
python manage.py migrate # configures database according to models and previous migrations
Operations to perform:
Apply all migrations: admin, auth, contenttypes, reactor_relay, sessions
Running migrations:
Applying contenttypes.0001_initial... OK
Applying auth.0001_initial... OK
Applying admin.0001_initial... OK
Applying admin.0002_logentry_remove_auto_add... OK
Applying contenttypes.0002_remove_content_type_name... OK
Applying auth.0002_alter_permission_name_max_length... OK
Applying auth.0003_alter_user_email_max_length... OK
Applying auth.0004_alter_user_username_opts... OK
Applying auth.0005_alter_user_last_login_null... OK
Applying auth.0006_require_contenttypes_0002... OK
Applying auth.0007_alter_validators_add_error_messages... OK
Applying auth.0008_alter_user_username_max_length... OK
Applying reactor_relay.0001_initial... OK
Applying sessions.0001_initial... OK
python manage.py loaddata reactor_relay/fixtures/initial_data.json
python manage.py createsuperuser
python manage.py runserver 0.0.0.0:8000 # relay
Now check that you can visit it in the browser, and login as the super-user you created.
The relay's web interface is accessible on:
http://<ip_addr>:8000/
It's OpenC2 API is accessible on:
http://<ip_addr>:8000/openc2/
It is recommended you put this behind an SSL reverse proxy such as NGINX as commands can contain sensitive information, and connections to this box should be IP locked to known and trusted upstream orchestrators.
ReactorRelay - :8000
The first step is to define the actuators you need this relay to control. Credentials can be specified if you need them in your code profiles. (Example: SSH login credentials)
Some example profiles are found in ./reactor_relay/profiles
- these are the code that translates OpenC2 code into vendor commands specific to your estate.
This relay has three really simple profiles to get you started, if you are running this code on a linux machine, they should all work:
This uses a local ping executable to ping a target address. action:SCAN,actuator:process-network-scanner,target:cybox:Address
This connects to a remote linux machine via SSH and executes an iptables command to drop an IP address, the revoke code is also in this profile aswell. action:DENY/ALLOW,actuator:network-ips,target:cybox:Address
This uses a local whois executable to perform a whois query for an IP. action:QUERY,actuator:process,target:cybox:Address
Capabilities are what the relay will disclose to the upstream orchestrator. Capabilities link an Acutuator and code profile, and specify what type of target it requires to execute e.g: Cybox:NetworkConnection
Once this is done, you must configure the Master and sync each relay's capabilities.
Follow the documentation for ReactorMaster until you are ready to send jobs.
The relay shows the details for jobs it has received from its master along with their status. Once a job is complete, the relay will send the outcome back to the master.
If the master does not appear to be receiving responses for jobs it has requested, check the relays themselves to determine whether the jobs are succeeding locally or not.
Adam Bradbury
┌────────┐ ┌───────┐ ┌──────────┐
| Master ├─ manages a ─→| Relay ├─ has an ──→| Actuator |
└─┬────┬─┘ └───────┘ └────┬─────┘
| | |
| └──── defines can use
| | |
specifies ↓ ↓
| ┌─────┐ ┌────────────┐
| | Job |←───────── used by ────┤ Capability │
| └──┬──┘ └────────────┘
↓ |
┌────────┐ targets
│ Target |←───────┘
└────────┘
.
├── LICENSE
├── README.md
├── main
│ ├── __init__.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
├── manage.py
├── reactor_relay
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── decorators.py
│ ├── fixtures
│ │ └── initial_data.json
│ ├── forms.py
│ ├── migrations
│ │ ├── 0001_initial.py
│ │ └── __init__.py
│ ├── models.py
│ ├── profiles
│ │ ├── __init__.py
│ │ ├── address_drop_ips.py
│ │ ├── address_ping.py
│ │ ├── email_send_office365_email.py
│ │ ├── response.py
│ │ └── uri_virustotal_lookup.py
│ ├── response.py
│ ├── templates
│ │ └── reactor_relay
│ ├── tests.py
│ ├── validators.py
│ └── views.py
├── requirements.txt
├── samples
│ └── response_ack.json
└── static
└── theme
├── css
├── font-awesome
├── fonts
└── js