1791 words
9 minutes
Xây dựng hệ thống CTFd - part 1

Chắc hẳn khi đọc bài viết này thì mọi người không còn xa lạ gì với CTF - Capture The Flag rồi nhỉ. CTF được chia làm thành 02 loại là Jeopardy và Attack Defense (AD), thường các giải tổ chức thường theo thể thức Jeopardy, dù lớn hay nhỏ. Và để có thể tổ chức được một giải CTF Jeopardy thì cần phải có một nơi để có thể quản trị. Trên thế giới có rất nhiều platform khác nhau để có thể tổ chức, tuy nhiên trong bài viết này mình sẽ hướng dẫn cách để có thể cấu hình một giải CTF từ A -> Z để các bạn có thể tự host giải CTF cho riêng mình

CẢNH BÁO

Các bạn có thể dựa trên doc CTFd để có thể config, tuy nhiên bài viết dựa trên kinh nghiệm cá nhân mỗi khi làm giải CTFd, mình sẽ nói một cách dễ hiểu các bước thực hiện và tại sao cần phải làm như vậy

Setup môi trường chạy#

Để tổ chức một giải đấu thì ta cần có một máy để host, chúng ta có thể dùng VPS để có thể host online hoặc có thể dùng Local Machine để có thể host

Tại thời điểm bài viết, mình sẽ dùng cấu hình như sau

  • Ubuntu 22.04.5
  • 08 GB RAM
  • 04 Processors

image

Các Dependency cần thiết#

Docker#

Để chạy được CTFd ta cần phải có Docker, để cài được Docker chạy trên máy ta có thể thực hiện theo trang web này tại đây hoặc có thể làm theo các câu lệnh dưới đây

for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done

sudo apt update

sudo apt install ca-certificates curl

sudo install -m 0755 -d /etc/apt/keyrings

sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc

sudo chmod a+r /etc/apt/keyrings/docker.asc

echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

sudo apt-get update

sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

sudo groupadd docker

sudo usermod -aG docker $USER

newgrp docker

Git#

Ngoài Docker, Git là công cụ cần thiết để có thể tải các plugins, themes hỗ trợ cho giải CTF

sudo apt install git

Setup CTFd#

Build from Prebuild Image#

CTFd đã cung cấp image sẵn, chúng ta chỉ cần chọn bản phù hợp, kéo image về rồi run. Tại đây mình sẽ chọn phiên bản mới nhất với các cú pháp sau:

docker pull ctfd/ctfd:<version_bạn_muốn>

Đợi sau khi hoàn thành, chúng ta sẽ thực hiện run nó bằng command dưới đây, giải thích câu lệnh thì câu lệnh này giúp ta chạy container tại port 80 map với port 80 của container

docker run -d -p 80:80 ctfd/ctfd:<version_bạn_muốn>

Kiểm tra bằng câu lệnh

docker ps

Sau đó chúng ta đã có thể truy cập vào bên trang web bằng địa chỉ IP tại port 80. Kiểm tra địa chỉ IP thông qua lệnh ip a. Trong trường hợp này là địa chỉ 192.168.88.129

image

Truy cập thông qua Web, như hình dưới ta đã deploy thành công

image

Build from source#

Vì cách trên có một số hạn chế đó chính là khó để có thể tùy biến vì thế còn có một cách khác đó chính là build image từ chính trên trang Github

CTFd
/
CTFd
Waiting for api.github.com...
00K
0K
0K
Waiting...

Chỉ cần thực hiện các câu lệnh sau:

git https://github.com/CTFd/CTFd.git

cd CTFd

docker compose up -d

Sau khi chạy xong, chún ta sẽ thấy được 04 containers đang được chạy

image

Và cũng thử truy cập vào trang Web bằng địa chỉ IP của máy host CTFd, ta cũng sẽ có kết quả tương tự

image

Advanced Setup CTFd#

Ở trên chỉ là cấu hình để CTFd có thể hoạt động, ngoài ra còn rất nhiều thứ cần phải làm để giúp cho CTFd có thể hoạt động để thi đấu, tại phần này, mình sẽ hướng dẫn cách cài các thành phần sau:

Nếu các bạn đã có VPS hoặc máy bạn có thể nat port ra bên ngoài thì mình sẽ tới phần Advance setup

  • Cấu hình DNS
  • SSL
  • Remote Database
  • Google Mail server
  • Remote Docker Instance

Cấu hình DNS#

