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ÁOCá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

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 dockerGit
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 gitSetup 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 psSau đó 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

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

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
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 -dSau khi chạy xong, chún ta sẽ thấy được 04 containers đang được chạy

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ự

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

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ÁOTại đây, để truy cập thì phần
Proxiestrong CF nên được tắt bởi tại đây chúng ta chưa cấu hìnhsslđể có thể truy cập thông quahttp

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

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

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

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>.comCẢNH BÁOTạ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

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
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:
- ctfdSau đó 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 -aSau khi chạy load trang lại thì ta đã có chứng chỉ (lúc này bật Proxies CF lên nhe)

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 Databasecó 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 trongmysql. Ví dụ mình muốn tạo một user tênJerryyytrongmysqltrên máyRemote Databaseta 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>/ctfdTheo 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]/ctfdSau 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 -aKiểm tra lại từ máy Remote database khi show databases thì thấy có một databases của CTFd

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 servertự host - Sử dụng
mail servercủ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.comMail 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ửiPassword: 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ề

