Attack scenario orchestrator for Cryton
Reason this release was yanked:
New versioning
Project description
[[TOC]]
Cryton Worker
Description
Cryton Worker is used for executing attack modules remotely. It utilizes RabbitMQ as its asynchronous remote procedures call protocol. It connects to the Rabbit MQ server and consumes messages from the Core component or any other app that implements its RabbitMQ API.
To be able to execute attack scenarios, you also need to install Cryton Core (or your custom tool that implements Worker's API). Modules provided by Cryton can be found here.
Cryton toolset is tested and targeted primarily on Debian and Kali Linux. Please keep in mind that only the latest version is supported and issues regarding different OS or distributions may not be resolved.
Settings
Cryton Worker uses environment variables for its settings. Please update them to your needs.
name | value | example | description |
---|---|---|---|
CRYTON_WORKER_NAME | string | my_worker1 | Unique name used to identify the Worker. |
CRYTON_WORKER_MODULES_DIR | string | /path/to/cryton-modules/modules/ | Path to the directory containing the modules. |
CRYTON_WORKER_DEBUG | boolean | false | Make Worker run with debug output. |
CRYTON_WORKER_INSTALL_REQUIREMENTS | boolean | true | Install requirements.txt for each module on startup. |
CRYTON_WORKER_CONSUMER_COUNT | int | 7 | Number of consumers used for Rabbit communication (more equals faster request processing and heavier processor usage). |
CRYTON_WORKER_PROCESSOR_COUNT | int | 7 | Number of processors used for internal requests (more equals faster internal requests processing, but heavier processor usage). |
CRYTON_WORKER_MAX_RETRIES | int | 3 | How many times to try to re-connect when the connection is lost. |
CRYTON_WORKER_MSFRPCD_HOST | str | localhost | Metasploit Framework RPC host. |
CRYTON_WORKER_MSFRPCD_PORT | int | 55553 | Metasploit Framework RPC port. |
CRYTON_WORKER_MSFRPCD_SSL | boolean | true | Use SSL to connect to Metasploit Framework RPC. |
CRYTON_WORKER_MSFRPCD_USERNAME | string | msf | Username for Metasploit Framework RPC login. |
CRYTON_WORKER_MSFRPCD_PASSWORD | string | toor | Password for Metasploit Framework RPC login. |
CRYTON_WORKER_RABBIT_HOST | string | 127.0.0.1 | RabbitMQ server host. |
CRYTON_WORKER_RABBIT_PORT | int | 5672 | RabbitMQ server port. |
CRYTON_WORKER_RABBIT_USERNAME | string | admin | Username for RabbitMQ server login. |
CRYTON_WORKER_RABBIT_PASSWORD | string | mypass | Password for RabbitMQ server login. |
CRYTON_WORKER_EMPIRE_HOST | string | 127.0.0.1 | Empire server host. |
CRYTON_WORKER_EMPIRE_PORT | int | 1337 | Empire server port. |
CRYTON_WORKER_EMPIRE_USERNAME | string | empireadmin | Username for Empire server login. |
CRYTON_WORKER_EMPIRE_PASSWORD | string | password123 | Password for Empire server login. |
CRYTON_WORKER_APP_DIRECTORY | string | ~/.local/cryton-worker/ | Path to the Cryton Worker directory. (do not change/set/export, if you don't know what you're doing) If changed, update the commands in this guide accordingly. |
To save the settings create an app directory:
mkdir ~/.local/cryton-worker/
The directory will be also used to store logs and other data created by Cryton Worker.
This doesn't apply to the Docker installation. It will be available in the same directory as the Dockerfile
(/path/to/cryton-worker/cryton-worker
).
Next, we download example settings (change the version to match the app version - versions can be found here):
curl -o ~/.local/cryton-worker/.env https://gitlab.ics.muni.cz/cryton/cryton-worker/-/raw/<version>/.env
Update these settings to your needs.
Overriding the settings
NOTICE: This doesn't apply to the Docker Compose installation.
To override the persistent settings, you can set/export the variables yourself using the export command (use unset to remove the variable). For example:
export CRYTON_WORKER_NAME=my_worker1
Some environment variables can be overridden in CLI. Try using cryton-worker --help
.
Setting up modules
To be able to execute (validate) attack modules you must download them into one directory. Then update
CRYTON_WORKER_MODULES_DIR
environment variable to point to the correct location. If you're using the provided modules
from the modules' repository, then the variable
will look similar to this CRYTON_WORKER_MODULES_DIR=/path/to/cryton-modules/modules/
.
Modules are hot-swappable, which means the modules don't have to be present at startup. This is especially useful for development but not recommended for production.
Modules directory example:
tree $CRYTON_WORKER_MODULES_DIR
CRYTON_WORKER_MODULES_DIR/
├── mod_hydra
│ └── mod.py
└── mod_cmd
└── mod.py
Prerequisites
Worker can run without these prerequisites. However, they are highly recommended since they allow Worker to use all of its functionality.
- Metasploit Framework allows using Metasploit sessions and MSF listeners.
- Empire post-exploitation framework allows deployment and interaction with Empire agents.
Additionally, to start the MSF as a service follow this guide or simply use:
msfrpcd -U <CRYTON_WORKER_MSFRPCD_USERNAME> -P <CRYTON_WORKER_MSFRPCD_PASSWORD>
Installation (using pip/pipx)
Cryton Worker is available in the PyPI and can be installed using pip (pip install --user cryton-worker
).
However, we highly recommend installing the app in an isolated environment using pipx.
Requirements
Install the following requirements:
Installing with pipx
Once you have pipx ready on your system, you can start the installation:
pipx install cryton-worker
Make sure you've correctly set the settings.
Optionally, you can set up shell completion.
Everything should be set. Check out the usage section.
Installation (using Docker Compose)
Cryton Worker can be installed using Docker Compose.
To allow the Worker to start listeners, the container has raw access to the host’s network interface.
This guide won't describe how to install or mount the tools/applications used by the (attack) modules. More information can be found in the Docker documentation.
Requirements
Add yourself to the group docker, so you can work with Docker CLI without sudo:
sudo groupadd docker
sudo usermod -aG docker $USER
newgrp docker
docker run hello-world
Installing and running with Docker Compose
First, we have to clone the repo and switch to the correct version.
git clone https://gitlab.ics.muni.cz/cryton/cryton-worker.git
cd cryton-worker
git checkout <version>
Make sure you've correctly set the settings. You can't change the settings on a running container.
Finally, copy your settings:
cp ~/.local/cryton-worker/.env .env
We are now ready to build and start the Worker:
docker compose up -d --build
After a while you should see a similar output:
[+] Running 1/1
⠿ Container cryton_worker Started
Everything should be set. Check if the installation was successful and the Worker is running:
docker compose logs
You should see [*] Waiting for messages.
in the output.
Docker can sometimes create dangling (<none>:<none>
) images which can result in high disk space usage. You can remove them using:
docker image prune
Development
To install Cryton Worker for development, you must install Poetry.
Clone the repository:
git clone https://gitlab.ics.muni.cz/cryton/cryton-worker.git
Then go to the correct directory and install the project:
cd cryton-worker
poetry install
To spawn a shell use:
poetry shell
Make sure you've correctly set the settings.
To override the settings quickly, you can use this handy one-liner:
export $(grep -v '^#' .env | xargs)
Optionally, you can set up shell completion
Everything should be set, check out the usage section.
Usage
NOTICE: If you're using Docker Compose to install the app, you can skip this section.
Use the following to invoke the app:
cryton-worker
You should see a help page:
Usage: cryton-worker [OPTIONS] COMMAND [ARGS]...
Cryton Worker CLI.
Options:
...
To learn about each command's options use:
cryton-worker <your command> --help
To start Worker use cryton-worker start
and you should see something like:
Starting Worker <Worker name>..
To exit press CTRL+C
Connection does not exist. Retrying..
Connection to RabbitMQ server established.
[*] Waiting for messages.
Executing modules
To be able to execute a module (Python script), it must have the following structure and IO arguments.
Modules' structure
- Each module must have its own directory with its name.
- Script (module) must be called
mod.py
. - Module must contain an
execute
function that takes a dictionary and returns a dictionary. It's an entry point for executing it. - Module should contain a
validate
function that takes a dictionary, validates it, and returns 0 if it's okay, else raises an exception.
Path example:
/CRYTON_WORKER_MODULES_DIR/my-module-name/mod.py
Where:
- CRYTON_WORKER_MODULES_DIR has to be the same path as is defined in the CRYTON_WORKER_MODULES_DIR variable.
- my-module-name is the directory containing your module.
- mod.py is the module file.
Module (mod.py
) example:
def validate(arguments: dict) -> int:
if arguments != {}:
return 0 # If arguments are valid.
raise Exception("No arguments") # If arguments aren't valid.
def execute(arguments: dict) -> dict:
# Do stuff.
return {"return_code": 0, "serialized_output": ["x", "y"]}
Input parameters
Every module has its own input parameters. These input parameters are given as a dictionary to the
module execute
(when executing the module) or validate
(when validating the module parameters) function.
Output parameters
Every attack module (its execute
function) returns a dictionary with the following keys:
Parameter name | Parameter meaning |
---|---|
return_code |
Numeric representation of result (0, -1, -2). 0 (OK) means the module finished successfully. -1 (FAIL) means the module finished unsuccessfully. -2 (ERROR) means the module finished with an unhandled error. |
serialized_output |
Parsed output of the module. Eg. for a bruteforce module, this might be a list of found usernames and passwords. |
output |
Raw output of the module |
Prebuilt functionality for modules
Worker provides prebuilt functionality to make building modules easier. Import it using:
from cryton_worker.lib.util import module_util
It gives you access to:
Metasploit
Wrapper for MsfRpcClient from pymetasploit3. Examples:
# Check if the connection to msfrpcd is OK before doing anything.
from cryton_worker.lib.util.module_util import Metasploit
msf = Metasploit()
if msf.is_connected():
msf.do_stuff()
from cryton_worker.lib.util.module_util import Metasploit
search_criteria = {"via_exploit": "my/exploit"}
found_sessions = Metasploit().get_sessions(**search_criteria)
from cryton_worker.lib.util.module_util import Metasploit
output = Metasploit().execute_in_session("my_command", "session_id")
from cryton_worker.lib.util.module_util import Metasploit
options = {"exploit_arguments": {}, "payload_arguments": {}}
Metasploit().execute_exploit("my_exploit", "my_payload", **options)
from cryton_worker.lib.util.module_util import Metasploit
token = Metasploit().client.add_perm_token()
from cryton_worker.lib.util.module_util import Metasploit
output = Metasploit().get_parameter_from_session("session_id", "my_param")
get_file_binary
Function to get a file as binary.
Example:
from cryton_worker.lib.util.module_util import get_file_binary
my_file_content = get_file_binary("/path/to/my/file")
File
Class used with schema for validation if file exists.
Example:
from schema import Schema
from cryton_worker.lib.util.module_util import File
schema = Schema(File(str))
schema.validate("/path/to/file")
Dir
Class used with schema for validation if directory exists.
Example:
from schema import Schema
from cryton_worker.lib.util.module_util import Dir
schema = Schema(Dir(str))
schema.validate("/path/to/directory")
Rabbit API
Worker is able to process any request sent through RabbitMQ to its Queues (cryton_worker.WORKER_NAME.attack.request
,
cryton_worker.WORKER_NAME.control.request
, cryton_worker.WORKER_NAME.agent.request
)
defined using WORKER_NAME (can be changed using CLI or in the settings).
The response is sent to the queue defined using the reply_to
parameter in a message.properties.
Attack requests
Requests to execute a command or a module are being processed in the cryton_worker.WORKER_NAME.attack.request
queue.
List of supported requests:
Execute attack module
To execute an attack module, send a message to cryton_worker.WORKER_NAME.attack.request
queue in a format
{"ack_queue": "confirmation_queue", "step_type": "worker/execute", "module": module_name, "module_arguments": module_arguments}
ACK response format:
{"return_code": 0, "correlation_id": "id"}
Response format:
{"return_code": 0, "output": "", "serialized_output": ""}
Execute command on agent
To execute a command on a deployed agent, send a message to the cryton_worker.WORKER_NAME.attack.request
queue in a format
{"step_type": "empire/execute", "arguments": {"shell_command": "whoami", "use_agent": "MyAgent"}}
ACK response format:
{"return_code": 0, "correlation_id": "id"}
Response format:
{"return_code": 0, "output": "", "serialized_output": ""}
Execute empire module on agent
To execute an empire module on a deployed agent, send a message to the cryton_worker.WORKER_NAME.attack.request
queue in a format
{"step_type": "empire/execute", "arguments": { "empire_module": "python/collection/linux/pillage_user", "use_agent": "MyAgent"}}
ACK response format:
{"return_code": 0, "correlation_id": "id"}
Response format:
{"return_code": 0, "output": "", "serialized_output": ""}
Agent requests
Requests to control empire agents are being processed in cryton_worker.WORKER_NAME.agent.request
queue.
List of supported requests:
Deploy agent
Deploy an agent and send a response containing the result.
Example:
{"step_type": "empire/agent-deploy", "arguments": {"stager_type": "multi/bash", "agent_name": "MyAgent", "listener_name": "TestListener", "listener_port": 80, "session_id": "MSF_SESSION_ID"}}
Response example:
{"return_code": 0, "output": "Agent 'MyAgent' deployed on target 192.168.33.12."}
Control requests
To perform a control event send a message to cryton_worker.WORKER_NAME.control.request
queue in a format
{"event_t": type, "event_v": value}
Response format:
{"event_t": type, "event_v": value}
List of supported requests:
Validate module
Validate a module and send a response containing the result.
Example:
{"event_t": "VALIDATE_MODULE", "event_v": {"module": module_name, "module_arguments": module_arguments}}
Response example:
{"event_t": "VALIDATE_MODULE", "event_v": {"return_code": 0, "output": "output"}}
List modules
List available modules and send a response containing the result.
Request example:
{"event_t": "LIST_MODULES", "event_v": {}}
Response example:
{"event_t": "LIST_MODULES", "event_v": {"module_list": ["module_name"]}}
List sessions
List available Metasploit sessions and send a response containing the result.
Request example:
{"event_t": "LIST_SESSIONS", "event_v": {"target_host": target_ip}}
Response example:
{"event_t": "LIST_SESSIONS", "event_v": {"session_list": ["session_id"]}}
Kill Step execution
Kill running Step (module) and send a response containing the result.
Example:
{"event_t": "KILL_STEP_EXECUTION", "event_v": {"correlation_id": correlation_id}}
Response example:
{"event_t": "KILL_STEP_EXECUTION", "event_v": {"return_code": -2, "output": "exception"}}
Health check
Check if Worker is alive and send a response containing the result.
Example:
{"event_t": "HEALTH_CHECK", "event_v": {}}
Response example:
{"event_t": "HEALTH_CHECK", "event_v": {"return_code": 0}}
Add trigger for HTTPListener
Add trigger with parameters and start listener with host
and port
if it doesn't already exists, send a response containing the result afterwards.
Request example:
{"event_t": "ADD_TRIGGER", "event_v": {"host": host, "port": port, "listener_type": "HTTP", "reply_to": reply_to_queue,
"routes": [{"path": path, "method": method, "parameters": [{"name": name, "value": value}]}]}}
Response example:
{"event_t": "ADD_TRIGGER", "event_v": {"return_code": 0, "trigger_id": "123"}}
Remove trigger for HTTPListener
Remove trigger, optionally stop the HTTPListener if there are no triggers left and send a response containing the result.
Request example:
{"event_t": "REMOVE_TRIGGER", "event_v": {"trigger_id": "123"}}
Add trigger for MSFListener
Add trigger with session identifiers and start MSFListener.
Request example:
{"event_t": "ADD_TRIGGER", "event_v": {"listener_type": "MSF", "reply_to": "cryton_core.control.response", "identifiers": {"via_exploit": "auxiliary/scanner/ssh/ssh_login"}}}
Response example:
{"event_t": "ADD_TRIGGER", "event_v": {"return_code": 0, "trigger_id": "123"}}
Remove trigger for MSFListener
This will stop the MSFListener because it can't have multiple triggers.
Request example:
{"event_t": "REMOVE_TRIGGER", "event_v": {"trigger_id": "123"}}
Response example:
{"event_t": "REMOVE_TRIGGER", "event_v": {"return_code": -2, "output": "exception"}}
List triggers
List available triggers and send a response containing the result.
Example:
{"event_t": "LIST_TRIGGERS", "event_v": {}}
Response example:
{"event_t": "LIST_TRIGGERS", "event_v": {"trigger_list": [{"id": "123", "trigger_param": "trigger_param_value", ...}]}}
Trigger Stage (Response only)
Sent when a trigger is activated.
Response example:
{"event_t": "TRIGGER_STAGE", "event_v": {"stage_execution_id": stage_execution_id}}
Shell completion
Shell completion is available for the Bash, Zsh, and Fish shell and has to be manually enabled (the tool must be installed first).
Bash
First, create an app directory (if you haven't already):
mkdir ~/.local/cryton-worker/
Generate and save the completion script:
_CRYTON_WORKER_COMPLETE=bash_source cryton-worker > ~/.local/cryton-worker/cryton-worker-complete.bash
Source the file in the ~/.bashrc
file:
echo ". ~/.local/cryton-worker/cryton-worker-complete.bash" >> ~/.bashrc
You may need to restart your shell for the changes to take effect.
Zsh
First, create an app directory (if you haven't already):
mkdir ~/.local/cryton-worker/
Generate and save the completion script:
_CRYTON_WORKER_COMPLETE=zsh_source cryton-worker > ~/.local/cryton-worker/cryton-worker-complete.zsh
Source the file in the ~/.zshrc
file:
echo ". ~/.local/cryton-worker/cryton-worker-complete.zsh" >> ~/.zshrc
You may need to restart your shell for the changes to take effect.
Fish
Generate and save the completion script:
_CRYTON_WORKER_COMPLETE=fish_source cryton-worker > ~/.config/fish/completions/cryton-worker-complete.fish
You may need to restart your shell for the changes to take effect.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Hashes for cryton_worker-2022.2.2-py3-none-any.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | bce941a6b5d08dc3462ec803b1f86999002a32c548376a952a132e85cbde3d8e |
|
MD5 | c30a411feee3020a0ae91dc8ce322f31 |
|
BLAKE2b-256 | 9d634e3a28146228460aa9d0d14546199d32fb806e271d115855c6e1707fd5a3 |