Để cấu hình DNS, ta sẽ cần tới ba thứ:

  • Thông tin Domain
  • Địa chỉ IP public
  • Tài khoản cloudflare

Vê phần thông tin domain, ta có thể lên các trang mạng để có thể mua địa chỉ, và nếu các bạn muốn có một tên domain free thì có thể làm theo bài viết này tại đây

Về phần địa chỉ IP Public, thì ta có thể lấy từ trên VPS hoặc từ các máy cloud

Sau khi đã có hai thứ trên, ta sẽ tạo tài khoản Cloudflare hoàn toàn miễn phí, và thực hiện trỏ tên miền về của mình về.

Giả sử mình có các thông tin sau:

  • IP: 35.229.144.39
  • Domain: jerryyytheduck.id.vn

Mình sẽ tiến hành vào trong dashboard của Cloudflare để tiến hành trỏ IP vào domain vơi các bước đầu như hình

image

Sau khi nhấn Add record, ta sẽ thêm type A vào và gắn trường name bằng tên mình muốn, tại đây mình muốn để là subdomain nên sẽ để là ctf, nếu các bạn muốn nó là domain chính luôn thì nhập vào @ trong trường name. Phần content sẽ để địa chỉ IPv4 mà mình muốn trỏ, trong trường hợp này là 35.229.144.39

Cloudflare sẽ cho chúng ta biết thông tin, như hình bên dưới, đã ghi rõ url ctf.jerryyytheduck.id.vn sẽ được mapping với địa chỉ 35.229.144.39. Sau khi kiểm tra, nhấn save là thành công.

CẢNH BÁO

Tại đây, để truy cập thì phần Proxies trong CF nên được tắt bởi tại đây chúng ta chưa cấu hình ssl để có thể truy cập thông qua http

image

Đây là khi ta chưa sử dụng trỏ DNS, truy cập thẳng bằng IP

image

Và sau khi chúng ta mapping rồi truy cập bằng tên domain thành công như hình bên dưới

image

Kiểm tra lại lần nữa thông qua CMD

image

Cấu hình chứng chỉ SSl#

Khi tạo chứng chỉ SSL, ta có rất nhiều cách khác nhau, có thể xin từ Domain provider hoặc là có thể tự tạo miễn phí như Let's Encrypt. Tại đây, mình sẽ thực hiện trên Let's Encrypt.

Sử dụng các câu lệnh sau:

#cài đặt certbot
sudo apt install certbot

#tạo chứng chỉ
sudo certbot certonly --standalone -d <domain_của_bạn>.com -d www.<domain_của_bạn>.com
CẢNH BÁO

Tại đây, nếu domain của bạn dùng là subdomain, thì bạn chỉ cần dùng command như ảnh bên dưới, còn nếu bạn dùng host CTFd với main domain thì làm như trên

image

Sau khi tạo chứng chỉ xong, ta sẽ cd chúng vào trong folder repo của CTFd và sử dụng các câu lệnh sau:

#tạo folder ssl trong repo CTFd
mkdir ssl

#cp fullchain.pem --> cert.crt
cp <đường dẫn fullchain.pem> ssl/cert.crt

#cp private.pem --> cert.key
cp <đường dẫn privkey.pem>  ssl/cert.key

image

Sau đó tiến hành chỉnh sửa file docker-compose.yml tại phần service --> nginx sẽ chỉnh thành

    nginx:
      image: nginx:stable
      restart: always
      volumes:
        - ./conf/nginx/http.conf:/etc/nginx/nginx.conf
        - ./ssl/cert.crt:/etc/nginx/cert.crt
        - ./ssl/cert.key:/etc/nginx/cert.key
      ports:
        - 443:443
      depends_on:
        - ctfd

Sau đó vào conf/nginx/http.conf chỉnh một số thông số trong phần server như sau:

    #listen 80 đổi thành như dưới đây
    listen 443 ssl;
    #thêm cách trường này vào
    server_name ctf.jerryyytheduck.id.vn; #tên miền của bạn đã setup
    ssl_certificate /etc/nginx/cert.crt;
    ssl_certificate_key /etc/nginx/cert.key;

Sau khi cấu hình xong, bấm save và thực hiện các command dưới đây:

# cho container down xuống
docker compose down 

#build lại container
docker compose up --build

#xóa đi các thứ không cần thiết
docker system prune -a

Sau khi chạy load trang lại thì ta đã có chứng chỉ (lúc này bật Proxies CF lên nhe)

image

Remote Database#

