Multi Container-based CTF challenges

Deze pagina is nog onvolledig. Start with the single container challenges workflow. Voor de bijbehorende GitLab repo kijk hier.

Container challenges on this platform have some criteria: - build in a docker-compose.yaml file. - Exists of linux x86 compatible container(s). - Containers do not use volumes, instead use copy, git, wget or curl.

Example multi-container docker-compose.yaml

The docker-compose below exists of two containers. The first one is a FTP server, which has SSH and FTP exposed but are not accessible from outside. Therefore the second container is used as bastion host to gain access to the local network via a SSH connection.

version: '3.3'

services:
   vsftpd:
     image: registry.gitlab.com/hu-hc/jcr/challenges/ftp:latest
     ports:
       - 21:21
       - 22:22
   bastion:
     image: registry.gitlab.com/hu-hc/jcr/challenges/minikali:latest
     ports:
       - 22:22
     labels:
       kompose.service.type: nodeport

Containers available in Container Registry

Before creating a multi-container challenge docker-compose.yaml file it is important that the container images you want to use in this challenge are created and pushed to a container registry. If you want to know how to do this follow the steps until "Push the container to the registry" in the container challenge workflow

Networking with a multi-container challenge

In a multi-container challenge it is possible to have some of the containers available from the internet and others only from other containers within the same challenge.

Communication between containers

The following code snippets from a 'docker-compose.yaml' explains how to expose one or more ports internally between multiple containers within the same challenge. If you want to expose a port range between containers check the following documentation from docker.

...
services:  
  vsftpd: 
    ports:
      - 21:21
      - 22:22
  bastion:
    ports:
      - 22:22
...

Now you can ssh from container bastion to container vsftpd with the following command, notice that the name of the service is also the dns address the container is reachable at from other containers within the challenge.

ssh exampleuser@vsftpd

Communication to the outside

If you want a container within your multi-container challenge which must be reachable from the outside you can add the label kompose.service.type: nodeport. This label exposes the port(s) defined in the "ports" block to the outside in the range 30000-32767.

In the docker-compose.yaml code snippet below you can see the label is added below the "ports" block. This ensures that port 22 is assigned to a random port in the range above which is accessible from the outside, later more on how to find this random port.

...
services:  
  ...
  bastion:
    ports:
      - 22:22
    labels:
      kompose.service.type: nodeport
...

Deploying a multi-container challenge

Before adding your challenge to your local or public CTFd it is important to test your docker-compose.yaml file. To do this you can use the same steps that are used for a single-container challenge to test your docker-compose. Follow "Test the docker-compose file" and "run in your k8s cluster" in the single container challenge workflow. Keep in mind that you need your own kompose created deployment and service file names.

After testing you can setup the challenge in your local or public CTFd instance, therefore you can follow the same steps as for a single container challenge workflow.