From 4e7df1cecea8c286b34fa2e301753c0bbebc21b9 Mon Sep 17 00:00:00 2001 From: The0mikkel <28625667+The0mikkel@users.noreply.github.com> Date: Sat, 20 Dec 2025 11:18:13 +0000 Subject: [PATCH 01/30] Create challenge: Where robots cannot search by The Mikkel --- .../web/where-robots-cannot-search/README.md | 4 + .../where-robots-cannot-search/challenge.yml | 27 ++++ .../where-robots-cannot-search/description.md | 6 + .../handout/.gitkeep | 2 + .../k8s/files/.gitkeep | 2 + .../solution/README.md | 3 + .../where-robots-cannot-search/src/.gitkeep | 2 + .../where-robots-cannot-search/src/Dockerfile | 8 ++ .../template/.gitkeep | 2 + .../template/k8s.yml | 133 ++++++++++++++++++ .../web/where-robots-cannot-search/version | 1 + 11 files changed, 190 insertions(+) create mode 100644 challenges/web/where-robots-cannot-search/README.md create mode 100644 challenges/web/where-robots-cannot-search/challenge.yml create mode 100644 challenges/web/where-robots-cannot-search/description.md create mode 100644 challenges/web/where-robots-cannot-search/handout/.gitkeep create mode 100644 challenges/web/where-robots-cannot-search/k8s/files/.gitkeep create mode 100644 challenges/web/where-robots-cannot-search/solution/README.md create mode 100644 challenges/web/where-robots-cannot-search/src/.gitkeep create mode 100644 challenges/web/where-robots-cannot-search/src/Dockerfile create mode 100644 challenges/web/where-robots-cannot-search/template/.gitkeep create mode 100644 challenges/web/where-robots-cannot-search/template/k8s.yml create mode 100644 challenges/web/where-robots-cannot-search/version diff --git a/challenges/web/where-robots-cannot-search/README.md b/challenges/web/where-robots-cannot-search/README.md new file mode 100644 index 0000000..efc04ff --- /dev/null +++ b/challenges/web/where-robots-cannot-search/README.md @@ -0,0 +1,4 @@ +# Where robots cannot search + +*Add information about challenge here* +*It is meant to contain internal documentation of the challenge, such as how it is solved* diff --git a/challenges/web/where-robots-cannot-search/challenge.yml b/challenges/web/where-robots-cannot-search/challenge.yml new file mode 100644 index 0000000..64e9b10 --- /dev/null +++ b/challenges/web/where-robots-cannot-search/challenge.yml @@ -0,0 +1,27 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/ctfpilot/challenge-schema/refs/heads/main/schema.json + +enabled: true +name: Where robots cannot search +slug: where-robots-cannot-search +author: The Mikkel +category: web +difficulty: beginner +tags: [] +type: instanced +instanced_type: web +instanced_name: null +instanced_subdomains: [] +connection: null +flag: +- flag: ctfpilot{r0bot5_sh0u1d_nOt_637_h3re_b0t_You_g07_h3re} + case_sensitive: false +points: 1000 +decay: 75 +min_points: 100 +description_location: description.md +handout_dir: handout +dockerfile_locations: +- location: src/Dockerfile + context: src/ + identifier: null + diff --git a/challenges/web/where-robots-cannot-search/description.md b/challenges/web/where-robots-cannot-search/description.md new file mode 100644 index 0000000..065df6f --- /dev/null +++ b/challenges/web/where-robots-cannot-search/description.md @@ -0,0 +1,6 @@ +# Where robots cannot search + +**Difficulty:** Beginner +**Author:** The Mikkel + +*Add challenge description here* diff --git a/challenges/web/where-robots-cannot-search/handout/.gitkeep b/challenges/web/where-robots-cannot-search/handout/.gitkeep new file mode 100644 index 0000000..0f065bc --- /dev/null +++ b/challenges/web/where-robots-cannot-search/handout/.gitkeep @@ -0,0 +1,2 @@ +# This file is used to keep the directory in the repository. +# This directory is used to store files that are handed out, for the challenge. The files are automatically zipped and copied to the files directory. \ No newline at end of file diff --git a/challenges/web/where-robots-cannot-search/k8s/files/.gitkeep b/challenges/web/where-robots-cannot-search/k8s/files/.gitkeep new file mode 100644 index 0000000..4fd76bb --- /dev/null +++ b/challenges/web/where-robots-cannot-search/k8s/files/.gitkeep @@ -0,0 +1,2 @@ +# This file is used to keep the directory in the repository. +# This directory is used to store files that are handed out, for the challenge. Use the handout directory for files that are handed out to users and want to be packaged as a zip file. \ No newline at end of file diff --git a/challenges/web/where-robots-cannot-search/solution/README.md b/challenges/web/where-robots-cannot-search/solution/README.md new file mode 100644 index 0000000..8614e07 --- /dev/null +++ b/challenges/web/where-robots-cannot-search/solution/README.md @@ -0,0 +1,3 @@ +# Solution +This directory is used to store the solution script for the challenge. +This file should contain the steps to solve the challenge. \ No newline at end of file diff --git a/challenges/web/where-robots-cannot-search/src/.gitkeep b/challenges/web/where-robots-cannot-search/src/.gitkeep new file mode 100644 index 0000000..76376a2 --- /dev/null +++ b/challenges/web/where-robots-cannot-search/src/.gitkeep @@ -0,0 +1,2 @@ +# This file is used to keep the directory in the repository. +# This directory is used to store source files for the challenge. \ No newline at end of file diff --git a/challenges/web/where-robots-cannot-search/src/Dockerfile b/challenges/web/where-robots-cannot-search/src/Dockerfile new file mode 100644 index 0000000..ec330ff --- /dev/null +++ b/challenges/web/where-robots-cannot-search/src/Dockerfile @@ -0,0 +1,8 @@ +# Dockerfile for web - Where robots cannot search +FROM ubuntu:22.04 + +RUN apt-get update && apt-get upgrade -y && apt-get install -y python3 +RUN useradd -m challengeuser + +USER challengeuser + diff --git a/challenges/web/where-robots-cannot-search/template/.gitkeep b/challenges/web/where-robots-cannot-search/template/.gitkeep new file mode 100644 index 0000000..709b816 --- /dev/null +++ b/challenges/web/where-robots-cannot-search/template/.gitkeep @@ -0,0 +1,2 @@ +# This file is used to keep the directory in the repository. +# This directory is used to store templates for the challenge deployment. \ No newline at end of file diff --git a/challenges/web/where-robots-cannot-search/template/k8s.yml b/challenges/web/where-robots-cannot-search/template/k8s.yml new file mode 100644 index 0000000..51cdafe --- /dev/null +++ b/challenges/web/where-robots-cannot-search/template/k8s.yml @@ -0,0 +1,133 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: "ctf-{{ deployment_id }}" + namespace: kubectf-challenges-instanced + labels: + challenges.ctfpilot.com/type: "{{ CHALLENGE_TYPE }}" + challenges.ctfpilot.com/name: "{{ CHALLENGE_NAME }}" + challenges.ctfpilot.com/category: "{{ CHALLENGE_CATEGORY }}" + instanced.challenges.ctfpilot.com/deployment: "{{ deployment_id }}" + instanced.challenges.ctfpilot.com/owner: "{{ owner_id }}" + ctfpilot.com/component: "instanced-challenge" + annotations: + janitor/expires: "{{ expires }}" +spec: + replicas: 1 + selector: + matchLabels: + instanced.challenges.ctfpilot.com/deployment: "{{ deployment_id }}" + instanced.challenges.ctfpilot.com/owner: "{{ owner_id }}" + template: + metadata: + labels: + role: "{{ CHALLENGE_TYPE }}" + challenges.ctfpilot.com/type: "{{ CHALLENGE_TYPE }}" + challenges.ctfpilot.com/name: "{{ CHALLENGE_NAME }}" + challenges.ctfpilot.com/category: "{{ CHALLENGE_CATEGORY }}" + instanced.challenges.ctfpilot.com/deployment: "{{ deployment_id }}" + instanced.challenges.ctfpilot.com/owner: "{{ owner_id }}" + ctfpilot.com/component: "instanced-challenge" + spec: + enableServiceLinks: false + automountServiceAccountToken: false + imagePullSecrets: + - name: dockerconfigjson-github-com + dnsPolicy: None + dnsConfig: + nameservers: + - 1.1.1.1 + - 8.8.8.8 + tolerations: + - key: "cluster.ctfpilot.com/node" + value: "scaler" + effect: "PreferNoSchedule" + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: "cluster.ctfpilot.com/node" + operator: In + values: + - scaler + containers: + - name: web + image: ghcr.io/{{ CHALLENGE_REPO }}-{{ DOCKER_IMAGE }}:{{ CHALLENGE_VERSION }} + imagePullPolicy: IfNotPresent + resources: + limits: + cpu: 200m + memory: 256Mi + requests: + cpu: 10m + memory: 32Mi + ports: + - containerPort: 80 + name: web-port + startupProbe: + httpGet: + path: / + port: web-port + failureThreshold: 12 + periodSeconds: 10 + readinessProbe: + httpGet: + path: / + port: web-port + initialDelaySeconds: 5 + timeoutSeconds: 5 +--- +apiVersion: v1 +kind: Service +metadata: + name: "ctf-{{ deployment_id }}" + namespace: kubectf-challenges-instanced + labels: + challenges.ctfpilot.com/type: "{{ CHALLENGE_TYPE }}" + challenges.ctfpilot.com/name: "{{ CHALLENGE_NAME }}" + challenges.ctfpilot.com/category: "{{ CHALLENGE_CATEGORY }}" + instanced.challenges.ctfpilot.com/deployment: "{{ deployment_id }}" + instanced.challenges.ctfpilot.com/owner: "{{ owner_id }}" + ctfpilot.com/component: "instanced-challenge" + annotations: + janitor/expires: "{{ expires }}" +spec: + selector: + role: "{{ CHALLENGE_TYPE }}" + instanced.challenges.ctfpilot.com/deployment: "{{ deployment_id }}" + ports: + - port: 80 + targetPort: web-port +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: ingress-ctf-{{ deployment_id }} + namespace: kubectf-challenges-instanced + labels: + challenges.ctfpilot.com/type: "{{ CHALLENGE_TYPE }}" + challenges.ctfpilot.com/name: "{{ CHALLENGE_NAME }}" + challenges.ctfpilot.com/category: "{{ CHALLENGE_CATEGORY }}" + instanced.challenges.ctfpilot.com/deployment: "{{ deployment_id }}" + instanced.challenges.ctfpilot.com/owner: "{{ owner_id }}" + ctfpilot.com/component: "instanced-challenge" + annotations: + janitor/expires: "{{ expires }}" + traefik.ingress.kubernetes.io/router.middlewares: kubectf-instancing-fallback@kubernetescrd +spec: + tls: + - hosts: + - "{{ deployment_id }}.{{ domain }}" + secretName: kubectf-cert-challs + rules: + - host: "{{ deployment_id }}.{{ domain }}" + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: ctf-{{ deployment_id }} + port: + number: 80 diff --git a/challenges/web/where-robots-cannot-search/version b/challenges/web/where-robots-cannot-search/version new file mode 100644 index 0000000..56a6051 --- /dev/null +++ b/challenges/web/where-robots-cannot-search/version @@ -0,0 +1 @@ +1 \ No newline at end of file From ddc6405633cfce912321adc656875650dcfe293b Mon Sep 17 00:00:00 2001 From: The0Mikkel Date: Sat, 20 Dec 2025 12:26:52 +0100 Subject: [PATCH 02/30] Add Where robots cannot search from BrunnerCTF 2025 --- .../where-robots-cannot-search/challenge.yml | 4 +- .../where-robots-cannot-search/description.md | 3 +- .../solution/README.md | 4 +- .../solution/solve.py | 109 ++++++++++++++++++ .../where-robots-cannot-search/src/Dockerfile | 9 +- .../src/docker-compose.yml | 7 ++ .../src/html/.htaccess | 5 + .../src/html/admin.html | 39 +++++++ .../src/html/flag.txt | 1 + .../src/html/hidden.html | 39 +++++++ .../src/html/index.html | 87 ++++++++++++++ .../src/html/private.html | 39 +++++++ .../src/html/robots.txt | 5 + 13 files changed, 342 insertions(+), 9 deletions(-) create mode 100644 challenges/web/where-robots-cannot-search/solution/solve.py create mode 100644 challenges/web/where-robots-cannot-search/src/docker-compose.yml create mode 100644 challenges/web/where-robots-cannot-search/src/html/.htaccess create mode 100644 challenges/web/where-robots-cannot-search/src/html/admin.html create mode 100644 challenges/web/where-robots-cannot-search/src/html/flag.txt create mode 100644 challenges/web/where-robots-cannot-search/src/html/hidden.html create mode 100644 challenges/web/where-robots-cannot-search/src/html/index.html create mode 100644 challenges/web/where-robots-cannot-search/src/html/private.html create mode 100644 challenges/web/where-robots-cannot-search/src/html/robots.txt diff --git a/challenges/web/where-robots-cannot-search/challenge.yml b/challenges/web/where-robots-cannot-search/challenge.yml index 64e9b10..82857e9 100644 --- a/challenges/web/where-robots-cannot-search/challenge.yml +++ b/challenges/web/where-robots-cannot-search/challenge.yml @@ -6,7 +6,9 @@ slug: where-robots-cannot-search author: The Mikkel category: web difficulty: beginner -tags: [] +tags: [ + "BrunnerCTF 2025", +] type: instanced instanced_type: web instanced_name: null diff --git a/challenges/web/where-robots-cannot-search/description.md b/challenges/web/where-robots-cannot-search/description.md index 065df6f..d8680ae 100644 --- a/challenges/web/where-robots-cannot-search/description.md +++ b/challenges/web/where-robots-cannot-search/description.md @@ -3,4 +3,5 @@ **Difficulty:** Beginner **Author:** The Mikkel -*Add challenge description here* +Ahh, the Brunnerne company. +But they have a secret, hidden away from robot search. diff --git a/challenges/web/where-robots-cannot-search/solution/README.md b/challenges/web/where-robots-cannot-search/solution/README.md index 8614e07..3023e39 100644 --- a/challenges/web/where-robots-cannot-search/solution/README.md +++ b/challenges/web/where-robots-cannot-search/solution/README.md @@ -1,3 +1,3 @@ # Solution -This directory is used to store the solution script for the challenge. -This file should contain the steps to solve the challenge. \ No newline at end of file + +Go to `/robots.txt` and see `/flag.txt` is disallowed. Go there for flag. diff --git a/challenges/web/where-robots-cannot-search/solution/solve.py b/challenges/web/where-robots-cannot-search/solution/solve.py new file mode 100644 index 0000000..1a985d9 --- /dev/null +++ b/challenges/web/where-robots-cannot-search/solution/solve.py @@ -0,0 +1,109 @@ +import requests +import argparse + +# ----------------- Logger class ----------------- + +# Fold this line in to minimize the code +class Logger: + level = 0 + + def __init__(self, verbose: bool, debug: bool = False): + if verbose: + self.level = 1 + self.write('Verbose logging enabled') + if debug: + self.write('[DEBUG] Debug logging enabled') + self.level = 2 + + ''' + Write a message to the console, regardless of the log level + ''' + def write(self, msg: str): + print(msg) + + ''' + Log a message to the console, if verbose logging is enabled + ''' + def log(self, msg: str): + if self.level > 0: + print(msg) + + ''' + Log a message to the console, if debug logging is enabled + ''' + def debug(self, msg: str): + if self.level > 1: + print(f'[DEBUG] {msg}') + +logger = Logger(False, False) # Is replaced by the logger in the main function + +# ----------------- Challenge specific code ----------------- + +def solve(url: str, flag: str) -> bool: + # Solve the challenge + # Ensure website is reachable + try: + logger.debug(f'Connecting to {url}') + response = requests.get(url) + except requests.exceptions.RequestException as e: + logger.log(f'Failed to connect to {url}') + return False + + # Send a GET request to the robots.txt file + try: + logger.debug('Sending GET request to robots.txt') + response = requests.get(url + '/robots.txt') + except requests.exceptions.RequestException as e: + logger.log('Failed to connect to /robots.txt') + return False + # Check if flag.txt is disallowed + if '/flag.txt' in response.text: + logger.log('Flag.txt is disallowed') + else: + logger.log('Flag.txt not specified in /robots.txt') + return False + + # Send a GET request to the flag.txt file + try: + logger.debug('Sending GET request to /flag.txt') + response = requests.get(url + '/flag.txt') + except requests.exceptions.RequestException as e: + logger.log('Failed to connect to flag.txt') + return False + # Check if the response contains the flag + if flag in response.text: + logger.log('Flag found in flag.txt') + return True + else: + logger.log('Flag not found') + return False + +# ----------------- Helper classes and functions ----------------- + +def get_args(): + parser = argparse.ArgumentParser() + parser.add_argument('url', help='URL to the challenge', type=str) + parser.add_argument('flag', help='Correct flag, to check the challenge against') + parser.add_argument('-v', '--verbose', help='Verbose output', action='store_true', default=False) + parser.add_argument('-d', '--debug', help='Debug output', action='store_true', default=False) + return parser.parse_args() + +def main(): + args = get_args() + url = args.url + flag = args.flag + + logger = Logger(args.verbose, args.debug) + logger.log(f'URL: {url}') + logger.log(f'Flag: {flag}') + + logger.log('Starting solve script...') + if solve(url, flag): + print('Challenge solved successfully') + exit(0) + else: + print('Failed to solve challenge') + exit(1) + +if __name__ == '__main__': + main() diff --git a/challenges/web/where-robots-cannot-search/src/Dockerfile b/challenges/web/where-robots-cannot-search/src/Dockerfile index ec330ff..fa0ebfe 100644 --- a/challenges/web/where-robots-cannot-search/src/Dockerfile +++ b/challenges/web/where-robots-cannot-search/src/Dockerfile @@ -1,8 +1,7 @@ # Dockerfile for web - Where robots cannot search -FROM ubuntu:22.04 +FROM httpd:2.4-alpine -RUN apt-get update && apt-get upgrade -y && apt-get install -y python3 -RUN useradd -m challengeuser - -USER challengeuser +RUN sed -i 's|#LoadModule rewrite_module modules/mod_rewrite.so|LoadModule rewrite_module modules/mod_rewrite.so|' /usr/local/apache2/conf/httpd.conf +RUN sed -i 's|AllowOverride None|AllowOverride All|' /usr/local/apache2/conf/httpd.conf +COPY ./html/ /usr/local/apache2/htdocs/ diff --git a/challenges/web/where-robots-cannot-search/src/docker-compose.yml b/challenges/web/where-robots-cannot-search/src/docker-compose.yml new file mode 100644 index 0000000..bfd6d46 --- /dev/null +++ b/challenges/web/where-robots-cannot-search/src/docker-compose.yml @@ -0,0 +1,7 @@ +services: + where-robots-cannot-search: + build: . + ports: + - "8080:80" + volumes: + - ./html:/usr/local/apache2/htdocs/ diff --git a/challenges/web/where-robots-cannot-search/src/html/.htaccess b/challenges/web/where-robots-cannot-search/src/html/.htaccess new file mode 100644 index 0000000..c4b71b7 --- /dev/null +++ b/challenges/web/where-robots-cannot-search/src/html/.htaccess @@ -0,0 +1,5 @@ +# Allow redirection from none .html files to .html files +RewriteEngine On +RewriteCond %{REQUEST_FILENAME} !-f +RewriteCond %{REQUEST_FILENAME} !-d +RewriteRule ^(.*)$ $1.html [L] diff --git a/challenges/web/where-robots-cannot-search/src/html/admin.html b/challenges/web/where-robots-cannot-search/src/html/admin.html new file mode 100644 index 0000000..34dc2d1 --- /dev/null +++ b/challenges/web/where-robots-cannot-search/src/html/admin.html @@ -0,0 +1,39 @@ + + + + + + + Admin - Brunnerne Company + + + + +
+

