about summary refs log tree commit diff
path: root/README.md
blob: 61b41ac728189bf6656c43043dad0eb346c20bf1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# circus-companion

The companion ~cube~ container spawned specifically for one user.

## Purpose

- Validator for flags
- Temporary secret vault for the user
- control endpoint of challenge containers for the user

## Usage

This executable needs some parameters to work properly:

| Key | Required? | Description |
|---|---|---|
| `-port` | No | The port for HTTP. *Default: 8080* |
| `-username` | No | Name of our user, as used e.g. in salutation. No length or charset limitation. *Default: Player 1* |
| `-accessCode` | Yes | Access code for the user. *Default: AllYourCodesAreBelongToUs* |
| `-sessionSalt` | Yes | Variable to salt the session token generator with. |
| `-seedFile` | Yes | JSON file to read challenge information from. |
| `-vpnRemoteAddress` | Yes | Address the VPN will run on, as rendered into the client VPN configuration file. |
| `-vpnRemotePort` | No | Port the VPN will run on |
| `-endTimestamp` | No | Date/Time after which flags are not accepted anymore |
| `-endAfter` | No | Seconds (!) after the first login, after which flags are not accepted anymore |

If `-endTimestamp` **and** `-endAfter` is given, flags are not accepted if **one** of the given flags kicks in.

## Seed file

The seed file should be of the following format:

```
{
  "challenges": [
    {
      "name": "Evil Service",
      "description": "A meaningful and funny description",
      "flag": "CIRCUS[IS_REALLY_COOL]",
      "container": "challenge-evilservice",
      "category": "Miscellaneous"
    },
    {
      "name": "Insecure Stuff",
      [...]
  ]
}
```

## API endpoints

| Path | Method | Parameter | Description |
|---|---|---|---|
| `/` | GET | - | static hosting `/files/index.html` |
| `/files/{file}` | GET | - | static hosting `{file}`, from `hosted/` directory. *Path traversal*-safe |
| `/login` | GET | - | static hosting `/files/login.html` |
| `/login` | POST | `username`, `accesscode` | processing `username` and `accesscode`, giving the user a session if they are valid |
| `/logout` | GET | - | Invalidates the session |
| `/challenges` | GET | - | static hosting `/files/challenges.html` |
| `/access` | GET | - | static hosting `/files/access.html` |
| `/api/getChallenges` | GET | - | Returns all challenges, as JSON. For an example, see below. |
| `/api/submitFlag` | POST | `challengeName`, `flag` | Validates `flag` for `challengeName` |
| `/api/startContainer` | POST | `challengeName` | Starts the challenge container for `challengeName`, if it's not already started |
| `/api/stopContainer` | POST | `challengeName` | Stops the challenge container for `challengeName`, if it's running |
| `/api/getAccess` | GET | - | Returns the VPN configuration required for accessing the containers |

### Response: `/api/getChallenges`

```
{
	"categories": {
		"Miscellaneous":1 // contains the amount of challenges in that category
	},
	"challenges": [
		{
			"name": "ChallengeName",
			"description": "Some meaningful, interesting and funny description",
			"category": "Miscellaneous",
			"foundFlag": false, // whether the user found the flag
			"ContainsLaunchable": true, // if set to true: there's a container which can be started/stopped
			"IPAddress": "1.2.3.4" // contains the IP address if the container is running
		}
	]
}
```