Fork of nategraf/Naumachia with a modified cluster manager.
The ambition of Naumachia is to enable the deployment of multi-host interactive exploit challenges for fun and non-profit. The origonal inspiration was to enable network exploit challenges. The main target is providing fun and challenging exercises for CTFs and classrooms.
The inspiration for this project comes from my love of networking and especially network security. I wanted a platform to write and play challenges where everything was in-bounds including ARP spoofing, VLAN hopping (WIP), DNS poisoning, SNMP attacks as well as destructive attacks like dropping database tables and installing backdoors without interferring with other users. Naumachia is a system I came up with to do just that.
Naumachia provides:
- Orchestration of "arbitrary" networks and hosts for challenges
- Isolation of teams within dedicated challenge instances
- "Full" ethernet access to the challenge network
The quotes around "full" and "arbitrary" indicate that this is not completely true, due to limitations tracked in GitHub issues and which are ongoing areas of development.
Access to a Naumachia-hosted challenge is achieved through an OpenVPN tunnel created for that challenge. The user is autheticated by a certificate and key-pair downloaded from the CTF website (or other authenticated web frontend) and generated by the Naumachia registrar. Upon connection, the VPN tunnel will place the connection information in a Redis database, and the manager will then create a challenge instance for that user if one is not already alive. The manager will then create a network path for the user to the challenge and the user can start playing! When the user leaves for a while, their challenge instance will be torn down to free up resources. Data can be persisted on a per-instance basis allowing things such as modified database state, a persistant backdoor, or other progress to be saved between user sessions.
Challenges are specified through Docker Compose config files (docker-compose.yaml
). Additional providers including Vagrant, and GENI and currently in the works.
- Obtain a Linux server (tested on Ubuntu 16.04). This can be, for example, a VM from for favorite IaaS provider (e.g. AWS, GCP, Digital Ocean..... Azure)
- Install Docker and Docker Compose
- Clone Naumachia source from here (https://github.com/devplayer0/Naumachia.git)
- Install requirements.txt for Python3 (
pip3 install -r requirements.txt
)
- Write a
docker-compose.yaml
template and put it and any associated files in directory within thechallenges
directory. Check out the example challenge as a starting point. - Modify
config.yaml
to include your challenge. If you don't yet have a config.yaml, checkoutconfig.example.yaml
for guidance. - Run
configure.py
to generate thedocker-compose.yaml
file from a Jinja2 template, OpenVPN config files, and PKI.
WARNING: When writing the compose file, do not use bind volumes (i.e. mount local directories to the container). It will not mount properly when started from the cluster-manager which handles creating and stopping challenge instances. No workaround is provided as it is the eventual intention to move toward a scalable model when you cannot control (or care about) where your challenges are deployed. See moby/moby#28124 for technical discussion of the underlying reason
In order to log into the VPN tunnel and access Naumachia a client needs the correct configuration, and a registered certificate. These two are bundled in an OpenVPN client config file.
To generate a client config (with embedded certificates) for your challenge either:
- Use the registrar CLI
- Ex:
./registrar-cli mitm add alice
will create certs for Alice and./registrar-cli mitm get alice
with output the configuration needed for Alice to connect to the 'MITM' challenge
- Ex:
- Use the registrar server
- Add
registrar: {}
or a non-default registrar configration to theconfig.yaml
file. - Secure your server by ensuring it cannot be accessed by the public or enabling TLS client verification, which is described in
config.example.yaml
.- WARNING: If left unsecure, the registrar server can be used to issue a trivial DoS attack or worse against your Naumachia installation.
- Issue REST API calls to registrar server to manage certificates and retrieve configuration files
/<chal>/list?cn=<cn>
(cn optional) : List all registered certificates or certificates for a specific cn/<chal>/add?cn=<cn>
: Create a new certificate with the specified common name (cn)/<chal>/revoke?cn=<cn>
: Revoke the certificate with the specified common name (cn)/<chal>/remove?cn=<cn>
: Remove the certificate with the specified common name (cn)/<chal>/get?cn=<cn>
: Get the OpenVPN configuration file for the user with specified common name (cn)
- Add
To run Naumachia simply bring up the environment with the Docker Compose CLI (e.g. docker-compose up
)
For lack of a better method there are two steps that will need to be completed on initial installation and every time Naumachia will be run after reboot. It is my intention to eliminate the need for these steps as development continues.
- Disable bridge-nf enforcement of iptables rules by running
disable-bridge-nf-iptables.sh
. This is needed to allow unrestricted access within the sandbox network Naumachia creates for each user. By default, Docker blocks certain traffic from connections into a Docker configured bridge which were not configured through Docker Networks. This does not effect layer 3 restrictions imposed by iptables - Run an arbitrary docker container on the host network (e.g.
docker run --rm --net=host alpine /bin/true
) This create a link in the/var/run/docker/netns
folder calleddefault
which allows access to the host network namespace. This will be added to the cluster-manager container at runtime to allow it to modify the bridges generated by Docker on the host.
Challenges in Naumachia are defined by a docker-compose.yaml
file and the resources it launches
Consider the example provided as example/docker-compose.yml
For examples of problems deployed in past CTFs go to the Naumachia-challenges repo
version: '3.7'
# The file defines the configuration for simple Nauachia challenge
# where a successful man-in-the-middle (MTIM) attack
# (such as ARP poisoning) provides a solution
# If you are unfamiliar with docker-compose this might be helpful:
# * https://docs.docker.com/compose/
# * https://docs.docker.com/compose/compose-file/
#
# But the gist is that the services block below specifies two containers,
# which act as parties in a vulnerable communication
services:
bob:
build: ./bob
image: naumachia/example.bob
environment:
- CTF_FLAG=fOOBaR
alice:
build: ./alice
image: naumachia/example/alice
depends_on:
- bob
environment:
- CTF_FLAG=fOOBaR
# To avoid users from using this challenge as a personal VPN
# gateway to the internet, it is important to specify the
# default network as internal (i.e. not connected to the internet)
networks:
default:
internal: true
This example defines a challenge which will feature two containers networked together through the default network, which has been modified to be inaccessible from the external world (as should be down for all challenges unless you have a good reason not to)
The code defining Alice's behavior is in the folder ./alice where you will find a Dockerfile defining the containers properties, and a python script which will be run as defined in the Dockerfile (This python script send a message to Bob "asking" if she has the right flag repeatedly)
Similarly Bob's definition is in ./bob which is a simple server listening for the flag Alice sends and responding yes or no to the correctness of the flag.
The user will log in to the VPN tunnel with a config provided by the registrar, and execute an attack to intercept the traffic and obtain the flag
Clients can use any OS supported by OpenVPN, although Linux is recommended for it's large number of hacking tools
To connect each user will need to:
- Install OpenVPN
- Can be found on most package managers (e.g. apt, pacman, brew, choco) or downloaded
- Ensure the TAP driver is installed
- Obtain a configuration file with certificates for the challenge they want to connect from the host
- Launch openvpn with the correct configuration
- CLI:
openvpn --config
- Windows GUI: Place the config file in
%HOMEPATH%\OpenVPN\config
and right-click the VPN icon on the status bar, then select the config you want
If using the CLI on Linux, or MacOS you may still need to more steps 4. Bring up the new TAP network interface
- Ex:
ip link set tap0 up
- Obtain an IP address by DHCP (if DHCP is enabled for the challenge)
- Ex:
dhcpcd tap0
- Ex:
udhcpc -i tap0
- Ex:
dhclient tap0