Admin Page

+

This page is restricted to administrators only.

+
+ + + \ No newline at end of file diff --git a/challenges/web/where-robots-cannot-search/src/html/flag.txt b/challenges/web/where-robots-cannot-search/src/html/flag.txt new file mode 100644 index 0000000..bfd98c7 --- /dev/null +++ b/challenges/web/where-robots-cannot-search/src/html/flag.txt @@ -0,0 +1 @@ +ctfpilot{r0bot5_sh0u1d_nOt_637_h3re_b0t_You_g07_h3re} diff --git a/challenges/web/where-robots-cannot-search/src/html/hidden.html b/challenges/web/where-robots-cannot-search/src/html/hidden.html new file mode 100644 index 0000000..4daa3f3 --- /dev/null +++ b/challenges/web/where-robots-cannot-search/src/html/hidden.html @@ -0,0 +1,39 @@ + + + + + + + Hidden - Brunnerne Company + + + + +
+

Hidden Page

+

This page is hidden from search engines.

+
+ + + \ No newline at end of file diff --git a/challenges/web/where-robots-cannot-search/src/html/index.html b/challenges/web/where-robots-cannot-search/src/html/index.html new file mode 100644 index 0000000..fbeb2fb --- /dev/null +++ b/challenges/web/where-robots-cannot-search/src/html/index.html @@ -0,0 +1,87 @@ + + + + + + + Brunnerne Company + + + + +
+

Brunnerne Company

+
+
+

Welcome to Brunnerne Company

+

We specialize in creating the most delicious Brunsviger. Come by our store in Odense!

+ Check out our location +
+ + + + \ No newline at end of file diff --git a/challenges/web/where-robots-cannot-search/src/html/private.html b/challenges/web/where-robots-cannot-search/src/html/private.html new file mode 100644 index 0000000..0330375 --- /dev/null +++ b/challenges/web/where-robots-cannot-search/src/html/private.html @@ -0,0 +1,39 @@ + + + + + + + Private - Brunnerne Company + + + + +
+

Private Page

+

This page contains private information.

