Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions backend/compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ services:
docker-socket-proxy:
container_name: dockerproxy
# Uncomment the following ports section for development
# ports:
# - "2375:2375"
ports:
- "2375:2375"
environment:
- CONTAINERS=1 # create/start/stop/inspect containers
- POST=1 # CRITICAL: allow POST requests
Expand Down Expand Up @@ -57,6 +57,8 @@ services:
restart: unless-stopped
ports:
- "${PORT:-3000}:3000"
volumes:
- ./src/utils/ca.pem:/app/dist/utils/key.pem:ro
env_file:
- .env
networks:
Expand Down
3 changes: 3 additions & 0 deletions backend/dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ RUN npm ci --omit=dev && \
# Copy built files from builder stage
COPY --from=builder /app/dist ./dist


COPY src/utils/ca.pem src/utils/cert.pem ./dist/utils/

# Change ownership to non-root user
RUN chown -R appuser:appgroup /app

Expand Down
25 changes: 25 additions & 0 deletions backend/nginx.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
events {
# Configuration for connection processing
worker_connections 1024;
}
http {
include mime.types;

upstream backendserver {
server 127.0.0.1:3000;
}

server {
listen 80; # Listen on standard web port
server_name localhost;

location / {
proxy_pass http://backendserver/;
# Important headers to keep the user's info intact
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
}
97 changes: 97 additions & 0 deletions backend/scripts/ctfImagePrep.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
## this script is specific for our use case in future will be updated to be more dynamic
#!/bin/sh

command_exists() {
command -v "$1" >/dev/null 2>&1
}
install_package() {
local package=$1
if command_exists apt; then
sudo apt install -y "$package"
elif command_exists pacman; then
sudo pacman -S --noconfirm "$package"
elif command_exists dnf; then
sudo dnf install -y "$package"
elif command_exists yum; then
sudo yum install -y "$package"
elif command_exists brew; then
brew install "$package"
else
echo "❌ Unsupported package manager. Please install $package manually."
fi
}
echo "checking prequisite"

#check docker
if ! command -v docker >/dev/null 2>&1
then
echo "docker not found installing it"
install_package docker
sudo systemctl start docker
sudo usermod -aG docker $USER
fi
# check git
if ! command -v git >/dev/null 2>&1
then
echo "Git not found installing it"
install_package git
fi

echo "Passed, checking does the Ctf challenge images/network exsits"
TMP_DIR_PATH="$HOME/ctf_prep_tmp"
BACKEND_IMAGE_NAME='ctf_ssrf_race_backend'
FRONTEND_IMAGE_NAME='ctf_ssrf_race_frontend'
SSRF_GITHUB_URL="https://github.com/sfeedbackx/ssrf-race.git"

if docker network ls | grep -q -w 'ctf_ssrf_race' ; then
echo 'network exsist'
else
echo 'creating network';
docker network create ctf_ssrf_race
fi
docker image ls | grep -q -w $FRONTEND_IMAGE_NAME
FRONTEND_IMAGE_FOUND=$?
docker image ls | grep -q -w $BACKEND_IMAGE_NAME
BACKEND_IMAGE_FOUND=$?

if [ "$FRONTEND_IMAGE_FOUND" -ne 0 ] || [ "$BACKEND_IMAGE_FOUND" -ne 0 ]; then
echo "frontent or backend image missing"
## first check if folder exsits
if [ ! -d "$TMP_DIR_PATH" ]; then
echo "creating tmp dir"
mkdir $TMP_DIR_PATH
else
echo "tmp folder exsits , preforming cleansing"
find $TMP_DIR_PATH -mindepth 1 -exec rm -rf {} +
fi
## preforming clone of ssrf challenge to tmp dir
echo "cloning ssrf_challenge"
git clone $SSRF_GITHUB_URL $TMP_DIR_PATH
if $BACKEND_IMAGE_FOUND; then
echo 'backend image exsist'
else
## we will be putting thes github repo of ctf challenge in folder called ctf_prep_tmp
echo 'creating backend image';
## now we go and build the image of the backend
cd $TMP_DIR_PATH/backend
echo "building backend image"
docker build -t $BACKEND_IMAGE_NAME .
echo "finished building backend image"
fi
if $FRONTEND_IMAGE_FOUND; then
echo 'backend image exsist'
else
echo 'creating frontend image';
## now we go and build the image of the frontend
cd $TMP_DIR_PATH/frontend
echo "building frontend image"
docker build -t $FRONTEND_IMAGE_NAME .
echo "finished building frontend image"
fi
else
echo "image are well defined , removing tmp folder"
rm -rf $TMP_DIR_PATH
fi



147 changes: 147 additions & 0 deletions backend/scripts/dockerTlsSetup.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
#!/bin/sh

command_exists() {
command -v "$1" >/dev/null 2>&1
}

install_package() {
local package=$1
if command_exists apt; then
sudo apt install -y "$package"
elif command_exists pacman; then
sudo pacman -S --noconfirm "$package"
elif command_exists dnf; then
sudo dnf install -y "$package"
elif command_exists brew; then
brew install "$package"
else
echo "❌ Unsupported package manager. Please install $package manually."
fi
}

if [ $# -ne 2 ] ; then
echo "usage $0 CA-IP EXT-IP"
exit 1
fi

CA_IP=$1
EXT_IP=$2

echo "checking prerequisite"

#check docker
if ! command -v docker >/dev/null 2>&1
then
echo "docker not found installing it"
install_package docker
sudo systemctl start docker
sudo usermod -aG docker $USER

fi

#check openssl
if ! command -v openssl >/dev/null 2>&1
then
echo "openssl not found plz installing it"
install_package openssl
fi

echo "starting setup the certificate"

CERT_PATH="$HOME/docker-certs"
if [ ! -d "$CERT_PATH" ]; then
echo "creating certif dir"
mkdir -p "$CERT_PATH"
else
echo "certif folder exists, performing cleansing"
find "$CERT_PATH" -mindepth 1 -exec rm -rf {} +
fi

cd "$CERT_PATH"

echo "generating CA key"
openssl genrsa -out ca-key.pem 4096

echo "generating CA certificate"
openssl req -new -x509 -days 365 -key ca-key.pem -sha256 -out ca.pem -subj "/CN=docker-ca"

echo "generating Server certificate"
echo "Create Server Private Key"
openssl genrsa -out server-key.pem 4096

echo "Create Certificate Signing Request"
openssl req -subj "/CN=$CA_IP" -sha256 -new -key server-key.pem -out server.csr

echo "Configure Certificate Extensions"
echo "subjectAltName = IP:$EXT_IP,IP:127.0.0.1" >> extfile.cnf
echo "extendedKeyUsage = serverAuth" >> extfile.cnf

echo "Sign the Server Certificate"
openssl x509 -req -days 365 -sha256 -in server.csr -CA ca.pem -CAkey ca-key.pem \
-CAcreateserial -out server-cert.pem -extfile extfile.cnf

echo "Generate Client Certificates"
echo "Create Client Private Key"
openssl genrsa -out key.pem 4096

echo "Create Client CSR"
openssl req -subj '/CN=client' -new -key key.pem -out client.csr

echo "Configure Client Extensions"
echo "extendedKeyUsage = clientAuth" > extfile-client.cnf

echo "Sign the Client Certificate"
openssl x509 -req -days 365 -sha256 -in client.csr -CA ca.pem -CAkey ca-key.pem \
-CAcreateserial -out cert.pem -extfile extfile-client.cnf

echo "Set Proper Permissions"
chmod 0400 ca-key.pem key.pem server-key.pem
chmod 0444 ca.pem server-cert.pem cert.pem

echo "Clean Up Temporary Files"
rm -v client.csr server.csr extfile.cnf extfile-client.cnf

DOCKER_PATH=/etc/docker/certs

echo "Configure Docker Daemon"
if [ ! -d "$DOCKER_PATH" ]; then
echo "creating docker remote dir"
sudo mkdir -p "$DOCKER_PATH"
else
echo "Docker remote folder exists, performing cleansing"
sudo find "$DOCKER_PATH" -mindepth 1 -exec rm -rf {} +
fi

sudo cp "$CERT_PATH/ca.pem" "$DOCKER_PATH"
sudo cp "$CERT_PATH/server-cert.pem" "$DOCKER_PATH"
sudo cp "$CERT_PATH/server-key.pem" "$DOCKER_PATH"

echo "Create Docker Service Override"
DOCKER_OVERRIDE_PATH="/etc/systemd/system/docker.service.d"
if [ ! -d "$DOCKER_OVERRIDE_PATH" ]; then
echo "creating docker override dir"
sudo mkdir -p "$DOCKER_OVERRIDE_PATH"
else
echo "Docker override folder exists, performing cleansing"
sudo find "$DOCKER_OVERRIDE_PATH" -mindepth 1 -exec rm -rf {} +
fi

sudo tee "$DOCKER_OVERRIDE_PATH/override.conf" > /dev/null << 'EOF'
[Service]
ExecStart=
ExecStart=/usr/bin/dockerd -H fd:// -H tcp://0.0.0.0:2376 \
--tlsverify \
--tlscacert=/etc/docker/certs/ca.pem \
--tlscert=/etc/docker/certs/server-cert.pem \
--tlskey=/etc/docker/certs/server-key.pem
EOF

echo "Reload and Restart Docker"
sudo systemctl daemon-reload
sudo systemctl restart docker

echo "Please copy the ca.pem, key.pem and cert.pem to the client to use it thanks"
sleep 5

echo "printing docker status"
sudo systemctl status docker
51 changes: 38 additions & 13 deletions backend/scripts/migrateScript.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,19 +51,44 @@ const containersConfig: containerConfig[] = [config0, config1];

const ctfChallenges: Ictf[] = [];

ctfChallenges.push({
name: 'SSRF-RACE',
withSite: true,
containersConfig: containersConfig,
description: 'Who said education has to be expensive? This platform seems to handle enrollment and pricing automatically. Still, nothing is ever as perfect as it looks.',
difficulty: ctfDifficulty.MID,
flag: 'cll{ss098fud63c2xgXPuVPimY3ZmkDmFsI+RfhCdqccOZwJKBqQI=}',
type: 'WEB_EXPLOIT',
resources: [],
hints: ['Hint 1: The server talks to itself. What happens when you make it ask the right questions?',
'Hint 2: Speed beats logic. Sometimes clicking faster than the server can think pays off.'
],
});
ctfChallenges.push(
{
name: 'SSRF-RACE',
withSite: true,
containersConfig: containersConfig,
description: 'Who said education has to be expensive? This platform seems to handle enrollment and pricing automatically. Still, nothing is ever as perfect as it looks.',
difficulty: ctfDifficulty.MID,
flag: 'cll{ss098fud63c2xgXPuVPimY3ZmkDmFsI+RfhCdqccOZwJKBqQI=}',
type: 'WEB_EXPLOIT',
resources: [],
hints: ['Hint 1: The server talks to itself. What happens when you make it ask the right questions?',
'Hint 2: Speed beats logic. Sometimes clicking faster than the server can think pays off.'
],
},
{
name: 'Steganography_basics',
withSite: false,
description: 'Do you know what is steganography ?',
difficulty: ctfDifficulty.EASY,
flag: 'cll{Fqj1Lkirsyi2sLn0O7aX1NIoYZggKuvy8MEfx1sU/PI=}',
type: 'FORENSICS',
resources: ['127.0.0.1:6650'],
hints: [],
},
{
name: 'STEGANOGRAPHY2',
withSite: false,
description: "So you know Steganography basics but didn't we deserve 20 ?",
difficulty: ctfDifficulty.MID,
flag: 'cll{iVwbTtAoYXciA486sEXwGMT1geaJOym3pIsEGeQQQNg=}',
type: 'FORENSICS',
resources: ['127.0.0.1:6600'],
hints: [
'Hint 1 : i can see the password there ! ',
'Hint 2 : really! we deserve 20'
],
}
);

const cleanCtfCollection = async () => {
console.log('deleting ctf collection...');
Expand Down
4 changes: 2 additions & 2 deletions backend/src/models/ctfModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ const ctfSchema = new Schema(
type: String,
trim: true,
required: [true, 'type required'],
enum: ['WEB_EXPLOIT', 'BE', 'OTHER'],
enum: ['WEB_EXPLOIT', 'BE', 'OTHER', 'FORENSICS'],
},

withSite: {
Expand All @@ -31,7 +31,7 @@ const ctfSchema = new Schema(
type: String,
trim: true,
required: [true, 'difficulty required'],
enum: ['ESAY', 'MID', 'HARD'],
enum: ['EASY', 'MID', 'HARD'],
},
hints: [
{
Expand Down
2 changes: 1 addition & 1 deletion backend/src/types/ctfTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ interface IMongoDocument extends ITimestamps {
export interface Ictf {
name: string;
description?: string | undefined;
type: 'WEB_EXPLOIT' | 'BE' | 'OTHER';
type: 'WEB_EXPLOIT' | 'BE' | 'OTHER' | 'FORENSICS';
resources: string[];
withSite: boolean;
difficulty: ctfDifficulty;
Expand Down