Về phần này, khi làm một server thi CTFd lớn cấp trường chẳng hạn, thì ta cần phải có một Remote Database để có thể backup lại dữ liệu. Phòng trường hợp máy host CTFd bị downtime.

Trong trường hợp này ta sẽ có một máy khác có chức năng host đề và các thông tin liên quan tới cuộc thi.

Để làm được như vậy, ta cần có một máy khác có sử dụng mysql. Trong bài viết này, mình giả sử bạn đã cài xong mysql rồi nhé, còn không thì có thể cài thông qua bài viết tại đây

Tại máy bạn muốn làm Remote Database, giả sử mình có con máy với địa chỉ IP 35.221.234.224 thì ta sẽ tiến hành như sau:

  • Trên máy làm Remote Database có thể dùng user root hoặc có thể tự tạo cho mình một user khác với pass cho user đó trên trong mysql. Ví dụ mình muốn tạo một user tên Jerryyy trong mysql trên máy Remote Database ta có thể làm như sau:
#đăng nhập root, nếu lần đầu đăng nhập thì làm theo các bước trong bài viết này:
#https://www.cyberciti.biz/faq/mysql-change-root-password/
mysql -u root -p

#sau khi đăng nhập thì tiến hành tao user
CREATE USER 'Jerryyy'@'<địa chỉ máy CTFd>' IDENTIFIED BY '123456xX';
GRANT ALL PRIVILEGES ON *.* TO 'Jerryyy'@'<địa chỉ máy CTFd>' WITH GRANT OPTION;
FLUSH PRIVILEGES;

Sau khi tạo thành công, ta sẽ vào bên trong config của mysql để chỉnh bind_address. Tham khảo các đường dẫn chứa file config mysql tại đây. Trong trường hợp của mình lúc viết bài là /etc/mysql/mariadb.conf.d/50-server.cnf

Chuyển đổi bind_address từ 127.0.0.1 thành 0.0.0.0 để listen bên ngoài và tiến hành restart service

giờ ta tiến hành lên trên máy host CTFd để thực hiện các công việc tiếp theo. Vào phần docker-compose.yml như phần cấu hình SSL để chỉnh sửa tiếp

Tại phần services --> ctfd --> environment biến DATABASE_URL sẽ được thanh đổi thành như sau:

DATABASE_URL=mysql+pymysql://<user>:<password>@<IP_máy_remote_database>/ctfd

Theo như trong trường hợp này thì sẽ là:

  • user: Jerryyy
  • password: 123456@xX
  • IP: 35.221.234.224

Ta sẽ có như sau:

#- DATABASE_URL=mysql+pymysql://ctfd:ctfd@db/ctfd
DATABASE_URL=mysql+pymysql://Jerryyy:[email protected]/ctfd

Sau khi cấu hình xong, bấm save và thực hiện các command dưới đây:

# cho container down xuống
docker compose down 

#build lại container
docker compose up --build

#xóa đi các thứ không cần thiết
docker system prune -a

Kiểm tra lại từ máy Remote database khi show databases thì thấy có một databases của CTFd

image

Google Mail server#

Và khi sử dụng CTFd thì chắc chắn phải tạo tới mail server dùng để xác thực. Tại đây ta có thể sử dụng hai hướng là

  • Sử dụng một mail server tự host
  • Sử dụng mail server của Google

Mình sẽ làm phương án số 02 do không có đủ kinh phí thuê mail server :(

Vì những lý do bảo mật mail nên mình sẽ gửi các bạn video hướng dẫn tạo mail server của Google.

Sau khi làm xong, chúng ta sẽ có được một cái password để sử dụng SMTP server. Giả sử mình có một mail tên [email protected] và muốn gửi thì tại đây ta sẽ nhập các thông số sau:

  • Mail From Address: Mail người gửi [email protected]
  • Mail Server Address: Server mail, tại đây mình sẽ để smtp.gmail.com
  • Mail Server Port: để mặc định 456 nếu xài mail google

Tick vào Use Mail Server Username and Password và chọn

  • Username: Cũng là mail người gửi
  • Password: Password tạo ra từ App Password

Tick vào TLS/SSL và nhấn hoàn tất. Kiểm tra bằng cách tạo thử account thì mình sẽ nhận được mail gửi về

image

Xây dựng hệ thống CTFd - part 1
https://jerryyytheduck.id.vn/posts/ctfd-infrastructure/ctfd-infa-1/
Author
Jerryyy
Published at
2025-02-11