+
+ + + \ No newline at end of file diff --git a/challenges/web/where-robots-cannot-search/src/html/robots.txt b/challenges/web/where-robots-cannot-search/src/html/robots.txt new file mode 100644 index 0000000..db86de4 --- /dev/null +++ b/challenges/web/where-robots-cannot-search/src/html/robots.txt @@ -0,0 +1,5 @@ +User-agent: * +Disallow: /admin +Disallow: /private +Disallow: /hidden +Disallow: /flag.txt From a002a7e2d4c25e5da259c7acab646284c0615b8b Mon Sep 17 00:00:00 2001 From: The0Mikkel Date: Sat, 20 Dec 2025 12:33:10 +0100 Subject: [PATCH 03/30] Update CI jobs to match up-to-date challenge-ci --- .github/workflows/configure-challs.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/configure-challs.yml b/.github/workflows/configure-challs.yml index a733728..3031634 100644 --- a/.github/workflows/configure-challs.yml +++ b/.github/workflows/configure-challs.yml @@ -7,8 +7,8 @@ on: workflow_dispatch: jobs: - create_challenge: - name: Create challenge + configure_challenges: + name: Configure challenges uses: ctfpilot/challenge-ci/.github/workflows/configure-challs.yml@v1.0.0 permissions: contents: write From 963f0197c14d3489fd792dcf574ecbc6f3eafcf1 Mon Sep 17 00:00:00 2001 From: The0Mikkel Date: Sat, 20 Dec 2025 12:49:15 +0100 Subject: [PATCH 04/30] Update workflows to use challenge-ci version 1.0.1 --- .github/workflows/configure-challs.yml | 2 +- .github/workflows/configure-pages.yml | 4 ++-- .github/workflows/create-chall.yml | 2 +- .github/workflows/render-templates.yml | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/configure-challs.yml b/.github/workflows/configure-challs.yml index 3031634..9368986 100644 --- a/.github/workflows/configure-challs.yml +++ b/.github/workflows/configure-challs.yml @@ -9,7 +9,7 @@ on: jobs: configure_challenges: name: Configure challenges - uses: ctfpilot/challenge-ci/.github/workflows/configure-challs.yml@v1.0.0 + uses: ctfpilot/challenge-ci/.github/workflows/configure-challs.yml@v1.0.1 permissions: contents: write packages: write diff --git a/.github/workflows/configure-pages.yml b/.github/workflows/configure-pages.yml index bd410a3..e382887 100644 --- a/.github/workflows/configure-pages.yml +++ b/.github/workflows/configure-pages.yml @@ -9,9 +9,9 @@ on: jobs: create_pages: name: Create pages - uses: ctfpilot/challenge-ci/.github/workflows/configure-pages.yml@v1.0.0 + uses: ctfpilot/challenge-ci/.github/workflows/configure-pages.yml@v1.0.1 permissions: contents: write with: runs-on: "ubuntu-latest" - toolkit-path: "./challenge-toolkit/" \ No newline at end of file + toolkit-path: "./challenge-toolkit/" diff --git a/.github/workflows/create-chall.yml b/.github/workflows/create-chall.yml index 5e932b6..5f0c53f 100644 --- a/.github/workflows/create-chall.yml +++ b/.github/workflows/create-chall.yml @@ -81,7 +81,7 @@ on: jobs: create_challenge: name: Create challenge - uses: ctfpilot/challenge-ci/.github/workflows/create-chall.yml@v1.0.0 + uses: ctfpilot/challenge-ci/.github/workflows/create-chall.yml@v1.0.1 permissions: contents: write pull-requests: write diff --git a/.github/workflows/render-templates.yml b/.github/workflows/render-templates.yml index 8213889..5f02fba 100644 --- a/.github/workflows/render-templates.yml +++ b/.github/workflows/render-templates.yml @@ -6,7 +6,7 @@ on: jobs: render_templates: name: Render all templates - uses: ctfpilot/challenge-ci/.github/workflows/render-templates.yml@v1.0.0 + uses: ctfpilot/challenge-ci/.github/workflows/render-templates.yml@v1.0.1 permissions: contents: write packages: write From c9fe01df37555be5b3ee82127624e0faf6589675 Mon Sep 17 00:00:00 2001 From: The0Mikkel Date: Sat, 20 Dec 2025 12:50:35 +0100 Subject: [PATCH 05/30] Trigger rebuild of where-robots-cannot-search --- challenges/web/where-robots-cannot-search/version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/challenges/web/where-robots-cannot-search/version b/challenges/web/where-robots-cannot-search/version index 56a6051..d8263ee 100644 --- a/challenges/web/where-robots-cannot-search/version +++ b/challenges/web/where-robots-cannot-search/version @@ -1 +1 @@ -1 \ No newline at end of file +2 \ No newline at end of file From 9bd142df18113be035c6fd550370c154beeba1e7 Mon Sep 17 00:00:00 2001 From: The0Mikkel Date: Sat, 20 Dec 2025 13:00:48 +0100 Subject: [PATCH 06/30] Update workflows to use challenge-ci version 1.0.2 --- .github/workflows/configure-challs.yml | 2 +- .github/workflows/configure-pages.yml | 2 +- .github/workflows/create-chall.yml | 2 +- .github/workflows/render-templates.yml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/configure-challs.yml b/.github/workflows/configure-challs.yml index 9368986..67c8352 100644 --- a/.github/workflows/configure-challs.yml +++ b/.github/workflows/configure-challs.yml @@ -9,7 +9,7 @@ on: jobs: configure_challenges: name: Configure challenges - uses: ctfpilot/challenge-ci/.github/workflows/configure-challs.yml@v1.0.1 + uses: ctfpilot/challenge-ci/.github/workflows/configure-challs.yml@v1.0.2 permissions: contents: write packages: write diff --git a/.github/workflows/configure-pages.yml b/.github/workflows/configure-pages.yml index e382887..627f398 100644 --- a/.github/workflows/configure-pages.yml +++ b/.github/workflows/configure-pages.yml @@ -9,7 +9,7 @@ on: jobs: create_pages: name: Create pages - uses: ctfpilot/challenge-ci/.github/workflows/configure-pages.yml@v1.0.1 + uses: ctfpilot/challenge-ci/.github/workflows/configure-pages.yml@v1.0.2 permissions: contents: write with: diff --git a/.github/workflows/create-chall.yml b/.github/workflows/create-chall.yml index 5f0c53f..486f134 100644 --- a/.github/workflows/create-chall.yml +++ b/.github/workflows/create-chall.yml @@ -81,7 +81,7 @@ on: jobs: create_challenge: name: Create challenge - uses: ctfpilot/challenge-ci/.github/workflows/create-chall.yml@v1.0.1 + uses: ctfpilot/challenge-ci/.github/workflows/create-chall.yml@v1.0.2 permissions: contents: write pull-requests: write diff --git a/.github/workflows/render-templates.yml b/.github/workflows/render-templates.yml index 5f02fba..92aa725 100644 --- a/.github/workflows/render-templates.yml +++ b/.github/workflows/render-templates.yml @@ -6,7 +6,7 @@ on: jobs: render_templates: name: Render all templates - uses: ctfpilot/challenge-ci/.github/workflows/render-templates.yml@v1.0.1 + uses: ctfpilot/challenge-ci/.github/workflows/render-templates.yml@v1.0.2 permissions: contents: write packages: write From e1db9d714d6c30f2e85d7310e512212e75d896cb Mon Sep 17 00:00:00 2001 From: The0Mikkel Date: Sat, 20 Dec 2025 13:01:09 +0100 Subject: [PATCH 07/30] Trigger rebuild of where-robots-cannot-search --- challenges/web/where-robots-cannot-search/version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/challenges/web/where-robots-cannot-search/version b/challenges/web/where-robots-cannot-search/version index d8263ee..56a6051 100644 --- a/challenges/web/where-robots-cannot-search/version +++ b/challenges/web/where-robots-cannot-search/version @@ -1 +1 @@ -2 \ No newline at end of file +1 \ No newline at end of file From be9cbf4265d23373159e2c70f98c132c57f4f9fa Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 20 Dec 2025 12:02:08 +0000 Subject: [PATCH 08/30] CI: Update challenges [skip ci] --- .../k8s/challenge/k8s.yml | 147 ++++++++++++++++++ .../k8s/config/Chart.yaml | 6 + .../k8s/config/templates/k8s.yml | 63 ++++++++ .../k8s/config/values.yaml | 11 ++ .../k8s/files/.gitkeep | 3 +- .../web/where-robots-cannot-search/version | 2 +- 6 files changed, 229 insertions(+), 3 deletions(-) create mode 100644 challenges/web/where-robots-cannot-search/k8s/challenge/k8s.yml create mode 100644 challenges/web/where-robots-cannot-search/k8s/config/Chart.yaml create mode 100644 challenges/web/where-robots-cannot-search/k8s/config/templates/k8s.yml create mode 100644 challenges/web/where-robots-cannot-search/k8s/config/values.yaml diff --git a/challenges/web/where-robots-cannot-search/k8s/challenge/k8s.yml b/challenges/web/where-robots-cannot-search/k8s/challenge/k8s.yml new file mode 100644 index 0000000..5f0578e --- /dev/null +++ b/challenges/web/where-robots-cannot-search/k8s/challenge/k8s.yml @@ -0,0 +1,147 @@ +apiVersion: kube-ctf.ctfpilot.com/v1 +kind: instancedChallenge +metadata: + name: "where-robots-cannot-search" + labels: + challenges.ctfpilot.com/type: "web" + challenges.ctfpilot.com/name: "where-robots-cannot-search" + challenges.ctfpilot.com/category: "web" + ctfpilot.com/component: "instanced-challenge" +spec: + expires: 3600 + available_at: 0 + type: web + template: | + apiVersion: apps/v1 + kind: Deployment + metadata: + name: "ctf-{{ deployment_id }}" + namespace: kubectf-challenges-instanced + labels: + challenges.ctfpilot.com/type: "web" + challenges.ctfpilot.com/name: "where-robots-cannot-search" + challenges.ctfpilot.com/category: "web" + instanced.challenges.ctfpilot.com/deployment: "{{ deployment_id }}" + instanced.challenges.ctfpilot.com/owner: "{{ owner_id }}" + ctfpilot.com/component: "instanced-challenge" + annotations: + janitor/expires: "{{ expires }}" + spec: + replicas: 1 + selector: + matchLabels: + instanced.challenges.ctfpilot.com/deployment: "{{ deployment_id }}" + instanced.challenges.ctfpilot.com/owner: "{{ owner_id }}" + template: + metadata: + labels: + role: "web" + challenges.ctfpilot.com/type: "web" + challenges.ctfpilot.com/name: "where-robots-cannot-search" + challenges.ctfpilot.com/category: "web" + instanced.challenges.ctfpilot.com/deployment: "{{ deployment_id }}" + instanced.challenges.ctfpilot.com/owner: "{{ owner_id }}" + ctfpilot.com/component: "instanced-challenge" + spec: + enableServiceLinks: false + automountServiceAccountToken: false + imagePullSecrets: + - name: dockerconfigjson-github-com + dnsPolicy: None + dnsConfig: + nameservers: + - 1.1.1.1 + - 8.8.8.8 + tolerations: + - key: "cluster.ctfpilot.com/node" + value: "scaler" + effect: "PreferNoSchedule" + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: "cluster.ctfpilot.com/node" + operator: In + values: + - scaler + containers: + - name: web + image: ghcr.io/ctfpilot/challenges-example-web-where-robots-cannot-search:2 + imagePullPolicy: IfNotPresent + resources: + limits: + cpu: 200m + memory: 256Mi + requests: + cpu: 10m + memory: 32Mi + ports: + - containerPort: 80 + name: web-port + startupProbe: + httpGet: + path: / + port: web-port + failureThreshold: 12 + periodSeconds: 10 + readinessProbe: + httpGet: + path: / + port: web-port + initialDelaySeconds: 5 + timeoutSeconds: 5 + --- + apiVersion: v1 + kind: Service + metadata: + name: "ctf-{{ deployment_id }}" + namespace: kubectf-challenges-instanced + labels: + challenges.ctfpilot.com/type: "web" + challenges.ctfpilot.com/name: "where-robots-cannot-search" + challenges.ctfpilot.com/category: "web" + instanced.challenges.ctfpilot.com/deployment: "{{ deployment_id }}" + instanced.challenges.ctfpilot.com/owner: "{{ owner_id }}" + ctfpilot.com/component: "instanced-challenge" + annotations: + janitor/expires: "{{ expires }}" + spec: + selector: + role: "web" + instanced.challenges.ctfpilot.com/deployment: "{{ deployment_id }}" + ports: + - port: 80 + targetPort: web-port + --- + apiVersion: networking.k8s.io/v1 + kind: Ingress + metadata: + name: ingress-ctf-{{ deployment_id }} + namespace: kubectf-challenges-instanced + labels: + challenges.ctfpilot.com/type: "web" + challenges.ctfpilot.com/name: "where-robots-cannot-search" + challenges.ctfpilot.com/category: "web" + instanced.challenges.ctfpilot.com/deployment: "{{ deployment_id }}" + instanced.challenges.ctfpilot.com/owner: "{{ owner_id }}" + ctfpilot.com/component: "instanced-challenge" + annotations: + janitor/expires: "{{ expires }}" + traefik.ingress.kubernetes.io/router.middlewares: kubectf-instancing-fallback@kubernetescrd + spec: + tls: + - hosts: + - "{{ deployment_id }}.{{ domain }}" + secretName: kubectf-cert-challs + rules: + - host: "{{ deployment_id }}.{{ domain }}" + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: ctf-{{ deployment_id }} + port: + number: 80 diff --git a/challenges/web/where-robots-cannot-search/k8s/config/Chart.yaml b/challenges/web/where-robots-cannot-search/k8s/config/Chart.yaml new file mode 100644 index 0000000..cf0aa6b --- /dev/null +++ b/challenges/web/where-robots-cannot-search/k8s/config/Chart.yaml @@ -0,0 +1,6 @@ +apiVersion: v2 +name: configmap-where-robots-cannot-search +version: 1.2.0 +description: Challenge configmap for where-robots-cannot-search in category web +appVersion: "1.2.0" +type: application diff --git a/challenges/web/where-robots-cannot-search/k8s/config/templates/k8s.yml b/challenges/web/where-robots-cannot-search/k8s/config/templates/k8s.yml new file mode 100644 index 0000000..843f3eb --- /dev/null +++ b/challenges/web/where-robots-cannot-search/k8s/config/templates/k8s.yml @@ -0,0 +1,63 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: "challenge-web-where-robots-cannot-search" + labels: + challenges.ctfpilot.com/type: "web" + challenges.ctfpilot.com/name: "where-robots-cannot-search" + challenges.ctfpilot.com/category: "web" + challenges.ctfpilot.com/version: "2" + challenges.ctfpilot.com/configmap: "challenge-config" + challenges.ctfpilot.com/enabled: "true" + ctfpilot.com/component: "challenge-config" +data: + name: "where-robots-cannot-search" + path: "challenges/web/where-robots-cannot-search" + repository: "ctfpilot/challenges-example" + generated_at: "2025-12-20 12:02:08" + challenge: | + { + "$schema": "https://raw.githubusercontent.com/ctfpilot/challenge-schema/refs/heads/main/schema.json", + "enabled": true, + "name": "Where robots cannot search", + "slug": "where-robots-cannot-search", + "author": "The Mikkel", + "category": "web", + "difficulty": "beginner", + "tags": [ + "BrunnerCTF 2025" + ], + "type": "instanced", + "instanced_type": "web", + "instanced_name": null, + "instanced_subdomains": [], + "connection": null, + "flag": [ + { + "flag": "ctfpilot{r0bot5_sh0u1d_nOt_637_h3re_b0t_You_g07_h3re}", + "case_sensitive": false + } + ], + "points": 1000, + "decay": 75, + "min_points": 100, + "description_location": "description.md", + "handout_dir": "handout", + "dockerfile_locations": [ + { + "location": "src/Dockerfile", + "context": "src/", + "identifier": null + } + ] + } + + description: | + # Where robots cannot search + + **Difficulty:** Beginner + **Author:** The Mikkel + + Ahh, the Brunnerne company. + But they have a secret, hidden away from robot search. + diff --git a/challenges/web/where-robots-cannot-search/k8s/config/values.yaml b/challenges/web/where-robots-cannot-search/k8s/config/values.yaml new file mode 100644 index 0000000..8d8c4e6 --- /dev/null +++ b/challenges/web/where-robots-cannot-search/k8s/config/values.yaml @@ -0,0 +1,11 @@ +challenge: + enabled: true + name: where-robots-cannot-search + category: web + type: web + version: 2 + path: challenges/web/where-robots-cannot-search +kubectf: + expires: 3600 + availableAt: 0 + host: example.com diff --git a/challenges/web/where-robots-cannot-search/k8s/files/.gitkeep b/challenges/web/where-robots-cannot-search/k8s/files/.gitkeep index 4fd76bb..ef3682f 100644 --- a/challenges/web/where-robots-cannot-search/k8s/files/.gitkeep +++ b/challenges/web/where-robots-cannot-search/k8s/files/.gitkeep @@ -1,2 +1 @@ -# This file is used to keep the directory in the repository. -# This directory is used to store files that are handed out, for the challenge. Use the handout directory for files that are handed out to users and want to be packaged as a zip file. \ No newline at end of file +# This file is to keep the directory in git. diff --git a/challenges/web/where-robots-cannot-search/version b/challenges/web/where-robots-cannot-search/version index 56a6051..d8263ee 100644 --- a/challenges/web/where-robots-cannot-search/version +++ b/challenges/web/where-robots-cannot-search/version @@ -1 +1 @@ -1 \ No newline at end of file +2 \ No newline at end of file From f8102f05b6486911b5ca4fba6ae4bb37a8ff7b0c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 20 Dec 2025 12:03:44 +0000 Subject: [PATCH 09/30] CI: Update challenges [skip ci] --- .../web/where-robots-cannot-search/k8s/challenge/k8s.yml | 2 +- .../web/where-robots-cannot-search/k8s/config/Chart.yaml | 4 ++-- .../where-robots-cannot-search/k8s/config/templates/k8s.yml | 4 ++-- .../web/where-robots-cannot-search/k8s/config/values.yaml | 2 +- challenges/web/where-robots-cannot-search/version | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/challenges/web/where-robots-cannot-search/k8s/challenge/k8s.yml b/challenges/web/where-robots-cannot-search/k8s/challenge/k8s.yml index 5f0578e..416e523 100644 --- a/challenges/web/where-robots-cannot-search/k8s/challenge/k8s.yml +++ b/challenges/web/where-robots-cannot-search/k8s/challenge/k8s.yml @@ -67,7 +67,7 @@ spec: - scaler containers: - name: web - image: ghcr.io/ctfpilot/challenges-example-web-where-robots-cannot-search:2 + image: ghcr.io/ctfpilot/challenges-example-web-where-robots-cannot-search:3 imagePullPolicy: IfNotPresent resources: limits: diff --git a/challenges/web/where-robots-cannot-search/k8s/config/Chart.yaml b/challenges/web/where-robots-cannot-search/k8s/config/Chart.yaml index cf0aa6b..005f5e5 100644 --- a/challenges/web/where-robots-cannot-search/k8s/config/Chart.yaml +++ b/challenges/web/where-robots-cannot-search/k8s/config/Chart.yaml @@ -1,6 +1,6 @@ apiVersion: v2 name: configmap-where-robots-cannot-search -version: 1.2.0 +version: 1.3.0 description: Challenge configmap for where-robots-cannot-search in category web -appVersion: "1.2.0" +appVersion: "1.3.0" type: application diff --git a/challenges/web/where-robots-cannot-search/k8s/config/templates/k8s.yml b/challenges/web/where-robots-cannot-search/k8s/config/templates/k8s.yml index 843f3eb..8db0306 100644 --- a/challenges/web/where-robots-cannot-search/k8s/config/templates/k8s.yml +++ b/challenges/web/where-robots-cannot-search/k8s/config/templates/k8s.yml @@ -6,7 +6,7 @@ metadata: challenges.ctfpilot.com/type: "web" challenges.ctfpilot.com/name: "where-robots-cannot-search" challenges.ctfpilot.com/category: "web" - challenges.ctfpilot.com/version: "2" + challenges.ctfpilot.com/version: "3" challenges.ctfpilot.com/configmap: "challenge-config" challenges.ctfpilot.com/enabled: "true" ctfpilot.com/component: "challenge-config" @@ -14,7 +14,7 @@ data: name: "where-robots-cannot-search" path: "challenges/web/where-robots-cannot-search" repository: "ctfpilot/challenges-example" - generated_at: "2025-12-20 12:02:08" + generated_at: "2025-12-20 12:03:44" challenge: | { "$schema": "https://raw.githubusercontent.com/ctfpilot/challenge-schema/refs/heads/main/schema.json", diff --git a/challenges/web/where-robots-cannot-search/k8s/config/values.yaml b/challenges/web/where-robots-cannot-search/k8s/config/values.yaml index 8d8c4e6..9b6bcae 100644 --- a/challenges/web/where-robots-cannot-search/k8s/config/values.yaml +++ b/challenges/web/where-robots-cannot-search/k8s/config/values.yaml @@ -3,7 +3,7 @@ challenge: name: where-robots-cannot-search category: web type: web - version: 2 + version: 3 path: challenges/web/where-robots-cannot-search kubectf: expires: 3600 diff --git a/challenges/web/where-robots-cannot-search/version b/challenges/web/where-robots-cannot-search/version index d8263ee..e440e5c 100644 --- a/challenges/web/where-robots-cannot-search/version +++ b/challenges/web/where-robots-cannot-search/version @@ -1 +1 @@ -2 \ No newline at end of file +3 \ No newline at end of file From d2e8b2fa821805c50c5d7e86b5b2eca850b3eed4 Mon Sep 17 00:00:00 2001 From: The0mikkel <28625667+The0mikkel@users.noreply.github.com> Date: Sat, 20 Dec 2025 12:04:50 +0000 Subject: [PATCH 10/30] Create challenge: Oh look, A flag! by The Mikkel --- challenges/forensics/oh-look-a-flag/README.md | 4 ++++ .../forensics/oh-look-a-flag/challenge.yml | 23 +++++++++++++++++++ .../forensics/oh-look-a-flag/description.md | 6 +++++ .../forensics/oh-look-a-flag/handout/.gitkeep | 2 ++ .../oh-look-a-flag/k8s/files/.gitkeep | 2 ++ .../oh-look-a-flag/solution/README.md | 3 +++ .../forensics/oh-look-a-flag/src/.gitkeep | 2 ++ challenges/forensics/oh-look-a-flag/version | 1 + 8 files changed, 43 insertions(+) create mode 100644 challenges/forensics/oh-look-a-flag/README.md create mode 100644 challenges/forensics/oh-look-a-flag/challenge.yml create mode 100644 challenges/forensics/oh-look-a-flag/description.md create mode 100644 challenges/forensics/oh-look-a-flag/handout/.gitkeep create mode 100644 challenges/forensics/oh-look-a-flag/k8s/files/.gitkeep create mode 100644 challenges/forensics/oh-look-a-flag/solution/README.md create mode 100644 challenges/forensics/oh-look-a-flag/src/.gitkeep create mode 100644 challenges/forensics/oh-look-a-flag/version diff --git a/challenges/forensics/oh-look-a-flag/README.md b/challenges/forensics/oh-look-a-flag/README.md new file mode 100644 index 0000000..771d0a8 --- /dev/null +++ b/challenges/forensics/oh-look-a-flag/README.md @@ -0,0 +1,4 @@ +# Oh look, A flag! + +*Add information about challenge here* +*It is meant to contain internal documentation of the challenge, such as how it is solved* diff --git a/challenges/forensics/oh-look-a-flag/challenge.yml b/challenges/forensics/oh-look-a-flag/challenge.yml new file mode 100644 index 0000000..9673bd6 --- /dev/null +++ b/challenges/forensics/oh-look-a-flag/challenge.yml @@ -0,0 +1,23 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/ctfpilot/challenge-schema/refs/heads/main/schema.json + +enabled: true +name: Oh look, A flag! +slug: oh-look-a-flag +author: The Mikkel +category: forensics +difficulty: beginner +tags: [] +type: static +instanced_type: none +instanced_name: null +instanced_subdomains: [] +connection: null +flag: +- flag: ctfpilot{handouts-may-contain-flag} + case_sensitive: false +points: 1000 +decay: 75 +min_points: 100 +description_location: description.md +handout_dir: handout + diff --git a/challenges/forensics/oh-look-a-flag/description.md b/challenges/forensics/oh-look-a-flag/description.md new file mode 100644 index 0000000..6ac1aaa --- /dev/null +++ b/challenges/forensics/oh-look-a-flag/description.md @@ -0,0 +1,6 @@ +# Oh look, A flag! + +**Difficulty:** Beginner +**Author:** The Mikkel + +*Add challenge description here* diff --git a/challenges/forensics/oh-look-a-flag/handout/.gitkeep b/challenges/forensics/oh-look-a-flag/handout/.gitkeep new file mode 100644 index 0000000..0f065bc --- /dev/null +++ b/challenges/forensics/oh-look-a-flag/handout/.gitkeep @@ -0,0 +1,2 @@ +# This file is used to keep the directory in the repository. +# This directory is used to store files that are handed out, for the challenge. The files are automatically zipped and copied to the files directory. \ No newline at end of file diff --git a/challenges/forensics/oh-look-a-flag/k8s/files/.gitkeep b/challenges/forensics/oh-look-a-flag/k8s/files/.gitkeep new file mode 100644 index 0000000..4fd76bb --- /dev/null +++ b/challenges/forensics/oh-look-a-flag/k8s/files/.gitkeep @@ -0,0 +1,2 @@ +# This file is used to keep the directory in the repository. +# This directory is used to store files that are handed out, for the challenge. Use the handout directory for files that are handed out to users and want to be packaged as a zip file. \ No newline at end of file diff --git a/challenges/forensics/oh-look-a-flag/solution/README.md b/challenges/forensics/oh-look-a-flag/solution/README.md new file mode 100644 index 0000000..8614e07 --- /dev/null +++ b/challenges/forensics/oh-look-a-flag/solution/README.md @@ -0,0 +1,3 @@ +# Solution +This directory is used to store the solution script for the challenge. +This file should contain the steps to solve the challenge. \ No newline at end of file diff --git a/challenges/forensics/oh-look-a-flag/src/.gitkeep b/challenges/forensics/oh-look-a-flag/src/.gitkeep new file mode 100644 index 0000000..76376a2 --- /dev/null +++ b/challenges/forensics/oh-look-a-flag/src/.gitkeep @@ -0,0 +1,2 @@ +# This file is used to keep the directory in the repository. +# This directory is used to store source files for the challenge. \ No newline at end of file diff --git a/challenges/forensics/oh-look-a-flag/version b/challenges/forensics/oh-look-a-flag/version new file mode 100644 index 0000000..56a6051 --- /dev/null +++ b/challenges/forensics/oh-look-a-flag/version @@ -0,0 +1 @@ +1 \ No newline at end of file From df5d5e47f3657eb50b6d64a1e960d44ca1771f49 Mon Sep 17 00:00:00 2001 From: The0Mikkel Date: Sat, 20 Dec 2025 13:37:52 +0100 Subject: [PATCH 11/30] docs: Add project board section to README for tracking challenge progress --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index 89ffb70..f65b353 100644 --- a/README.md +++ b/README.md @@ -205,3 +205,8 @@ To create a new challenge, follow these steps: 7. Once the workflow is complete, a new branch, pull request, and issue will be created for the challenge. If errors occur during the workflow execution, please reach out to the infrastructure team for assistance. Logs from the workflow can be found in the `Actions` tab of the repository. + +## Project board + +A project board is available to track the progress of challenges. +This can be found at: [Challenges Project board](https://github.com/orgs/ctfpilot/projects/2) From 3784b15464f440f5e56019d142210002e4cad8c1 Mon Sep 17 00:00:00 2001 From: The0Mikkel Date: Sat, 20 Dec 2025 13:50:13 +0100 Subject: [PATCH 12/30] docs: Update README with important usage information for the challenge repository template --- README.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index f65b353..32ee6c8 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,12 @@ # Challenges example repository -This repository contains an example challenges repository, for CTF Pilot's Challenge Repository Template +> [!IMPORTANT] +> This is an example repository of the [CTF Pilot's Challenge Repository Template](https://github.com/ctfpilot/challenges-template). +> It is intended to be used as a reference for creating your own challenges repository, and testing the infrastructure with some example challenges. +> +> **Please use the [Challenge Repository Template](https://github.com/ctfpilot/challenges-template) if you want to create your own challenges repository.** + +This repository contains an example challenges repository, for [CTF Pilot's Challenge Repository Template](https://github.com/ctfpilot/challenges-template). ## Challenge toolkit From 748d726fe526f87846a42eae783ffba3066e111f Mon Sep 17 00:00:00 2001 From: The0Mikkel Date: Sat, 20 Dec 2025 13:53:34 +0100 Subject: [PATCH 13/30] Update challenge documentation and add handout file for "Oh look, A flag!" challenge --- challenges/forensics/oh-look-a-flag/README.md | 6 ++++-- challenges/forensics/oh-look-a-flag/description.md | 2 +- challenges/forensics/oh-look-a-flag/handout/handout.txt | 2 ++ challenges/forensics/oh-look-a-flag/solution/README.md | 4 ++-- 4 files changed, 9 insertions(+), 5 deletions(-) create mode 100644 challenges/forensics/oh-look-a-flag/handout/handout.txt diff --git a/challenges/forensics/oh-look-a-flag/README.md b/challenges/forensics/oh-look-a-flag/README.md index 771d0a8..1801b93 100644 --- a/challenges/forensics/oh-look-a-flag/README.md +++ b/challenges/forensics/oh-look-a-flag/README.md @@ -1,4 +1,6 @@ # Oh look, A flag! -*Add information about challenge here* -*It is meant to contain internal documentation of the challenge, such as how it is solved* +This challenge is an example challenge for testing the handout system. + +It contains a single text file, which contains a flag. +In the infrastructure, this file should be automatically zipped into a handout file, and uploaded to the platform. diff --git a/challenges/forensics/oh-look-a-flag/description.md b/challenges/forensics/oh-look-a-flag/description.md index 6ac1aaa..cfcf6ef 100644 --- a/challenges/forensics/oh-look-a-flag/description.md +++ b/challenges/forensics/oh-look-a-flag/description.md @@ -3,4 +3,4 @@ **Difficulty:** Beginner **Author:** The Mikkel -*Add challenge description here* +Handouts may contain flags, but does this one? diff --git a/challenges/forensics/oh-look-a-flag/handout/handout.txt b/challenges/forensics/oh-look-a-flag/handout/handout.txt new file mode 100644 index 0000000..ede38af --- /dev/null +++ b/challenges/forensics/oh-look-a-flag/handout/handout.txt @@ -0,0 +1,2 @@ +Alright, here is the flag: +ctfpilot{handouts-may-contain-flag} diff --git a/challenges/forensics/oh-look-a-flag/solution/README.md b/challenges/forensics/oh-look-a-flag/solution/README.md index 8614e07..b860944 100644 --- a/challenges/forensics/oh-look-a-flag/solution/README.md +++ b/challenges/forensics/oh-look-a-flag/solution/README.md @@ -1,3 +1,3 @@ # Solution -This directory is used to store the solution script for the challenge. -This file should contain the steps to solve the challenge. \ No newline at end of file + +Download the handout file and extract it. Inside, you will find a text file containing the flag. From 57ec6e327ce1001b5522b8b0084aac712b9a08de Mon Sep 17 00:00:00 2001 From: The0Mikkel Date: Sat, 20 Dec 2025 13:55:02 +0100 Subject: [PATCH 14/30] docs: Enhance README with detailed challenge description and context --- .../web/where-robots-cannot-search/README.md | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/challenges/web/where-robots-cannot-search/README.md b/challenges/web/where-robots-cannot-search/README.md index efc04ff..0024c3a 100644 --- a/challenges/web/where-robots-cannot-search/README.md +++ b/challenges/web/where-robots-cannot-search/README.md @@ -1,4 +1,14 @@ # Where robots cannot search -*Add information about challenge here* -*It is meant to contain internal documentation of the challenge, such as how it is solved* +A challenge based on the notion of robots.txt, and how it should never be used to hide sensitive information. + +The challenge name refers to robots (web scrapers) that are not allowed to search for certain files on a website, therefore giving the hint that the flag is located in a file that is disallowed in the robots.txt file. + +## Challenge + +A website is given, which contains a robots.txt file, in this file one or more directories and files are disallowed. +However, one of them is called `flag.txt`, which contains the flag. + +## Story + +To fit the Brunnerne story, the website is a simple landing page for the `Brunnerne company`. From 3c1b2c935fd8428a0c433b098621d7fbf28cc776 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 20 Dec 2025 12:56:04 +0000 Subject: [PATCH 15/30] CI: Update challenges [skip ci] --- .../web/where-robots-cannot-search/k8s/challenge/k8s.yml | 2 +- .../web/where-robots-cannot-search/k8s/config/Chart.yaml | 4 ++-- .../where-robots-cannot-search/k8s/config/templates/k8s.yml | 4 ++-- .../web/where-robots-cannot-search/k8s/config/values.yaml | 2 +- challenges/web/where-robots-cannot-search/version | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/challenges/web/where-robots-cannot-search/k8s/challenge/k8s.yml b/challenges/web/where-robots-cannot-search/k8s/challenge/k8s.yml index 416e523..af3a5f6 100644 --- a/challenges/web/where-robots-cannot-search/k8s/challenge/k8s.yml +++ b/challenges/web/where-robots-cannot-search/k8s/challenge/k8s.yml @@ -67,7 +67,7 @@ spec: - scaler containers: - name: web - image: ghcr.io/ctfpilot/challenges-example-web-where-robots-cannot-search:3 + image: ghcr.io/ctfpilot/challenges-example-web-where-robots-cannot-search:4 imagePullPolicy: IfNotPresent resources: limits: diff --git a/challenges/web/where-robots-cannot-search/k8s/config/Chart.yaml b/challenges/web/where-robots-cannot-search/k8s/config/Chart.yaml index 005f5e5..cb80b41 100644 --- a/challenges/web/where-robots-cannot-search/k8s/config/Chart.yaml +++ b/challenges/web/where-robots-cannot-search/k8s/config/Chart.yaml @@ -1,6 +1,6 @@ apiVersion: v2 name: configmap-where-robots-cannot-search -version: 1.3.0 +version: 1.4.0 description: Challenge configmap for where-robots-cannot-search in category web -appVersion: "1.3.0" +appVersion: "1.4.0" type: application diff --git a/challenges/web/where-robots-cannot-search/k8s/config/templates/k8s.yml b/challenges/web/where-robots-cannot-search/k8s/config/templates/k8s.yml index 8db0306..d0a2ded 100644 --- a/challenges/web/where-robots-cannot-search/k8s/config/templates/k8s.yml +++ b/challenges/web/where-robots-cannot-search/k8s/config/templates/k8s.yml @@ -6,7 +6,7 @@ metadata: challenges.ctfpilot.com/type: "web" challenges.ctfpilot.com/name: "where-robots-cannot-search" challenges.ctfpilot.com/category: "web" - challenges.ctfpilot.com/version: "3" + challenges.ctfpilot.com/version: "4" challenges.ctfpilot.com/configmap: "challenge-config" challenges.ctfpilot.com/enabled: "true" ctfpilot.com/component: "challenge-config" @@ -14,7 +14,7 @@ data: name: "where-robots-cannot-search" path: "challenges/web/where-robots-cannot-search" repository: "ctfpilot/challenges-example" - generated_at: "2025-12-20 12:03:44" + generated_at: "2025-12-20 12:56:04" challenge: | { "$schema": "https://raw.githubusercontent.com/ctfpilot/challenge-schema/refs/heads/main/schema.json", diff --git a/challenges/web/where-robots-cannot-search/k8s/config/values.yaml b/challenges/web/where-robots-cannot-search/k8s/config/values.yaml index 9b6bcae..e464e11 100644 --- a/challenges/web/where-robots-cannot-search/k8s/config/values.yaml +++ b/challenges/web/where-robots-cannot-search/k8s/config/values.yaml @@ -3,7 +3,7 @@ challenge: name: where-robots-cannot-search category: web type: web - version: 3 + version: 4 path: challenges/web/where-robots-cannot-search kubectf: expires: 3600 diff --git a/challenges/web/where-robots-cannot-search/version b/challenges/web/where-robots-cannot-search/version index e440e5c..bf0d87a 100644 --- a/challenges/web/where-robots-cannot-search/version +++ b/challenges/web/where-robots-cannot-search/version @@ -1 +1 @@ -3 \ No newline at end of file +4 \ No newline at end of file From 4d7a20e25c9da38be3bfc4f1272f88eb0082e86d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 20 Dec 2025 12:59:17 +0000 Subject: [PATCH 16/30] CI: Update challenges [skip ci] --- .../web/where-robots-cannot-search/k8s/challenge/k8s.yml | 2 +- .../web/where-robots-cannot-search/k8s/config/Chart.yaml | 4 ++-- .../where-robots-cannot-search/k8s/config/templates/k8s.yml | 4 ++-- .../web/where-robots-cannot-search/k8s/config/values.yaml | 2 +- challenges/web/where-robots-cannot-search/version | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/challenges/web/where-robots-cannot-search/k8s/challenge/k8s.yml b/challenges/web/where-robots-cannot-search/k8s/challenge/k8s.yml index af3a5f6..879386e 100644 --- a/challenges/web/where-robots-cannot-search/k8s/challenge/k8s.yml +++ b/challenges/web/where-robots-cannot-search/k8s/challenge/k8s.yml @@ -67,7 +67,7 @@ spec: - scaler containers: - name: web - image: ghcr.io/ctfpilot/challenges-example-web-where-robots-cannot-search:4 + image: ghcr.io/ctfpilot/challenges-example-web-where-robots-cannot-search:5 imagePullPolicy: IfNotPresent resources: limits: diff --git a/challenges/web/where-robots-cannot-search/k8s/config/Chart.yaml b/challenges/web/where-robots-cannot-search/k8s/config/Chart.yaml index cb80b41..ddda4e8 100644 --- a/challenges/web/where-robots-cannot-search/k8s/config/Chart.yaml +++ b/challenges/web/where-robots-cannot-search/k8s/config/Chart.yaml @@ -1,6 +1,6 @@ apiVersion: v2 name: configmap-where-robots-cannot-search -version: 1.4.0 +version: 1.5.0 description: Challenge configmap for where-robots-cannot-search in category web -appVersion: "1.4.0" +appVersion: "1.5.0" type: application diff --git a/challenges/web/where-robots-cannot-search/k8s/config/templates/k8s.yml b/challenges/web/where-robots-cannot-search/k8s/config/templates/k8s.yml index d0a2ded..8ae98f1 100644 --- a/challenges/web/where-robots-cannot-search/k8s/config/templates/k8s.yml +++ b/challenges/web/where-robots-cannot-search/k8s/config/templates/k8s.yml @@ -6,7 +6,7 @@ metadata: challenges.ctfpilot.com/type: "web" challenges.ctfpilot.com/name: "where-robots-cannot-search" challenges.ctfpilot.com/category: "web" - challenges.ctfpilot.com/version: "4" + challenges.ctfpilot.com/version: "5" challenges.ctfpilot.com/configmap: "challenge-config" challenges.ctfpilot.com/enabled: "true" ctfpilot.com/component: "challenge-config" @@ -14,7 +14,7 @@ data: name: "where-robots-cannot-search" path: "challenges/web/where-robots-cannot-search" repository: "ctfpilot/challenges-example" - generated_at: "2025-12-20 12:56:04" + generated_at: "2025-12-20 12:59:17" challenge: | { "$schema": "https://raw.githubusercontent.com/ctfpilot/challenge-schema/refs/heads/main/schema.json", diff --git a/challenges/web/where-robots-cannot-search/k8s/config/values.yaml b/challenges/web/where-robots-cannot-search/k8s/config/values.yaml index e464e11..652125d 100644 --- a/challenges/web/where-robots-cannot-search/k8s/config/values.yaml +++ b/challenges/web/where-robots-cannot-search/k8s/config/values.yaml @@ -3,7 +3,7 @@ challenge: name: where-robots-cannot-search category: web type: web - version: 4 + version: 5 path: challenges/web/where-robots-cannot-search kubectf: expires: 3600 diff --git a/challenges/web/where-robots-cannot-search/version b/challenges/web/where-robots-cannot-search/version index bf0d87a..7813681 100644 --- a/challenges/web/where-robots-cannot-search/version +++ b/challenges/web/where-robots-cannot-search/version @@ -1 +1 @@ -4 \ No newline at end of file +5 \ No newline at end of file From f9389770b0dcc712f104e6b64d5f2834d2d2a7c2 Mon Sep 17 00:00:00 2001 From: The0Mikkel Date: Sat, 20 Dec 2025 14:01:32 +0100 Subject: [PATCH 17/30] Trigger rebuild of oh-look-a-flag --- challenges/forensics/oh-look-a-flag/version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/challenges/forensics/oh-look-a-flag/version b/challenges/forensics/oh-look-a-flag/version index 56a6051..d8263ee 100644 --- a/challenges/forensics/oh-look-a-flag/version +++ b/challenges/forensics/oh-look-a-flag/version @@ -1 +1 @@ -1 \ No newline at end of file +2 \ No newline at end of file From 72f0d86b1dded81afb29137f1246843c7c87e901 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 20 Dec 2025 13:02:20 +0000 Subject: [PATCH 18/30] CI: Update challenges [skip ci] --- .../oh-look-a-flag/k8s/config/Chart.yaml | 6 ++ .../k8s/config/templates/k8s.yml | 53 ++++++++++++++++++ .../oh-look-a-flag/k8s/config/values.yaml | 11 ++++ .../oh-look-a-flag/k8s/files/.gitkeep | 3 +- .../k8s/files/forensics_oh-look-a-flag.zip | Bin 0 -> 359 bytes challenges/forensics/oh-look-a-flag/version | 2 +- 6 files changed, 72 insertions(+), 3 deletions(-) create mode 100644 challenges/forensics/oh-look-a-flag/k8s/config/Chart.yaml create mode 100644 challenges/forensics/oh-look-a-flag/k8s/config/templates/k8s.yml create mode 100644 challenges/forensics/oh-look-a-flag/k8s/config/values.yaml create mode 100644 challenges/forensics/oh-look-a-flag/k8s/files/forensics_oh-look-a-flag.zip diff --git a/challenges/forensics/oh-look-a-flag/k8s/config/Chart.yaml b/challenges/forensics/oh-look-a-flag/k8s/config/Chart.yaml new file mode 100644 index 0000000..a00949f --- /dev/null +++ b/challenges/forensics/oh-look-a-flag/k8s/config/Chart.yaml @@ -0,0 +1,6 @@ +apiVersion: v2 +name: configmap-oh-look-a-flag +version: 1.3.0 +description: Challenge configmap for oh-look-a-flag in category forensics +appVersion: "1.3.0" +type: application diff --git a/challenges/forensics/oh-look-a-flag/k8s/config/templates/k8s.yml b/challenges/forensics/oh-look-a-flag/k8s/config/templates/k8s.yml new file mode 100644 index 0000000..8659be2 --- /dev/null +++ b/challenges/forensics/oh-look-a-flag/k8s/config/templates/k8s.yml @@ -0,0 +1,53 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: "challenge-forensics-oh-look-a-flag" + labels: + challenges.ctfpilot.com/type: "none" + challenges.ctfpilot.com/name: "oh-look-a-flag" + challenges.ctfpilot.com/category: "forensics" + challenges.ctfpilot.com/version: "3" + challenges.ctfpilot.com/configmap: "challenge-config" + challenges.ctfpilot.com/enabled: "true" + ctfpilot.com/component: "challenge-config" +data: + name: "oh-look-a-flag" + path: "challenges/forensics/oh-look-a-flag" + repository: "ctfpilot/challenges-example" + generated_at: "2025-12-20 13:02:20" + challenge: | + { + "$schema": "https://raw.githubusercontent.com/ctfpilot/challenge-schema/refs/heads/main/schema.json", + "enabled": true, + "name": "Oh look, A flag!", + "slug": "oh-look-a-flag", + "author": "The Mikkel", + "category": "forensics", + "difficulty": "beginner", + "tags": [], + "type": "static", + "instanced_type": "none", + "instanced_name": null, + "instanced_subdomains": [], + "connection": null, + "flag": [ + { + "flag": "ctfpilot{handouts-may-contain-flag}", + "case_sensitive": false + } + ], + "points": 1000, + "decay": 75, + "min_points": 100, + "description_location": "description.md", + "handout_dir": "handout" + } + + description: | + # Oh look, A flag! + + **Difficulty:** Beginner + **Author:** The Mikkel + + Handouts may contain flags, but does this one? + diff --git a/challenges/forensics/oh-look-a-flag/k8s/config/values.yaml b/challenges/forensics/oh-look-a-flag/k8s/config/values.yaml new file mode 100644 index 0000000..4707b0c --- /dev/null +++ b/challenges/forensics/oh-look-a-flag/k8s/config/values.yaml @@ -0,0 +1,11 @@ +challenge: + enabled: true + name: oh-look-a-flag + category: forensics + type: none + version: 3 + path: challenges/forensics/oh-look-a-flag +kubectf: + expires: 3600 + availableAt: 0 + host: example.com diff --git a/challenges/forensics/oh-look-a-flag/k8s/files/.gitkeep b/challenges/forensics/oh-look-a-flag/k8s/files/.gitkeep index 4fd76bb..ef3682f 100644 --- a/challenges/forensics/oh-look-a-flag/k8s/files/.gitkeep +++ b/challenges/forensics/oh-look-a-flag/k8s/files/.gitkeep @@ -1,2 +1 @@ -# This file is used to keep the directory in the repository. -# This directory is used to store files that are handed out, for the challenge. Use the handout directory for files that are handed out to users and want to be packaged as a zip file. \ No newline at end of file +# This file is to keep the directory in git. diff --git a/challenges/forensics/oh-look-a-flag/k8s/files/forensics_oh-look-a-flag.zip b/challenges/forensics/oh-look-a-flag/k8s/files/forensics_oh-look-a-flag.zip new file mode 100644 index 0000000000000000000000000000000000000000..f65b99600d71bbc166f788fec1a43d55f5f06ca4 GIT binary patch literal 359 zcmWIWW@Zs#00FOzDbZjCl#m3{Y57H|dBvH@#qs$Wx;gpz*}93kX*r4M`TUCnD}eb-#^J$GK)^URsctSeVOWnu{MW@Hj!#_e*TD}X?N s;jJTx#^Vo|G1z?q(hLGi8qI+uPGgY#72wUv2GYR Date: Sat, 20 Dec 2025 13:03:33 +0000 Subject: [PATCH 19/30] CI: Update challenges [skip ci] --- .../oh-look-a-flag/k8s/config/Chart.yaml | 4 ++-- .../oh-look-a-flag/k8s/config/templates/k8s.yml | 4 ++-- .../oh-look-a-flag/k8s/config/values.yaml | 2 +- .../k8s/files/forensics_oh-look-a-flag.zip | Bin 359 -> 359 bytes challenges/forensics/oh-look-a-flag/version | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/challenges/forensics/oh-look-a-flag/k8s/config/Chart.yaml b/challenges/forensics/oh-look-a-flag/k8s/config/Chart.yaml index a00949f..ea47587 100644 --- a/challenges/forensics/oh-look-a-flag/k8s/config/Chart.yaml +++ b/challenges/forensics/oh-look-a-flag/k8s/config/Chart.yaml @@ -1,6 +1,6 @@ apiVersion: v2 name: configmap-oh-look-a-flag -version: 1.3.0 +version: 1.4.0 description: Challenge configmap for oh-look-a-flag in category forensics -appVersion: "1.3.0" +appVersion: "1.4.0" type: application diff --git a/challenges/forensics/oh-look-a-flag/k8s/config/templates/k8s.yml b/challenges/forensics/oh-look-a-flag/k8s/config/templates/k8s.yml index 8659be2..dc50c94 100644 --- a/challenges/forensics/oh-look-a-flag/k8s/config/templates/k8s.yml +++ b/challenges/forensics/oh-look-a-flag/k8s/config/templates/k8s.yml @@ -6,7 +6,7 @@ metadata: challenges.ctfpilot.com/type: "none" challenges.ctfpilot.com/name: "oh-look-a-flag" challenges.ctfpilot.com/category: "forensics" - challenges.ctfpilot.com/version: "3" + challenges.ctfpilot.com/version: "4" challenges.ctfpilot.com/configmap: "challenge-config" challenges.ctfpilot.com/enabled: "true" ctfpilot.com/component: "challenge-config" @@ -14,7 +14,7 @@ data: name: "oh-look-a-flag" path: "challenges/forensics/oh-look-a-flag" repository: "ctfpilot/challenges-example" - generated_at: "2025-12-20 13:02:20" + generated_at: "2025-12-20 13:03:33" challenge: | { "$schema": "https://raw.githubusercontent.com/ctfpilot/challenge-schema/refs/heads/main/schema.json", diff --git a/challenges/forensics/oh-look-a-flag/k8s/config/values.yaml b/challenges/forensics/oh-look-a-flag/k8s/config/values.yaml index 4707b0c..173af03 100644 --- a/challenges/forensics/oh-look-a-flag/k8s/config/values.yaml +++ b/challenges/forensics/oh-look-a-flag/k8s/config/values.yaml @@ -3,7 +3,7 @@ challenge: name: oh-look-a-flag category: forensics type: none - version: 3 + version: 4 path: challenges/forensics/oh-look-a-flag kubectf: expires: 3600 diff --git a/challenges/forensics/oh-look-a-flag/k8s/files/forensics_oh-look-a-flag.zip b/challenges/forensics/oh-look-a-flag/k8s/files/forensics_oh-look-a-flag.zip index f65b99600d71bbc166f788fec1a43d55f5f06ca4..2f390dfea79eeb9c79a104c87fd060c29d59d490 100644 GIT binary patch delta 35 ocmaFP^qh%1z?+#xgaHH!CUToGCQo!~Vl0?=)QvHDG7n=k0GV?L`v3p{ delta 35 ocmaFP^qh%1z?+#xgaHJ+CUToGT2FLpV)UAL)Q!=4G7n=k0FmDaUjP6A diff --git a/challenges/forensics/oh-look-a-flag/version b/challenges/forensics/oh-look-a-flag/version index e440e5c..bf0d87a 100644 --- a/challenges/forensics/oh-look-a-flag/version +++ b/challenges/forensics/oh-look-a-flag/version @@ -1 +1 @@ -3 \ No newline at end of file +4 \ No newline at end of file From 546ba5b60d6729c620da5b8ce0812778fb2e5c4d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 20 Dec 2025 13:03:34 +0000 Subject: [PATCH 20/30] CI: Update challenges [skip ci] --- .../web/where-robots-cannot-search/k8s/challenge/k8s.yml | 2 +- .../web/where-robots-cannot-search/k8s/config/Chart.yaml | 4 ++-- .../where-robots-cannot-search/k8s/config/templates/k8s.yml | 4 ++-- .../web/where-robots-cannot-search/k8s/config/values.yaml | 2 +- challenges/web/where-robots-cannot-search/version | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/challenges/web/where-robots-cannot-search/k8s/challenge/k8s.yml b/challenges/web/where-robots-cannot-search/k8s/challenge/k8s.yml index 879386e..aa21f26 100644 --- a/challenges/web/where-robots-cannot-search/k8s/challenge/k8s.yml +++ b/challenges/web/where-robots-cannot-search/k8s/challenge/k8s.yml @@ -67,7 +67,7 @@ spec: - scaler containers: - name: web - image: ghcr.io/ctfpilot/challenges-example-web-where-robots-cannot-search:5 + image: ghcr.io/ctfpilot/challenges-example-web-where-robots-cannot-search:6 imagePullPolicy: IfNotPresent resources: limits: diff --git a/challenges/web/where-robots-cannot-search/k8s/config/Chart.yaml b/challenges/web/where-robots-cannot-search/k8s/config/Chart.yaml index ddda4e8..3b76e1c 100644 --- a/challenges/web/where-robots-cannot-search/k8s/config/Chart.yaml +++ b/challenges/web/where-robots-cannot-search/k8s/config/Chart.yaml @@ -1,6 +1,6 @@ apiVersion: v2 name: configmap-where-robots-cannot-search -version: 1.5.0 +version: 1.6.0 description: Challenge configmap for where-robots-cannot-search in category web -appVersion: "1.5.0" +appVersion: "1.6.0" type: application diff --git a/challenges/web/where-robots-cannot-search/k8s/config/templates/k8s.yml b/challenges/web/where-robots-cannot-search/k8s/config/templates/k8s.yml index 8ae98f1..a7f9f55 100644 --- a/challenges/web/where-robots-cannot-search/k8s/config/templates/k8s.yml +++ b/challenges/web/where-robots-cannot-search/k8s/config/templates/k8s.yml @@ -6,7 +6,7 @@ metadata: challenges.ctfpilot.com/type: "web" challenges.ctfpilot.com/name: "where-robots-cannot-search" challenges.ctfpilot.com/category: "web" - challenges.ctfpilot.com/version: "5" + challenges.ctfpilot.com/version: "6" challenges.ctfpilot.com/configmap: "challenge-config" challenges.ctfpilot.com/enabled: "true" ctfpilot.com/component: "challenge-config" @@ -14,7 +14,7 @@ data: name: "where-robots-cannot-search" path: "challenges/web/where-robots-cannot-search" repository: "ctfpilot/challenges-example" - generated_at: "2025-12-20 12:59:17" + generated_at: "2025-12-20 13:03:34" challenge: | { "$schema": "https://raw.githubusercontent.com/ctfpilot/challenge-schema/refs/heads/main/schema.json", diff --git a/challenges/web/where-robots-cannot-search/k8s/config/values.yaml b/challenges/web/where-robots-cannot-search/k8s/config/values.yaml index 652125d..55f6a78 100644 --- a/challenges/web/where-robots-cannot-search/k8s/config/values.yaml +++ b/challenges/web/where-robots-cannot-search/k8s/config/values.yaml @@ -3,7 +3,7 @@ challenge: name: where-robots-cannot-search category: web type: web - version: 5 + version: 6 path: challenges/web/where-robots-cannot-search kubectf: expires: 3600 diff --git a/challenges/web/where-robots-cannot-search/version b/challenges/web/where-robots-cannot-search/version index 7813681..62f9457 100644 --- a/challenges/web/where-robots-cannot-search/version +++ b/challenges/web/where-robots-cannot-search/version @@ -1 +1 @@ -5 \ No newline at end of file +6 \ No newline at end of file From eee95ac5d45287836c0b864d20e4f24177de6f4e Mon Sep 17 00:00:00 2001 From: The0Mikkel Date: Sat, 20 Dec 2025 14:03:56 +0100 Subject: [PATCH 21/30] Remove test/example challenge --- challenges/test/example/README.md | 4 -- challenges/test/example/challenge.yml | 23 -------- challenges/test/example/description.md | 6 --- challenges/test/example/handout/.gitkeep | 2 - challenges/test/example/k8s/config/Chart.yaml | 6 --- .../test/example/k8s/config/templates/k8s.yml | 53 ------------------- .../test/example/k8s/config/values.yaml | 11 ---- challenges/test/example/k8s/files/.gitkeep | 1 - challenges/test/example/solution/README.md | 3 -- challenges/test/example/src/.gitkeep | 2 - challenges/test/example/version | 1 - 11 files changed, 112 deletions(-) delete mode 100644 challenges/test/example/README.md delete mode 100644 challenges/test/example/challenge.yml delete mode 100644 challenges/test/example/description.md delete mode 100644 challenges/test/example/handout/.gitkeep delete mode 100644 challenges/test/example/k8s/config/Chart.yaml delete mode 100644 challenges/test/example/k8s/config/templates/k8s.yml delete mode 100644 challenges/test/example/k8s/config/values.yaml delete mode 100644 challenges/test/example/k8s/files/.gitkeep delete mode 100644 challenges/test/example/solution/README.md delete mode 100644 challenges/test/example/src/.gitkeep delete mode 100644 challenges/test/example/version diff --git a/challenges/test/example/README.md b/challenges/test/example/README.md deleted file mode 100644 index 8a2278f..0000000 --- a/challenges/test/example/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# Example - -*Add information about challenge here* -*It is meant to contain internal documentation of the challenge, such as how it is solved* diff --git a/challenges/test/example/challenge.yml b/challenges/test/example/challenge.yml deleted file mode 100644 index bd58f01..0000000 --- a/challenges/test/example/challenge.yml +++ /dev/null @@ -1,23 +0,0 @@ -# yaml-language-server: $schema=https://raw.githubusercontent.com/ctfpilot/challenge-schema/refs/heads/main/schema.json - -enabled: true -name: Example -slug: example -author: The Mikkel -category: test -difficulty: easy -tags: [] -type: static -instanced_type: none -instanced_name: null -instanced_subdomains: [] -connection: null -flag: -- flag: test{demo} - case_sensitive: false -points: 1000 -decay: 75 -min_points: 10 -description_location: description.md -handout_dir: handout - diff --git a/challenges/test/example/description.md b/challenges/test/example/description.md deleted file mode 100644 index 1d07ceb..0000000 --- a/challenges/test/example/description.md +++ /dev/null @@ -1,6 +0,0 @@ -# Example - -**Difficulty:** Easy -**Author:** The Mikkel - -*Add challenge description here* diff --git a/challenges/test/example/handout/.gitkeep b/challenges/test/example/handout/.gitkeep deleted file mode 100644 index 0f065bc..0000000 --- a/challenges/test/example/handout/.gitkeep +++ /dev/null @@ -1,2 +0,0 @@ -# This file is used to keep the directory in the repository. -# This directory is used to store files that are handed out, for the challenge. The files are automatically zipped and copied to the files directory. \ No newline at end of file diff --git a/challenges/test/example/k8s/config/Chart.yaml b/challenges/test/example/k8s/config/Chart.yaml deleted file mode 100644 index 1c246e7..0000000 --- a/challenges/test/example/k8s/config/Chart.yaml +++ /dev/null @@ -1,6 +0,0 @@ -apiVersion: v2 -name: configmap-example -version: 1.5.0 -description: Challenge configmap for example in category test -appVersion: "1.5.0" -type: application diff --git a/challenges/test/example/k8s/config/templates/k8s.yml b/challenges/test/example/k8s/config/templates/k8s.yml deleted file mode 100644 index cccd3ca..0000000 --- a/challenges/test/example/k8s/config/templates/k8s.yml +++ /dev/null @@ -1,53 +0,0 @@ -apiVersion: v1 -kind: ConfigMap -metadata: - name: "challenge-test-example" - labels: - challenges.ctfpilot.com/type: "none" - challenges.ctfpilot.com/name: "example" - challenges.ctfpilot.com/category: "test" - challenges.ctfpilot.com/version: "5" - challenges.ctfpilot.com/configmap: "challenge-config" - challenges.ctfpilot.com/enabled: "true" - ctfpilot.com/component: "challenge-config" -data: - name: "example" - path: "challenges/test/example" - repository: "ctfpilot/challenges-example" - generated_at: "2025-12-20 10:41:26" - challenge: | - { - "$schema": "https://raw.githubusercontent.com/ctfpilot/challenge-schema/refs/heads/main/schema.json", - "enabled": true, - "name": "Example", - "slug": "example", - "author": "The Mikkel", - "category": "test", - "difficulty": "easy", - "tags": [], - "type": "static", - "instanced_type": "none", - "instanced_name": null, - "instanced_subdomains": [], - "connection": null, - "flag": [ - { - "flag": "test{demo}", - "case_sensitive": false - } - ], - "points": 1000, - "decay": 75, - "min_points": 10, - "description_location": "description.md", - "handout_dir": "handout" - } - - description: | - # Example - - **Difficulty:** Easy - **Author:** The Mikkel - - *Add challenge description here* - diff --git a/challenges/test/example/k8s/config/values.yaml b/challenges/test/example/k8s/config/values.yaml deleted file mode 100644 index 81cf4bb..0000000 --- a/challenges/test/example/k8s/config/values.yaml +++ /dev/null @@ -1,11 +0,0 @@ -challenge: - enabled: true - name: example - category: test - type: none - version: 5 - path: challenges/test/example -kubectf: - expires: 3600 - availableAt: 0 - host: example.com diff --git a/challenges/test/example/k8s/files/.gitkeep b/challenges/test/example/k8s/files/.gitkeep deleted file mode 100644 index ef3682f..0000000 --- a/challenges/test/example/k8s/files/.gitkeep +++ /dev/null @@ -1 +0,0 @@ -# This file is to keep the directory in git. diff --git a/challenges/test/example/solution/README.md b/challenges/test/example/solution/README.md deleted file mode 100644 index 8614e07..0000000 --- a/challenges/test/example/solution/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Solution -This directory is used to store the solution script for the challenge. -This file should contain the steps to solve the challenge. \ No newline at end of file diff --git a/challenges/test/example/src/.gitkeep b/challenges/test/example/src/.gitkeep deleted file mode 100644 index 76376a2..0000000 --- a/challenges/test/example/src/.gitkeep +++ /dev/null @@ -1,2 +0,0 @@ -# This file is used to keep the directory in the repository. -# This directory is used to store source files for the challenge. \ No newline at end of file diff --git a/challenges/test/example/version b/challenges/test/example/version deleted file mode 100644 index 7813681..0000000 --- a/challenges/test/example/version +++ /dev/null @@ -1 +0,0 @@ -5 \ No newline at end of file From 6d3dc91ae8285ea07174f340ffdf193d4c9769a5 Mon Sep 17 00:00:00 2001 From: The0Mikkel Date: Sat, 20 Dec 2025 16:39:27 +0100 Subject: [PATCH 22/30] Update toolkit --- challenge-toolkit | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/challenge-toolkit b/challenge-toolkit index 4a714ce..38b0360 160000 --- a/challenge-toolkit +++ b/challenge-toolkit @@ -1 +1 @@ -Subproject commit 4a714ceecae83031b30ccf599381a22a4ac59743 +Subproject commit 38b03600b49b24180dae1aa66913664018c7a35a From 8e0547ab460a25e7284c9bf8fba3b64e2e517178 Mon Sep 17 00:00:00 2001 From: The0Mikkel Date: Sat, 20 Dec 2025 16:43:04 +0100 Subject: [PATCH 23/30] Update templates from toolkit --- template/instanced-tcp-k8s.yml | 3 +- template/shared-tcp-k8s.yml | 106 +++++++++++++++++++++++++++++ template/shared-web-k8s.yml | 121 +++++++++++++++++++++++++++++++++ 3 files changed, 229 insertions(+), 1 deletion(-) create mode 100644 template/shared-tcp-k8s.yml create mode 100644 template/shared-web-k8s.yml diff --git a/template/instanced-tcp-k8s.yml b/template/instanced-tcp-k8s.yml index 8d050c3..03c4634 100644 --- a/template/instanced-tcp-k8s.yml +++ b/template/instanced-tcp-k8s.yml @@ -52,7 +52,7 @@ spec: values: - scaler containers: - - name: web + - name: tcp image: ghcr.io/{{ CHALLENGE_REPO }}-{{ DOCKER_IMAGE }}:{{ CHALLENGE_VERSION }} imagePullPolicy: IfNotPresent resources: @@ -87,6 +87,7 @@ spec: ports: - port: 8080 name: tcp + targetPort: tcp --- apiVersion: traefik.io/v1alpha1 kind: IngressRouteTCP diff --git a/template/shared-tcp-k8s.yml b/template/shared-tcp-k8s.yml new file mode 100644 index 0000000..f7c920e --- /dev/null +++ b/template/shared-tcp-k8s.yml @@ -0,0 +1,106 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: "ctf-{{ CHALLENGE_CATEGORY }}-{{ CHALLENGE_NAME }}" + namespace: kubectf-challenges + labels: + challenges.ctfpilot.com/type: "{{ CHALLENGE_TYPE }}" + challenges.ctfpilot.com/name: "{{ CHALLENGE_NAME }}" + challenges.ctfpilot.com/category: "{{ CHALLENGE_CATEGORY }}" + ctfpilot.com/component: "shared-challenge" +spec: + replicas: 1 + selector: + matchLabels: + challenges.ctfpilot.com/type: "{{ CHALLENGE_TYPE }}" + challenges.ctfpilot.com/name: "{{ CHALLENGE_NAME }}" + challenges.ctfpilot.com/category: "{{ CHALLENGE_CATEGORY }}" + template: + metadata: + labels: + challenges.ctfpilot.com/type: "{{ CHALLENGE_TYPE }}" + challenges.ctfpilot.com/name: "{{ CHALLENGE_NAME }}" + challenges.ctfpilot.com/category: "{{ CHALLENGE_CATEGORY }}" + ctfpilot.com/component: "shared-challenge" + spec: + enableServiceLinks: false + automountServiceAccountToken: false + imagePullSecrets: + - name: dockerconfigjson-github-com + dnsPolicy: None + dnsConfig: + nameservers: + - 1.1.1.1 + - 8.8.8.8 + tolerations: + - key: "cluster.ctfpilot.com/node" + value: "scaler" + effect: "PreferNoSchedule" + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: "cluster.ctfpilot.com/node" + operator: In + values: + - scaler + containers: + - name: tcp + image: ghcr.io/{{ CHALLENGE_REPO }}-{{ DOCKER_IMAGE }}:{{ CHALLENGE_VERSION }} + imagePullPolicy: IfNotPresent + resources: + limits: + cpu: 200m + memory: 256Mi + requests: + cpu: 10m + memory: 32Mi + ports: + - containerPort: 8080 + name: tcp +--- +apiVersion: v1 +kind: Service +metadata: + name: "ctf-{{ CHALLENGE_CATEGORY }}-{{ CHALLENGE_NAME }}" + namespace: kubectf-challenges + labels: + challenges.ctfpilot.com/type: "{{ CHALLENGE_TYPE }}" + challenges.ctfpilot.com/name: "{{ CHALLENGE_NAME }}" + challenges.ctfpilot.com/category: "{{ CHALLENGE_CATEGORY }}" + ctfpilot.com/component: "shared-challenge" +spec: + selector: + challenges.ctfpilot.com/type: "{{ CHALLENGE_TYPE }}" + challenges.ctfpilot.com/name: "{{ CHALLENGE_NAME }}" + challenges.ctfpilot.com/category: "{{ CHALLENGE_CATEGORY }}" + ports: + - port: 8080 + name: tcp + targetPort: tcp +--- +apiVersion: traefik.io/v1alpha1 +kind: IngressRouteTCP +metadata: + name: "ingress-ctf-{{ CHALLENGE_CATEGORY }}-{{ CHALLENGE_NAME }}" + namespace: kubectf-challenges + labels: + challenges.ctfpilot.com/type: "{{ CHALLENGE_TYPE }}" + challenges.ctfpilot.com/name: "{{ CHALLENGE_NAME }}" + challenges.ctfpilot.com/category: "{{ CHALLENGE_CATEGORY }}" + ctfpilot.com/component: "shared-challenge" + annotations: + traefik.ingress.kubernetes.io/router.priority: "100" +spec: + entryPoints: + - tcp-{{ CHALLENGE_CATEGORY }}-{{ CHALLENGE_NAME }} # Needs to be a custom entrypoint defined in Traefik - This is defined per challenge + routes: + - match: HostSNI(`*`) + priority: 10 + middlewares: + - name: challenge-ipwhitelist-tcp + namespace: kubectf-challenges + services: + - name: "ctf-{{ CHALLENGE_CATEGORY }}-{{ CHALLENGE_NAME }}" + port: 8080 diff --git a/template/shared-web-k8s.yml b/template/shared-web-k8s.yml new file mode 100644 index 0000000..f64c276 --- /dev/null +++ b/template/shared-web-k8s.yml @@ -0,0 +1,121 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: "ctf-{{ CHALLENGE_CATEGORY }}-{{ CHALLENGE_NAME }}" + namespace: kubectf-challenges + labels: + challenges.ctfpilot.com/type: "{{ CHALLENGE_TYPE }}" + challenges.ctfpilot.com/name: "{{ CHALLENGE_NAME }}" + challenges.ctfpilot.com/category: "{{ CHALLENGE_CATEGORY }}" + ctfpilot.com/component: "shared-challenge" +spec: + replicas: 1 + selector: + matchLabels: + challenges.ctfpilot.com/type: "{{ CHALLENGE_TYPE }}" + challenges.ctfpilot.com/name: "{{ CHALLENGE_NAME }}" + challenges.ctfpilot.com/category: "{{ CHALLENGE_CATEGORY }}" + template: + metadata: + labels: + challenges.ctfpilot.com/type: "{{ CHALLENGE_TYPE }}" + challenges.ctfpilot.com/name: "{{ CHALLENGE_NAME }}" + challenges.ctfpilot.com/category: "{{ CHALLENGE_CATEGORY }}" + ctfpilot.com/component: "shared-challenge" + spec: + enableServiceLinks: false + automountServiceAccountToken: false + imagePullSecrets: + - name: dockerconfigjson-github-com + dnsPolicy: None + dnsConfig: + nameservers: + - 1.1.1.1 + - 8.8.8.8 + tolerations: + - key: "cluster.ctfpilot.com/node" + value: "scaler" + effect: "PreferNoSchedule" + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: "cluster.ctfpilot.com/node" + operator: In + values: + - scaler + containers: + - name: web + image: ghcr.io/{{ CHALLENGE_REPO }}-{{ DOCKER_IMAGE }}:{{ CHALLENGE_VERSION }} + imagePullPolicy: IfNotPresent + resources: + limits: + cpu: 200m + memory: 256Mi + requests: + cpu: 10m + memory: 32Mi + ports: + - containerPort: 80 + name: web-port + startupProbe: + httpGet: + path: / + port: web-port + failureThreshold: 12 + periodSeconds: 10 + readinessProbe: + httpGet: + path: / + port: web-port + initialDelaySeconds: 5 + timeoutSeconds: 5 +--- +apiVersion: v1 +kind: Service +metadata: + name: "ctf-{{ CHALLENGE_CATEGORY }}-{{ CHALLENGE_NAME }}" + namespace: kubectf-challenges + labels: + challenges.ctfpilot.com/type: "{{ CHALLENGE_TYPE }}" + challenges.ctfpilot.com/name: "{{ CHALLENGE_NAME }}" + challenges.ctfpilot.com/category: "{{ CHALLENGE_CATEGORY }}" + ctfpilot.com/component: "shared-challenge" +spec: + selector: + challenges.ctfpilot.com/type: "{{ CHALLENGE_TYPE }}" + challenges.ctfpilot.com/name: "{{ CHALLENGE_NAME }}" + challenges.ctfpilot.com/category: "{{ CHALLENGE_CATEGORY }}" + ports: + - port: 80 + targetPort: web-port +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: "ingress-ctf-{{ CHALLENGE_CATEGORY }}-{{ CHALLENGE_NAME }}" + namespace: kubectf-challenges + labels: + challenges.ctfpilot.com/type: "{{ CHALLENGE_TYPE }}" + challenges.ctfpilot.com/name: "{{ CHALLENGE_NAME }}" + challenges.ctfpilot.com/category: "{{ CHALLENGE_CATEGORY }}" + ctfpilot.com/component: "shared-challenge" + annotations: + traefik.ingress.kubernetes.io/router.middlewares: kubectf-instancing-fallback@kubernetescrd +spec: + tls: + - hosts: + - "{{ CHALLENGE_NAME }}.{{ .Values.kubectf.host }}" + secretName: kubectf-cert-challs + rules: + - host: "{{ CHALLENGE_NAME }}.{{ .Values.kubectf.host }}" + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: "ctf-{{ CHALLENGE_CATEGORY }}-{{ CHALLENGE_NAME }}" + port: + number: 80 From 4d94e49485d21d0f8e1e2faee40a5505ae4e8ba2 Mon Sep 17 00:00:00 2001 From: The0mikkel <28625667+The0mikkel@users.noreply.github.com> Date: Sat, 20 Dec 2025 15:43:55 +0000 Subject: [PATCH 24/30] Create challenge: The shared site by The Mikkel --- challenges/web/the-shared-site/README.md | 4 + challenges/web/the-shared-site/challenge.yml | 27 ++++ challenges/web/the-shared-site/description.md | 6 + .../web/the-shared-site/handout/.gitkeep | 2 + .../web/the-shared-site/k8s/files/.gitkeep | 2 + .../web/the-shared-site/solution/README.md | 3 + challenges/web/the-shared-site/src/.gitkeep | 2 + challenges/web/the-shared-site/src/Dockerfile | 8 ++ .../web/the-shared-site/template/.gitkeep | 2 + .../web/the-shared-site/template/k8s.yml | 121 ++++++++++++++++++ challenges/web/the-shared-site/version | 1 + 11 files changed, 178 insertions(+) create mode 100644 challenges/web/the-shared-site/README.md create mode 100644 challenges/web/the-shared-site/challenge.yml create mode 100644 challenges/web/the-shared-site/description.md create mode 100644 challenges/web/the-shared-site/handout/.gitkeep create mode 100644 challenges/web/the-shared-site/k8s/files/.gitkeep create mode 100644 challenges/web/the-shared-site/solution/README.md create mode 100644 challenges/web/the-shared-site/src/.gitkeep create mode 100644 challenges/web/the-shared-site/src/Dockerfile create mode 100644 challenges/web/the-shared-site/template/.gitkeep create mode 100644 challenges/web/the-shared-site/template/k8s.yml create mode 100644 challenges/web/the-shared-site/version diff --git a/challenges/web/the-shared-site/README.md b/challenges/web/the-shared-site/README.md new file mode 100644 index 0000000..7ad50df --- /dev/null +++ b/challenges/web/the-shared-site/README.md @@ -0,0 +1,4 @@ +# The shared site + +*Add information about challenge here* +*It is meant to contain internal documentation of the challenge, such as how it is solved* diff --git a/challenges/web/the-shared-site/challenge.yml b/challenges/web/the-shared-site/challenge.yml new file mode 100644 index 0000000..936b093 --- /dev/null +++ b/challenges/web/the-shared-site/challenge.yml @@ -0,0 +1,27 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/ctfpilot/challenge-schema/refs/heads/main/schema.json + +enabled: true +name: The shared site +slug: the-shared-site +author: The Mikkel +category: web +difficulty: beginner +tags: [] +type: shared +instanced_type: web +instanced_name: null +instanced_subdomains: [] +connection: null +flag: +- flag: ctfpilot{thanks-for-visiting-the-shared-site} + case_sensitive: false +points: 1000 +decay: 75 +min_points: 100 +description_location: description.md +handout_dir: handout +dockerfile_locations: +- location: src/Dockerfile + context: src/ + identifier: null + diff --git a/challenges/web/the-shared-site/description.md b/challenges/web/the-shared-site/description.md new file mode 100644 index 0000000..53dff89 --- /dev/null +++ b/challenges/web/the-shared-site/description.md @@ -0,0 +1,6 @@ +# The shared site + +**Difficulty:** Beginner +**Author:** The Mikkel + +*Add challenge description here* diff --git a/challenges/web/the-shared-site/handout/.gitkeep b/challenges/web/the-shared-site/handout/.gitkeep new file mode 100644 index 0000000..0f065bc --- /dev/null +++ b/challenges/web/the-shared-site/handout/.gitkeep @@ -0,0 +1,2 @@ +# This file is used to keep the directory in the repository. +# This directory is used to store files that are handed out, for the challenge. The files are automatically zipped and copied to the files directory. \ No newline at end of file diff --git a/challenges/web/the-shared-site/k8s/files/.gitkeep b/challenges/web/the-shared-site/k8s/files/.gitkeep new file mode 100644 index 0000000..4fd76bb --- /dev/null +++ b/challenges/web/the-shared-site/k8s/files/.gitkeep @@ -0,0 +1,2 @@ +# This file is used to keep the directory in the repository. +# This directory is used to store files that are handed out, for the challenge. Use the handout directory for files that are handed out to users and want to be packaged as a zip file. \ No newline at end of file diff --git a/challenges/web/the-shared-site/solution/README.md b/challenges/web/the-shared-site/solution/README.md new file mode 100644 index 0000000..8614e07 --- /dev/null +++ b/challenges/web/the-shared-site/solution/README.md @@ -0,0 +1,3 @@ +# Solution +This directory is used to store the solution script for the challenge. +This file should contain the steps to solve the challenge. \ No newline at end of file diff --git a/challenges/web/the-shared-site/src/.gitkeep b/challenges/web/the-shared-site/src/.gitkeep new file mode 100644 index 0000000..76376a2 --- /dev/null +++ b/challenges/web/the-shared-site/src/.gitkeep @@ -0,0 +1,2 @@ +# This file is used to keep the directory in the repository. +# This directory is used to store source files for the challenge. \ No newline at end of file diff --git a/challenges/web/the-shared-site/src/Dockerfile b/challenges/web/the-shared-site/src/Dockerfile new file mode 100644 index 0000000..6fa51cc --- /dev/null +++ b/challenges/web/the-shared-site/src/Dockerfile @@ -0,0 +1,8 @@ +# Dockerfile for web - The shared site +FROM ubuntu:22.04 + +RUN apt-get update && apt-get upgrade -y && apt-get install -y python3 +RUN useradd -m challengeuser + +USER challengeuser + diff --git a/challenges/web/the-shared-site/template/.gitkeep b/challenges/web/the-shared-site/template/.gitkeep new file mode 100644 index 0000000..709b816 --- /dev/null +++ b/challenges/web/the-shared-site/template/.gitkeep @@ -0,0 +1,2 @@ +# This file is used to keep the directory in the repository. +# This directory is used to store templates for the challenge deployment. \ No newline at end of file diff --git a/challenges/web/the-shared-site/template/k8s.yml b/challenges/web/the-shared-site/template/k8s.yml new file mode 100644 index 0000000..f64c276 --- /dev/null +++ b/challenges/web/the-shared-site/template/k8s.yml @@ -0,0 +1,121 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: "ctf-{{ CHALLENGE_CATEGORY }}-{{ CHALLENGE_NAME }}" + namespace: kubectf-challenges + labels: + challenges.ctfpilot.com/type: "{{ CHALLENGE_TYPE }}" + challenges.ctfpilot.com/name: "{{ CHALLENGE_NAME }}" + challenges.ctfpilot.com/category: "{{ CHALLENGE_CATEGORY }}" + ctfpilot.com/component: "shared-challenge" +spec: + replicas: 1 + selector: + matchLabels: + challenges.ctfpilot.com/type: "{{ CHALLENGE_TYPE }}" + challenges.ctfpilot.com/name: "{{ CHALLENGE_NAME }}" + challenges.ctfpilot.com/category: "{{ CHALLENGE_CATEGORY }}" + template: + metadata: + labels: + challenges.ctfpilot.com/type: "{{ CHALLENGE_TYPE }}" + challenges.ctfpilot.com/name: "{{ CHALLENGE_NAME }}" + challenges.ctfpilot.com/category: "{{ CHALLENGE_CATEGORY }}" + ctfpilot.com/component: "shared-challenge" + spec: + enableServiceLinks: false + automountServiceAccountToken: false + imagePullSecrets: + - name: dockerconfigjson-github-com + dnsPolicy: None + dnsConfig: + nameservers: + - 1.1.1.1 + - 8.8.8.8 + tolerations: + - key: "cluster.ctfpilot.com/node" + value: "scaler" + effect: "PreferNoSchedule" + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: "cluster.ctfpilot.com/node" + operator: In + values: + - scaler + containers: + - name: web + image: ghcr.io/{{ CHALLENGE_REPO }}-{{ DOCKER_IMAGE }}:{{ CHALLENGE_VERSION }} + imagePullPolicy: IfNotPresent + resources: + limits: + cpu: 200m + memory: 256Mi + requests: + cpu: 10m + memory: 32Mi + ports: + - containerPort: 80 + name: web-port + startupProbe: + httpGet: + path: / + port: web-port + failureThreshold: 12 + periodSeconds: 10 + readinessProbe: + httpGet: + path: / + port: web-port + initialDelaySeconds: 5 + timeoutSeconds: 5 +--- +apiVersion: v1 +kind: Service +metadata: + name: "ctf-{{ CHALLENGE_CATEGORY }}-{{ CHALLENGE_NAME }}" + namespace: kubectf-challenges + labels: + challenges.ctfpilot.com/type: "{{ CHALLENGE_TYPE }}" + challenges.ctfpilot.com/name: "{{ CHALLENGE_NAME }}" + challenges.ctfpilot.com/category: "{{ CHALLENGE_CATEGORY }}" + ctfpilot.com/component: "shared-challenge" +spec: + selector: + challenges.ctfpilot.com/type: "{{ CHALLENGE_TYPE }}" + challenges.ctfpilot.com/name: "{{ CHALLENGE_NAME }}" + challenges.ctfpilot.com/category: "{{ CHALLENGE_CATEGORY }}" + ports: + - port: 80 + targetPort: web-port +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: "ingress-ctf-{{ CHALLENGE_CATEGORY }}-{{ CHALLENGE_NAME }}" + namespace: kubectf-challenges + labels: + challenges.ctfpilot.com/type: "{{ CHALLENGE_TYPE }}" + challenges.ctfpilot.com/name: "{{ CHALLENGE_NAME }}" + challenges.ctfpilot.com/category: "{{ CHALLENGE_CATEGORY }}" + ctfpilot.com/component: "shared-challenge" + annotations: + traefik.ingress.kubernetes.io/router.middlewares: kubectf-instancing-fallback@kubernetescrd +spec: + tls: + - hosts: + - "{{ CHALLENGE_NAME }}.{{ .Values.kubectf.host }}" + secretName: kubectf-cert-challs + rules: + - host: "{{ CHALLENGE_NAME }}.{{ .Values.kubectf.host }}" + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: "ctf-{{ CHALLENGE_CATEGORY }}-{{ CHALLENGE_NAME }}" + port: + number: 80 diff --git a/challenges/web/the-shared-site/version b/challenges/web/the-shared-site/version new file mode 100644 index 0000000..56a6051 --- /dev/null +++ b/challenges/web/the-shared-site/version @@ -0,0 +1 @@ +1 \ No newline at end of file From c90814a436eea22307cbe12568393e0979401cbf Mon Sep 17 00:00:00 2001 From: The0Mikkel Date: Sat, 20 Dec 2025 16:50:15 +0100 Subject: [PATCH 25/30] Add the shared site challenge --- challenges/web/the-shared-site/README.md | 3 +-- challenges/web/the-shared-site/challenge.yml | 5 ++++- challenges/web/the-shared-site/description.md | 2 +- .../web/the-shared-site/solution/README.md | 4 ++-- challenges/web/the-shared-site/src/Dockerfile | 8 ++------ .../web/the-shared-site/src/docker-compose.yml | 6 ++++++ .../web/the-shared-site/src/html/index.html | 16 ++++++++++++++++ 7 files changed, 32 insertions(+), 12 deletions(-) create mode 100644 challenges/web/the-shared-site/src/docker-compose.yml create mode 100644 challenges/web/the-shared-site/src/html/index.html diff --git a/challenges/web/the-shared-site/README.md b/challenges/web/the-shared-site/README.md index 7ad50df..e4f2f17 100644 --- a/challenges/web/the-shared-site/README.md +++ b/challenges/web/the-shared-site/README.md @@ -1,4 +1,3 @@ # The shared site -*Add information about challenge here* -*It is meant to contain internal documentation of the challenge, such as how it is solved* +This challenge is an example challenge, that is meant to demonstrate how shared challenges work. diff --git a/challenges/web/the-shared-site/challenge.yml b/challenges/web/the-shared-site/challenge.yml index 936b093..2258613 100644 --- a/challenges/web/the-shared-site/challenge.yml +++ b/challenges/web/the-shared-site/challenge.yml @@ -6,7 +6,10 @@ slug: the-shared-site author: The Mikkel category: web difficulty: beginner -tags: [] +tags: [ + Shared, + Example +] type: shared instanced_type: web instanced_name: null diff --git a/challenges/web/the-shared-site/description.md b/challenges/web/the-shared-site/description.md index 53dff89..42c7e0f 100644 --- a/challenges/web/the-shared-site/description.md +++ b/challenges/web/the-shared-site/description.md @@ -3,4 +3,4 @@ **Difficulty:** Beginner **Author:** The Mikkel -*Add challenge description here* +The site may contain the precious object you are looking for. diff --git a/challenges/web/the-shared-site/solution/README.md b/challenges/web/the-shared-site/solution/README.md index 8614e07..991c897 100644 --- a/challenges/web/the-shared-site/solution/README.md +++ b/challenges/web/the-shared-site/solution/README.md @@ -1,3 +1,3 @@ # Solution -This directory is used to store the solution script for the challenge. -This file should contain the steps to solve the challenge. \ No newline at end of file + +The flag is visible on the main page of the website handed out as part of this challenge. diff --git a/challenges/web/the-shared-site/src/Dockerfile b/challenges/web/the-shared-site/src/Dockerfile index 6fa51cc..8ebc473 100644 --- a/challenges/web/the-shared-site/src/Dockerfile +++ b/challenges/web/the-shared-site/src/Dockerfile @@ -1,8 +1,4 @@ # Dockerfile for web - The shared site -FROM ubuntu:22.04 - -RUN apt-get update && apt-get upgrade -y && apt-get install -y python3 -RUN useradd -m challengeuser - -USER challengeuser +FROM httpd:2.4-alpine +COPY ./html/ /usr/local/apache2/htdocs/ diff --git a/challenges/web/the-shared-site/src/docker-compose.yml b/challenges/web/the-shared-site/src/docker-compose.yml new file mode 100644 index 0000000..6925645 --- /dev/null +++ b/challenges/web/the-shared-site/src/docker-compose.yml @@ -0,0 +1,6 @@ +services: + the-shared-site: + build: . + ports: + - "8080:80" + restart: always \ No newline at end of file diff --git a/challenges/web/the-shared-site/src/html/index.html b/challenges/web/the-shared-site/src/html/index.html new file mode 100644 index 0000000..20c86b6 --- /dev/null +++ b/challenges/web/the-shared-site/src/html/index.html @@ -0,0 +1,16 @@ + + + + + + + The shared site + + + +

