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 code base provides a way to administrate multiple ReactorRelay deployments. It provides an OpenC2 API to send commands to downstream relays, as well as a way for analyst to manually send commands to capable actuators deployed on client's sites that wouldn't be accessible directly from the internet.
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!
Reactor Master uses port
9000
by default - set byOPENC2_RESPONSE_URL
- which can be changed inmain/settings.py
35 # OpenC2 Response URL
36 OPENC2_RESPONSE_URL = 'http://0.0.0.0:9000/openc2/'
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=9000/tcp --zone=public --permanent # ReactorMaster
firewall-cmd --reload
echo "*/1 * * * * root /usr/bin/wget --spider -q http://:9000/cron/launch/ > /dev/null" >> /etc/crontab
git clone https://User:Token@github.com/User/ReactorMaster.git
OR...
git clone https://github.com/User/ReactorMaster.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 ReactorMaster && ls
LICENSE main manage.py reactor_master 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="[ReactorMaster]"
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_master;
Query OK, 1 row affected (0.00 sec)
MariaDB [(none)]> show schemas;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| reactor_master |
+--------------------+
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_master, 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_master.0001_initial... OK
Applying sessions.0001_initial... OK
python manage.py loaddata reactor_master/fixtures/initial_data.json
python manage.py createsuperuser
python manage.py runserver 0.0.0.0:9000 # master
Performing system checks...
2017-07-10 20:40:42,252 INFO Registered response name with signature {'action': 'response', 'target': {'type': 'openc2:Data'}}
2017-07-10 20:40:42,410 INFO Initialising master
2017-07-10 20:40:42,410 INFO Loading profile response.py
2017-07-10 20:40:42,411 INFO Registered response name with signature {'action': 'response', 'target': {'type': 'openc2:Data'}}
System check identified no issues (0 silenced).
July 10, 2017 - 20:40:42
Django version 1.10.2, using settings 'main.settings'
Starting development server at http://0.0.0.0:9000/
Quit the server with CONTROL-C.
Now check that you can visit it in the browser, and login as the super-user you created.
The master's web interface is accessible on:
http://<ip_addr>:9000/
It's OpenC2 API is accessible on:
http://<ip_addr>:9000/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.
ReactorMaster - :9000
Follow the documentation for ReactorRelay for each relay being configured, and then return here to link them to the master and synchronise their capabilities.
With the relay(s) created, the first step is to link with the master - This can be done by clicking Create New Relay from the main dashboard view. The URL specified should be the OpenC2 API (usually /openc2/
). The username and password should be the password you generated when running createsuperuser
on the downstream relay.
Once your relay is configured, click Sync Capabilities, this will request a list of all configured capabilities from all downstream relays. This then provides the list of actions that can be taken from the central orchestrator. If the error Sync Failed occurs, ensure that the url have specified is the fully qualified OpenC2 API url e.g. http://10.20.30.40:8000/openc2/
- Note the trailing slash. Make sure this is accessible from the Orchestrator.
If syncing still fails, this could be because you have entered incorrect credentials for the relay, which will require you to delete the relay in the Live Relay section and re-create it with the correct credentials.
Targets are a standardised way to express variables to pass to profiles, for example the IP of an attacker you wish to block. In Reactor we are still using CybOX 2.1, however the codebase is expandable to take any kind of JSON object.
This allows the user to create a job, linking a capability with a target. Once actioned - it will be picked up by the /cron/launcher/
view within 60 seconds (ensure you have created the cron job for the master). Responses, errors and job status can then be tracked by clicking on the job in the GUI.
Job progress can be tracked and the status will transition from Sent
to Pending
to Success
, or Failed
if an error occurred.
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_master
│ ├── __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
│ │ └── response.py
│ ├── response.py
│ ├── templates
│ │ └── reactor_master
│ ├── templatetags
│ │ ├── __init__.py
│ │ └── tags.py
│ ├── tests.py
│ ├── validators.py
│ └── views.py
├── requirements.txt
├── samples
│ └── response_ack.json
└── static
└── theme
├── css
├── font-awesome
├── fonts
└── js