https://github.com/theflash2k/ctfd-flag-validator
A Simple CTFd Plugin that will act as a flag generator and validator
https://github.com/theflash2k/ctfd-flag-validator
ctfd ctfd-plugin
Last synced: about 1 year ago
JSON representation
A Simple CTFd Plugin that will act as a flag generator and validator
- Host: GitHub
- URL: https://github.com/theflash2k/ctfd-flag-validator
- Owner: TheFlash2k
- Created: 2023-10-31T23:50:13.000Z (over 2 years ago)
- Default Branch: main
- Last Pushed: 2023-11-23T18:14:40.000Z (over 2 years ago)
- Last Synced: 2023-11-24T18:41:53.813Z (over 2 years ago)
- Topics: ctfd, ctfd-plugin
- Language: Python
- Homepage:
- Size: 31.3 KB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# CTFd-Flag-Validator
A Simple CTFd Plugin (not really a plugin) that will act as a flag generator and validator
> **NOTE**: This only works with challenges that have a RegEx-based Flag and works only on TEAM Mode (along with the [**containers**](https://github.com/theflash2k/containers) plugin)
The working of this is as follows:
- Creating an API using FastAPI and exposes two endpoints:
- `/flag` - This API takes two query parameters:
- `team_id`
- `chal_id`
And generates a FLAG based on these parameters.
- `/check`
- Runs a check against the submitted flags and those in the database to check for duplicates.
- Also checks if someone without generating a flag, submitted it.
> Each team will have a single flag for a single challenge and that flag will be stored locally in `flags.db` file.
---
## Covered Scenarios
- [x] Team-A generates a flag, Team-B submits it before Team-A `(Both teams will be banned)`
- [x] Team-B generated a flag, Team-A submits it, Team-B doesn't submit `(Both teams will be banned) [Each team will have 1 flag generated per challenge, and that won't change no matter how many new instances are spawned]`
- [x] Team-A somehow guesses the Regex and generates a flag and submits it `(Team-A will be banned for brute-forcing and not solving as intended)`
- [x] Team-A and Team-B banned for using Team-A's flag. Team-C submit's Team-A's flag `(Team-C will be banned)`
---
## Environment Variables
- `CTFD_ADMIN_TOKEN` - The CTFd API Administrator Token
- `CTFD_INSTANCE` - The URL for the CTFd Instance
- `DISCORD_WEBHOOK_URL` - **[OPTIONAL]** - The Webhook URL to post your Ban notifications on Discord (by default, Notifications are posted on CTFd as well.)
- `API_HOST` - **[DEFAULT: *0.0.0.0*]** - The host on which the API will listen on
- `API_PORT` - **[DEFAULT: *9125*]** - The port on which API will listen on
- `VERIFICATION_DELAY` - **[DEFAULT: *1*]** - The delay (in minutes), after which request to `/check` will be made.
- `DB_NAME` - **[DEFAULT: *flags.db*]** - The local database name in which flags and their detail will be stored
---
## Integration with CTFd docker-compose:
In order to integrate this with your CTFd `docker-compose`, just copy the following config into your CTFd's docker-compose:
```yaml
flagvalidator:
build: . # Change this to the folder you have the source code + Dockerfile in.
ports:
- "172.17.0.1:9512:9512"
environment:
- CTFD_ADMIN_TOKEN=
- CTFD_INSTANCE=
- DISCORD_WEBHOOK_URL=""
- API_HOST="0.0.0.0"
- API_PORT=9512
- VERIFICATION_DELAY=1
- DB_NAME="flags.db"
volumes:
- .:/app/
restart: always
```
> Make sure that you paste this under the `services` key inside the `docker-compose.yml`.
---
## Setting up the plugin
In order to set this up, we need to run this inside docker. Both Dockerfile and docker-compose.yml have been provided to make it easier. The `flags.db` will be generated at run time and the current folder will be mounted inside the docker container.
> NOTE: If you're running a local `CTFd` deployment, make sure to modify the variables inside your docker-entrypoint scripts accordingly.
---
## Setting up a challenge:
Let's suppose we have a challenge called `test_chal`, and we want to add a dynamic flag. The YAML config file is:
```yaml
name: "test_chal"
author: "TheFlash2k"
category: Test
description: Some Descriptive Description
value: 100
type: container
extra:
initial: 100
decay: 1
minimum: 100
image: test_chal:latest
port: 8000
command: ""
volumes: ""
build: ./src/
flags:
- {
type: "regex",
content: "CY243L{s4mpl3_fl4g_r3geX_[0-9a-zA-Z]{9}[1-9a-zA-Z]{9}[5-9a-eR-Z]{8}",
data: "case_insensitive",
}
state: visible
version: "0.1"
```
Now, inside the `src/` folder, a Dockerfile can be as follows:
```Dockerfile
FROM php:7.0-apache
ENV BASE_DIR="/var/www/html"
COPY ./src/ $BASE_DIR/
COPY ./docker-entrypoint.sh /
RUN echo "ServerName localhost" >> "/etc/apache2/apache2.conf"
ENTRYPOINT [ "/docker-entrypoint.sh" ]
```
Now, inside the `docker-entrypoint.sh`, we need to fetch the flag from `http://172.17.0.1:9152` (or whatever your API_PORT is)
> NOTE: The IP is of `docker0` interface on your system
> Quick Fact: Using the `containers` plugin which I've forked, I set `CHALLENGE_ID` and `TEAM_ID` as environment variable on each container being deployed, therefore, the script uses these:
```bash
service=http://172.17.0.1:9512
flag=$(curl -s $service/flag\?chal_id\=$CHALLENGE_ID\&team_id\=$TEAM_ID)
# We now have the flag in $flag and can do whatever we want:
echo $flag > /var/www/html/flag.txt
```
Similarly, for your own containers, you will have to write a similar `docker-entrypoint.sh` and set that as your entrypoint to cater for dynamic flaging. The rest will be managed by this plugin.
## Screenshots
- On the CTFd Web Page

- Logs being generated