Welcome to the shared site!

+

This is an example of a shared web challenge.

+

Flag: ctfpilot{thanks-for-visiting-the-shared-site}

+ + + \ No newline at end of file From 54d04cb16f2c272bbac10ab0b1388fc4e115217f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 20 Dec 2025 15:51:07 +0000 Subject: [PATCH 26/30] CI: Update challenges [skip ci] --- .../the-shared-site/k8s/challenge/Chart.yaml | 6 + .../k8s/challenge/templates/k8s.yml | 121 ++++++++++++++++++ .../the-shared-site/k8s/challenge/values.yaml | 12 ++ .../web/the-shared-site/k8s/config/Chart.yaml | 6 + .../k8s/config/templates/k8s.yml | 63 +++++++++ .../the-shared-site/k8s/config/values.yaml | 11 ++ .../web/the-shared-site/k8s/files/.gitkeep | 3 +- challenges/web/the-shared-site/version | 2 +- 8 files changed, 221 insertions(+), 3 deletions(-) create mode 100644 challenges/web/the-shared-site/k8s/challenge/Chart.yaml create mode 100644 challenges/web/the-shared-site/k8s/challenge/templates/k8s.yml create mode 100644 challenges/web/the-shared-site/k8s/challenge/values.yaml create mode 100644 challenges/web/the-shared-site/k8s/config/Chart.yaml create mode 100644 challenges/web/the-shared-site/k8s/config/templates/k8s.yml create mode 100644 challenges/web/the-shared-site/k8s/config/values.yaml diff --git a/challenges/web/the-shared-site/k8s/challenge/Chart.yaml b/challenges/web/the-shared-site/k8s/challenge/Chart.yaml new file mode 100644 index 0000000..2ae8d0e --- /dev/null +++ b/challenges/web/the-shared-site/k8s/challenge/Chart.yaml @@ -0,0 +1,6 @@ +apiVersion: v2 +name: the-shared-site +version: 1.2.0 +description: Challenge the-shared-site in category web +appVersion: "1.2.0" +type: application diff --git a/challenges/web/the-shared-site/k8s/challenge/templates/k8s.yml b/challenges/web/the-shared-site/k8s/challenge/templates/k8s.yml new file mode 100644 index 0000000..7b83a11 --- /dev/null +++ b/challenges/web/the-shared-site/k8s/challenge/templates/k8s.yml @@ -0,0 +1,121 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: "ctf-web-the-shared-site" + namespace: kubectf-challenges + labels: + challenges.ctfpilot.com/type: "web" + challenges.ctfpilot.com/name: "the-shared-site" + challenges.ctfpilot.com/category: "web" + ctfpilot.com/component: "shared-challenge" +spec: + replicas: 1 + selector: + matchLabels: + challenges.ctfpilot.com/type: "web" + challenges.ctfpilot.com/name: "the-shared-site" + challenges.ctfpilot.com/category: "web" + template: + metadata: + labels: + challenges.ctfpilot.com/type: "web" + challenges.ctfpilot.com/name: "the-shared-site" + challenges.ctfpilot.com/category: "web" + ctfpilot.com/component: "shared-challenge" + spec: + enableServiceLinks: false + automountServiceAccountToken: false + imagePullSecrets: + - name: dockerconfigjson-github-com + dnsPolicy: None + dnsConfig: + nameservers: + - 1.1.1.1 + - 8.8.8.8 + tolerations: + - key: "cluster.ctfpilot.com/node" + value: "scaler" + effect: "PreferNoSchedule" + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: "cluster.ctfpilot.com/node" + operator: In + values: + - scaler + containers: + - name: web + image: ghcr.io/ctfpilot/challenges-example-web-the-shared-site:2 + imagePullPolicy: IfNotPresent + resources: + limits: + cpu: 200m + memory: 256Mi + requests: + cpu: 10m + memory: 32Mi + ports: + - containerPort: 80 + name: web-port + startupProbe: + httpGet: + path: / + port: web-port + failureThreshold: 12 + periodSeconds: 10 + readinessProbe: + httpGet: + path: / + port: web-port + initialDelaySeconds: 5 + timeoutSeconds: 5 +--- +apiVersion: v1 +kind: Service +metadata: + name: "ctf-web-the-shared-site" + namespace: kubectf-challenges + labels: + challenges.ctfpilot.com/type: "web" + challenges.ctfpilot.com/name: "the-shared-site" + challenges.ctfpilot.com/category: "web" + ctfpilot.com/component: "shared-challenge" +spec: + selector: + challenges.ctfpilot.com/type: "web" + challenges.ctfpilot.com/name: "the-shared-site" + challenges.ctfpilot.com/category: "web" + ports: + - port: 80 + targetPort: web-port +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: "ingress-ctf-web-the-shared-site" + namespace: kubectf-challenges + labels: + challenges.ctfpilot.com/type: "web" + challenges.ctfpilot.com/name: "the-shared-site" + challenges.ctfpilot.com/category: "web" + ctfpilot.com/component: "shared-challenge" + annotations: + traefik.ingress.kubernetes.io/router.middlewares: kubectf-instancing-fallback@kubernetescrd +spec: + tls: + - hosts: + - "the-shared-site.{{ .Values.kubectf.host }}" + secretName: kubectf-cert-challs + rules: + - host: "the-shared-site.{{ .Values.kubectf.host }}" + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: "ctf-web-the-shared-site" + port: + number: 80 diff --git a/challenges/web/the-shared-site/k8s/challenge/values.yaml b/challenges/web/the-shared-site/k8s/challenge/values.yaml new file mode 100644 index 0000000..88095ee --- /dev/null +++ b/challenges/web/the-shared-site/k8s/challenge/values.yaml @@ -0,0 +1,12 @@ +challenge: + enabled: true + name: the-shared-site + category: web + type: web + version: 2 + path: challenges/web/the-shared-site + dockerImage: web-the-shared-site +kubectf: + expires: 3600 + availableAt: 0 + host: example.com diff --git a/challenges/web/the-shared-site/k8s/config/Chart.yaml b/challenges/web/the-shared-site/k8s/config/Chart.yaml new file mode 100644 index 0000000..d9a966a --- /dev/null +++ b/challenges/web/the-shared-site/k8s/config/Chart.yaml @@ -0,0 +1,6 @@ +apiVersion: v2 +name: configmap-the-shared-site +version: 1.2.0 +description: Challenge configmap for the-shared-site in category web +appVersion: "1.2.0" +type: application diff --git a/challenges/web/the-shared-site/k8s/config/templates/k8s.yml b/challenges/web/the-shared-site/k8s/config/templates/k8s.yml new file mode 100644 index 0000000..21ed4ef --- /dev/null +++ b/challenges/web/the-shared-site/k8s/config/templates/k8s.yml @@ -0,0 +1,63 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: "challenge-web-the-shared-site" + labels: + challenges.ctfpilot.com/type: "web" + challenges.ctfpilot.com/name: "the-shared-site" + challenges.ctfpilot.com/category: "web" + challenges.ctfpilot.com/version: "2" + challenges.ctfpilot.com/configmap: "challenge-config" + challenges.ctfpilot.com/enabled: "true" + ctfpilot.com/component: "challenge-config" +data: + name: "the-shared-site" + path: "challenges/web/the-shared-site" + repository: "ctfpilot/challenges-example" + generated_at: "2025-12-20 15:51:07" + challenge: | + { + "$schema": "https://raw.githubusercontent.com/ctfpilot/challenge-schema/refs/heads/main/schema.json", + "enabled": true, + "name": "The shared site", + "slug": "the-shared-site", + "author": "The Mikkel", + "category": "web", + "difficulty": "beginner", + "tags": [ + "Shared", + "Example" + ], + "type": "shared", + "instanced_type": "web", + "instanced_name": null, + "instanced_subdomains": [], + "connection": null, + "flag": [ + { + "flag": "ctfpilot{thanks-for-visiting-the-shared-site}", + "case_sensitive": false + } + ], + "points": 1000, + "decay": 75, + "min_points": 100, + "description_location": "description.md", + "handout_dir": "handout", + "dockerfile_locations": [ + { + "location": "src/Dockerfile", + "context": "src/", + "identifier": null + } + ] + } + + description: | + # The shared site + + **Difficulty:** Beginner + **Author:** The Mikkel + + The site may contain the precious object you are looking for. + diff --git a/challenges/web/the-shared-site/k8s/config/values.yaml b/challenges/web/the-shared-site/k8s/config/values.yaml new file mode 100644 index 0000000..4fc8dd6 --- /dev/null +++ b/challenges/web/the-shared-site/k8s/config/values.yaml @@ -0,0 +1,11 @@ +challenge: + enabled: true + name: the-shared-site + category: web + type: web + version: 2 + path: challenges/web/the-shared-site +kubectf: + expires: 3600 + availableAt: 0 + host: example.com diff --git a/challenges/web/the-shared-site/k8s/files/.gitkeep b/challenges/web/the-shared-site/k8s/files/.gitkeep index 4fd76bb..ef3682f 100644 --- a/challenges/web/the-shared-site/k8s/files/.gitkeep +++ b/challenges/web/the-shared-site/k8s/files/.gitkeep @@ -1,2 +1 @@ -# This file is used to keep the directory in the repository. -# This directory is used to store files that are handed out, for the challenge. Use the handout directory for files that are handed out to users and want to be packaged as a zip file. \ No newline at end of file +# This file is to keep the directory in git. diff --git a/challenges/web/the-shared-site/version b/challenges/web/the-shared-site/version index 56a6051..d8263ee 100644 --- a/challenges/web/the-shared-site/version +++ b/challenges/web/the-shared-site/version @@ -1 +1 @@ -1 \ No newline at end of file +2 \ No newline at end of file From ba27ac70a166308ec826b1380517687a509f63e2 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 20 Dec 2025 15:52:29 +0000 Subject: [PATCH 27/30] CI: Update challenges [skip ci] --- challenges/web/the-shared-site/k8s/challenge/Chart.yaml | 4 ++-- .../web/the-shared-site/k8s/challenge/templates/k8s.yml | 2 +- challenges/web/the-shared-site/k8s/challenge/values.yaml | 2 +- challenges/web/the-shared-site/k8s/config/Chart.yaml | 4 ++-- challenges/web/the-shared-site/k8s/config/templates/k8s.yml | 4 ++-- challenges/web/the-shared-site/k8s/config/values.yaml | 2 +- challenges/web/the-shared-site/version | 2 +- 7 files changed, 10 insertions(+), 10 deletions(-) diff --git a/challenges/web/the-shared-site/k8s/challenge/Chart.yaml b/challenges/web/the-shared-site/k8s/challenge/Chart.yaml index 2ae8d0e..14d17f4 100644 --- a/challenges/web/the-shared-site/k8s/challenge/Chart.yaml +++ b/challenges/web/the-shared-site/k8s/challenge/Chart.yaml @@ -1,6 +1,6 @@ apiVersion: v2 name: the-shared-site -version: 1.2.0 +version: 1.3.0 description: Challenge the-shared-site in category web -appVersion: "1.2.0" +appVersion: "1.3.0" type: application diff --git a/challenges/web/the-shared-site/k8s/challenge/templates/k8s.yml b/challenges/web/the-shared-site/k8s/challenge/templates/k8s.yml index 7b83a11..d068608 100644 --- a/challenges/web/the-shared-site/k8s/challenge/templates/k8s.yml +++ b/challenges/web/the-shared-site/k8s/challenge/templates/k8s.yml @@ -47,7 +47,7 @@ spec: - scaler containers: - name: web - image: ghcr.io/ctfpilot/challenges-example-web-the-shared-site:2 + image: ghcr.io/ctfpilot/challenges-example-web-the-shared-site:3 imagePullPolicy: IfNotPresent resources: limits: diff --git a/challenges/web/the-shared-site/k8s/challenge/values.yaml b/challenges/web/the-shared-site/k8s/challenge/values.yaml index 88095ee..2d12a4b 100644 --- a/challenges/web/the-shared-site/k8s/challenge/values.yaml +++ b/challenges/web/the-shared-site/k8s/challenge/values.yaml @@ -3,7 +3,7 @@ challenge: name: the-shared-site category: web type: web - version: 2 + version: 3 path: challenges/web/the-shared-site dockerImage: web-the-shared-site kubectf: diff --git a/challenges/web/the-shared-site/k8s/config/Chart.yaml b/challenges/web/the-shared-site/k8s/config/Chart.yaml index d9a966a..5c3d680 100644 --- a/challenges/web/the-shared-site/k8s/config/Chart.yaml +++ b/challenges/web/the-shared-site/k8s/config/Chart.yaml @@ -1,6 +1,6 @@ apiVersion: v2 name: configmap-the-shared-site -version: 1.2.0 +version: 1.3.0 description: Challenge configmap for the-shared-site in category web -appVersion: "1.2.0" +appVersion: "1.3.0" type: application diff --git a/challenges/web/the-shared-site/k8s/config/templates/k8s.yml b/challenges/web/the-shared-site/k8s/config/templates/k8s.yml index 21ed4ef..22f4edd 100644 --- a/challenges/web/the-shared-site/k8s/config/templates/k8s.yml +++ b/challenges/web/the-shared-site/k8s/config/templates/k8s.yml @@ -6,7 +6,7 @@ metadata: challenges.ctfpilot.com/type: "web" challenges.ctfpilot.com/name: "the-shared-site" challenges.ctfpilot.com/category: "web" - challenges.ctfpilot.com/version: "2" + challenges.ctfpilot.com/version: "3" challenges.ctfpilot.com/configmap: "challenge-config" challenges.ctfpilot.com/enabled: "true" ctfpilot.com/component: "challenge-config" @@ -14,7 +14,7 @@ data: name: "the-shared-site" path: "challenges/web/the-shared-site" repository: "ctfpilot/challenges-example" - generated_at: "2025-12-20 15:51:07" + generated_at: "2025-12-20 15:52:29" challenge: | { "$schema": "https://raw.githubusercontent.com/ctfpilot/challenge-schema/refs/heads/main/schema.json", diff --git a/challenges/web/the-shared-site/k8s/config/values.yaml b/challenges/web/the-shared-site/k8s/config/values.yaml index 4fc8dd6..f399ee3 100644 --- a/challenges/web/the-shared-site/k8s/config/values.yaml +++ b/challenges/web/the-shared-site/k8s/config/values.yaml @@ -3,7 +3,7 @@ challenge: name: the-shared-site category: web type: web - version: 2 + version: 3 path: challenges/web/the-shared-site kubectf: expires: 3600 diff --git a/challenges/web/the-shared-site/version b/challenges/web/the-shared-site/version index d8263ee..e440e5c 100644 --- a/challenges/web/the-shared-site/version +++ b/challenges/web/the-shared-site/version @@ -1 +1 @@ -2 \ No newline at end of file +3 \ No newline at end of file From 80cfb6b455b08c1faf0195f67103257fc671b077 Mon Sep 17 00:00:00 2001 From: The0Mikkel Date: Sat, 20 Dec 2025 16:53:23 +0100 Subject: [PATCH 28/30] Add tags to challenges: "Oh look, A flag!" and "Where robots cannot search" --- challenges/forensics/oh-look-a-flag/challenge.yml | 5 ++++- challenges/web/where-robots-cannot-search/challenge.yml | 2 ++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/challenges/forensics/oh-look-a-flag/challenge.yml b/challenges/forensics/oh-look-a-flag/challenge.yml index 9673bd6..940e5cd 100644 --- a/challenges/forensics/oh-look-a-flag/challenge.yml +++ b/challenges/forensics/oh-look-a-flag/challenge.yml @@ -6,7 +6,10 @@ slug: oh-look-a-flag author: The Mikkel category: forensics difficulty: beginner -tags: [] +tags: [ + Static, + Example +] type: static instanced_type: none instanced_name: null diff --git a/challenges/web/where-robots-cannot-search/challenge.yml b/challenges/web/where-robots-cannot-search/challenge.yml index 82857e9..23eb068 100644 --- a/challenges/web/where-robots-cannot-search/challenge.yml +++ b/challenges/web/where-robots-cannot-search/challenge.yml @@ -8,6 +8,8 @@ category: web difficulty: beginner tags: [ "BrunnerCTF 2025", + Instanced, + Example ] type: instanced instanced_type: web From 90215c6de467f7b90981668818a61ec4e52c7f1b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 20 Dec 2025 15:54:13 +0000 Subject: [PATCH 29/30] CI: Update challenges [skip ci] --- .../oh-look-a-flag/k8s/config/Chart.yaml | 4 ++-- .../oh-look-a-flag/k8s/config/templates/k8s.yml | 9 ++++++--- .../oh-look-a-flag/k8s/config/values.yaml | 2 +- .../k8s/files/forensics_oh-look-a-flag.zip | Bin 359 -> 359 bytes challenges/forensics/oh-look-a-flag/version | 2 +- 5 files changed, 10 insertions(+), 7 deletions(-) diff --git a/challenges/forensics/oh-look-a-flag/k8s/config/Chart.yaml b/challenges/forensics/oh-look-a-flag/k8s/config/Chart.yaml index ea47587..a8c42fc 100644 --- a/challenges/forensics/oh-look-a-flag/k8s/config/Chart.yaml +++ b/challenges/forensics/oh-look-a-flag/k8s/config/Chart.yaml @@ -1,6 +1,6 @@ apiVersion: v2 name: configmap-oh-look-a-flag -version: 1.4.0 +version: 1.5.0 description: Challenge configmap for oh-look-a-flag in category forensics -appVersion: "1.4.0" +appVersion: "1.5.0" type: application diff --git a/challenges/forensics/oh-look-a-flag/k8s/config/templates/k8s.yml b/challenges/forensics/oh-look-a-flag/k8s/config/templates/k8s.yml index dc50c94..3a6423e 100644 --- a/challenges/forensics/oh-look-a-flag/k8s/config/templates/k8s.yml +++ b/challenges/forensics/oh-look-a-flag/k8s/config/templates/k8s.yml @@ -6,7 +6,7 @@ metadata: challenges.ctfpilot.com/type: "none" challenges.ctfpilot.com/name: "oh-look-a-flag" challenges.ctfpilot.com/category: "forensics" - challenges.ctfpilot.com/version: "4" + challenges.ctfpilot.com/version: "5" challenges.ctfpilot.com/configmap: "challenge-config" challenges.ctfpilot.com/enabled: "true" ctfpilot.com/component: "challenge-config" @@ -14,7 +14,7 @@ data: name: "oh-look-a-flag" path: "challenges/forensics/oh-look-a-flag" repository: "ctfpilot/challenges-example" - generated_at: "2025-12-20 13:03:33" + generated_at: "2025-12-20 15:54:13" challenge: | { "$schema": "https://raw.githubusercontent.com/ctfpilot/challenge-schema/refs/heads/main/schema.json", @@ -24,7 +24,10 @@ data: "author": "The Mikkel", "category": "forensics", "difficulty": "beginner", - "tags": [], + "tags": [ + "Static", + "Example" + ], "type": "static", "instanced_type": "none", "instanced_name": null, diff --git a/challenges/forensics/oh-look-a-flag/k8s/config/values.yaml b/challenges/forensics/oh-look-a-flag/k8s/config/values.yaml index 173af03..fb2a662 100644 --- a/challenges/forensics/oh-look-a-flag/k8s/config/values.yaml +++ b/challenges/forensics/oh-look-a-flag/k8s/config/values.yaml @@ -3,7 +3,7 @@ challenge: name: oh-look-a-flag category: forensics type: none - version: 4 + version: 5 path: challenges/forensics/oh-look-a-flag kubectf: expires: 3600 diff --git a/challenges/forensics/oh-look-a-flag/k8s/files/forensics_oh-look-a-flag.zip b/challenges/forensics/oh-look-a-flag/k8s/files/forensics_oh-look-a-flag.zip index 2f390dfea79eeb9c79a104c87fd060c29d59d490..64862e0fc493291b0b56a2afc6771069f620a9f3 100644 GIT binary patch delta 39 qcmaFP^qh$&z?+#xgaHJO)lK9vW!hCY(YcWc$Uf!@WKZU0i~<1O& Date: Sat, 20 Dec 2025 15:54:20 +0000 Subject: [PATCH 30/30] CI: Update challenges [skip ci] --- .../web/where-robots-cannot-search/k8s/challenge/k8s.yml | 2 +- .../web/where-robots-cannot-search/k8s/config/Chart.yaml | 4 ++-- .../k8s/config/templates/k8s.yml | 8 +++++--- .../web/where-robots-cannot-search/k8s/config/values.yaml | 2 +- challenges/web/where-robots-cannot-search/version | 2 +- 5 files changed, 10 insertions(+), 8 deletions(-) diff --git a/challenges/web/where-robots-cannot-search/k8s/challenge/k8s.yml b/challenges/web/where-robots-cannot-search/k8s/challenge/k8s.yml index aa21f26..ff6a12e 100644 --- a/challenges/web/where-robots-cannot-search/k8s/challenge/k8s.yml +++ b/challenges/web/where-robots-cannot-search/k8s/challenge/k8s.yml @@ -67,7 +67,7 @@ spec: - scaler containers: - name: web - image: ghcr.io/ctfpilot/challenges-example-web-where-robots-cannot-search:6 + image: ghcr.io/ctfpilot/challenges-example-web-where-robots-cannot-search:7 imagePullPolicy: IfNotPresent resources: limits: diff --git a/challenges/web/where-robots-cannot-search/k8s/config/Chart.yaml b/challenges/web/where-robots-cannot-search/k8s/config/Chart.yaml index 3b76e1c..5809e9d 100644 --- a/challenges/web/where-robots-cannot-search/k8s/config/Chart.yaml +++ b/challenges/web/where-robots-cannot-search/k8s/config/Chart.yaml @@ -1,6 +1,6 @@ apiVersion: v2 name: configmap-where-robots-cannot-search -version: 1.6.0 +version: 1.7.0 description: Challenge configmap for where-robots-cannot-search in category web -appVersion: "1.6.0" +appVersion: "1.7.0" type: application diff --git a/challenges/web/where-robots-cannot-search/k8s/config/templates/k8s.yml b/challenges/web/where-robots-cannot-search/k8s/config/templates/k8s.yml index a7f9f55..5f685e9 100644 --- a/challenges/web/where-robots-cannot-search/k8s/config/templates/k8s.yml +++ b/challenges/web/where-robots-cannot-search/k8s/config/templates/k8s.yml @@ -6,7 +6,7 @@ metadata: challenges.ctfpilot.com/type: "web" challenges.ctfpilot.com/name: "where-robots-cannot-search" challenges.ctfpilot.com/category: "web" - challenges.ctfpilot.com/version: "6" + challenges.ctfpilot.com/version: "7" challenges.ctfpilot.com/configmap: "challenge-config" challenges.ctfpilot.com/enabled: "true" ctfpilot.com/component: "challenge-config" @@ -14,7 +14,7 @@ data: name: "where-robots-cannot-search" path: "challenges/web/where-robots-cannot-search" repository: "ctfpilot/challenges-example" - generated_at: "2025-12-20 13:03:34" + generated_at: "2025-12-20 15:54:20" challenge: | { "$schema": "https://raw.githubusercontent.com/ctfpilot/challenge-schema/refs/heads/main/schema.json", @@ -25,7 +25,9 @@ data: "category": "web", "difficulty": "beginner", "tags": [ - "BrunnerCTF 2025" + "BrunnerCTF 2025", + "Instanced", + "Example" ], "type": "instanced", "instanced_type": "web", diff --git a/challenges/web/where-robots-cannot-search/k8s/config/values.yaml b/challenges/web/where-robots-cannot-search/k8s/config/values.yaml index 55f6a78..31cf09a 100644 --- a/challenges/web/where-robots-cannot-search/k8s/config/values.yaml +++ b/challenges/web/where-robots-cannot-search/k8s/config/values.yaml @@ -3,7 +3,7 @@ challenge: name: where-robots-cannot-search category: web type: web - version: 6 + version: 7 path: challenges/web/where-robots-cannot-search kubectf: expires: 3600 diff --git a/challenges/web/where-robots-cannot-search/version b/challenges/web/where-robots-cannot-search/version index 62f9457..c793025 100644 --- a/challenges/web/where-robots-cannot-search/version +++ b/challenges/web/where-robots-cannot-search/version @@ -1 +1 @@ -6 \ No newline at end of file +7 \ No newline at end of file