Sau khi hoàn tất việc xây dựng hệ thống ở mức cơ bản để có thể sử dụng trong bài viết đầu tiên về xây dựng hệ thống CTFd, trong bài này thì mình sẽ giới thiệu một số công cụ cùng với các plugins được sử dụng để có thể host một giải CTF chỉnh chu nhất có thể
CẢNH BÁOTrong bài viết này mình chỉ hướng dẫn cho việc build from source nên khi các bạn tự pull về bằng docker CTF thì mình sẽ có một bài viết trong tương lai về phần này nhé
Bài viết này sẽ chia làm 02 phần cài Themes và Plugins
Themes
Về phần theme, khi các bạn chơi CTF ở các giải khác nhau thì sẽ có rất nhiều theme khác nhau được sử dụng riêng cho giải đấu, hoặc các bạn có thể lên trang CTFd họ cũng bán các loại theme khác nhau để sử dụng trong CTF, và dĩ nhiên là nó tính phí. Bạn có thể xem tại đây

Và vì CTFd là một dự án Opensource, vì thế trên cộng dồng cũng đã phát triển khá nhiều Theme khác nhau và được CTFd mark cho một trang riêng để ta có thể tiện để có thể clone về và sử dụng. Các bạn có thể tham khảo tại đây
Và để có thể sử dụng các Theme này bên trong CTFd, ta sẽ cần phải biết đường dẫn của Theme, tại thư mục CTFd, theme sẽ được đặt tại CTFd\themes
Tại đây thì ta thấy được cơ bản CTFd cung cấp cho ta 02 themes và một trong quản trị admin

Mình sẽ lấy một Theme làm ví dụ, tại đây mình sẽ lấy Theme này để làm ví dụ (tại vì nó đẹp)
Một cấu trúc file Theme cơ bản sẽ có các thành phần sau:

Việc của chúng ta chỉ cần đem folder này ném vào trong CTFd\themes là thành công

Lưu ýTùy vào từng theme mà họ sẽ có những cách cài đặt khác nhau, và đây chỉ là cài đặt Theme cơ bản, mỳ ăn liền nên sẽ dễ tiếp cận với các bạn mới. Tuy nhiê nếu muốn tùy biến thì các bạn có thể tham khảo thêm trên docs của CTFd
Sau khi cài xongg rồi chúng ta sẽ vào phần config theo đường dẫn sau: <url thi>/admin/config và kéo xuống phần Appearance/Theme tại đây chúng ta đã thấy có Theme chúng ta đã thêm vào

Click chọn và nhấn Update, thoát ra trang chủ thì ta sẽ thấy sự thay đổi

Plugins
Cũng giống như Themes, các Plugins cũng sẽ có một đường dẫn để chứa hết tất cả các Plugins, đường dẫn của nó sẽ nằm chung với thư mục cha của Themes

Tại phần Plugins mình sẽ Setup bao gồm các thứ như sau:
- Discord firstblood
- Scoring
- Dynamic instance cho các challenge Web
Discord firstblood
Đa phần các giải CTF đều sẽ có một con bot chuyên cho việc thông báo First Blood,tương tự như thế này

Để tạo được một bot như vậy thì tại đây mình sẽ dùng ctfd-discord-webhook-plugin của sigpwny, và đương nhiên là tất cả plugins này mình sẽ lấy trên Github tại mình quá noob để có thể dev ra những cái Plugins giống vầy
Để cài đặt, ta sẽ clone về thư mục Plugins
git clone https://github.com/sigpwny/ctfd-discord-webhook-plugin.gitSau khi clone về thành công thì ta sẽ cần tới Discord webhook url, để lấy được Webhook URL thì chúng ta chỉ cần vào Discord đến kênh chúng ta muốn sử dụng để thông báo Firstblood chọn vào phần setting của kênh

Và chọn click vào theo thứ tự như hình bên dưới

Sau khi có được Webhook URL, ta sẽ sử dụng để cấu hình cho bot. Để cấu hình, ta sẽ vào bên trong file docker-compose.yml của CTFd để config.
Tại phần services/ctfd/environment ta sẽ thêm các dòng lệnh dưới đây để có thể thêm biến môi trường để bot có thể hoạt động
- DISCORD_WEBHOOK_URL="webhook_của_bạn"
- DISCORD_WEBHOOK_LIMIT="Số lượng người giải được"
- DISCORD_WEBHOOK_MESSAGE="Thông báo bạn muốn khi thông báo như thế nào"Như ví dụ dưới đây thì mình sẽ có setting như sau:
- DISCORD_WEBHOOK_URL=https://discord.com/api/webhooks/1340061336134221834/A49eG4cvNKDALom_bWyksYvhBKq6RT4t6x3BYS5e8edSqQ8pK8OD4nDEWM5DJ8eycV4o
- DISCORD_WEBHOOK_LIMIT="1"
- DISCORD_WEBHOOK_MESSAGE=Chúc mừng \"{team}\" cho \"{fsolves}\" trên challenge \"{challenge}\"Sau khi đã setup xong, chúng ta sẽ restart lại docker
# 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 bằng cách thử tạo ra một Challenge rồi thử tính năng


Scoring
Về phần Scoring, thường thì phần này mọi người sẽ bỏ qua tại mọi người thường sẽ sử dụng Scoring của CTFd luôn, tuy nhiên thì sau khi mình đọc một bài nghiên cứu nói về Scoring của CTFd thì biểu đồ của CTFd nhìn không ổn tí nào, vì thế nên mình sẽ apply thêm motojcasi scoring khác trong hệ thống CTFd của mình
Đây là biểu đồ của CTFd điểm giảm:

Và đây là bản mod của sigpwny

Vào trong thư mục plugin, chúng ta sẽ cấu hình như sau:
git clone https://github.com/sigpwny/ctfd-dynamic-challenges-mod.git dynamic_challenges_mod Sau đó thực hiện việc restart lại docker
# 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 -aDynamic Docker Instance
Vấn đề được đặt ra khi trong một giải đấu CTF đó chính là làm sao để hệ thống Challenge được host trên nền tảng luôn được trong trạng thái ổn nhất, đặc biệt các thử thách web challenge rất dễ bị tấn công bruteforce hoặc chiếm quyền điều khiển để đổi Flag trên hệ thống, vì thế Dynamic Docker instance được sinh ra để có thể cung cấp cho mỗi team một docker riêng cho thử thách để tránh việc ảnh hưởng tới các team khác
Để sử dụng, chúng ta sẽ tiến hành cài đặt. Trên trang github của author cũng ghi khá rõ về các bước thực hiện, tuy nhiên để tránh mất thời gian lòng vòng thì mình sẽ hướng dẫn luôn cho các bạn
- Git clone repo về thư mục
plugins
git clone https://github.com/phannhat17/CTFd-Docker-Plugin.git containersSau khi clone về xong, ta sẽ tiến hành set up, tại đây có hai cách set up
- Setup sử dụng socket docker của CTFd
- Setup sử dụng SSH qua một máy host đề khác
Socket Docker
Tại đây thì cách này khuyến khích không nên dùng, vì khi kết nối Socket docker của máy host CTFd đồng nghĩa vói việc bạn sử dụng máy host CTFd làm máy host đề,
Điều này vẫn được nhưng không phải là Best Practice dựa trên doc của Docker, nhưng mà cứ làm đi =)))
Để làm điều này thì trong docker-compose.yml ta sẽ thêm phần sau đây vào services/ctfd/volumes
- /var/run/docker.sock:/var/run/docker.sockRồi sau đó sẽ chạy build lại docker là được. Sau khi restart thì ta có thể thấy rằng thanh kết nối reachable có nghĩa là đã thành công

Bây giờ chỉ việc spawn Docker challenge trên máy đang chạy CTFd là được rồi nhé :>
SSH Docker
Tại đây thì nó sẽ phức tạp hơn một chút, vì chúng ta phải cấu hình máy đang chạy CTFd kết nối được tới máy host đề
Giả sử mình có hai máy sau:
- Máy chạy CTFd: 35.229.144.39
- Máy chạy chứa đề Docker đề web: 35.221.234.224
Các bước thực hiện như sau:
- Tạo SSH key pair trên máy chạy CTFd:
ssh-keygen -t rsa -b 4096 -f ~/.ssh/id_rsa- Copy Public key tới máy host đề. Mục đích để vào SSH mà không bị hỏi password
ssh-copy-id -i ~/.ssh/id_rsa.pub <tên user>@<IP máy host đề>CẢNH BÁOKhi copy thì có thể sẽ được hỏi fingerprint các bạn nhấn yes luôn nhé
- Cho thông tin vào known_host, từ máy CTFd, ta sẽ tiến hành kết nối
SSHtới máyhost đề
ssh <tên user>@<IP máy host đề>Mình sẽ được hỏi fingerprint như sau đây thì chỉ cần type yes:

- Cấu hình
~/.ssh/configbằng cấu hình sau:
Host <IP server>
HostName <IP server>
User <tên để login>
IdentityFile ~/.ssh/id_rsaNhư cấu hình của mình thì ở đây sẽ là:
Host 35.221.234.224
HostName 35.221.234.224
User lmao
IdentityFile ~/.ssh/id_rsa- Vào trong thư mục chứa
docker_compose.ymlvà thực hiện các câu lệnh sau:
mkdir ssh_config
cp ~/.ssh/id_rsa ~/.ssh/known_hosts ~/.ssh/config ssh_config/
- Vào bên trogn
docker-compose.ymlvà thêm các câu lệnh sau tai phầnservices/ctfd/volumes
- ./ssh_config:/root/.ssh:roSau đó tiến hành restart lại Docker:
docker compose down
docker compose upSau đó thì vào và điền thêm SSH như trong ảnh rồi ta nhấn Submit sẽ thấy được connect status Reachable như hình

Một khi đã reachable thì ta sẽ test thử một challenge bằng docker. Tại đây mình đã chuẩn bị sẵn một bài CTF, build lên và tiến hành test.
Tại phần tạo Challenge, chúng ta sẽ sử dụng containers, và cấu hình như sau:
Images: Image docker mà bài bạn muốn hostConnection type: Loại kết nốiPort: đây là phần khá quan trọng, để kiểm tra Port mapping cho đúng thì ta sẽ sử dụng câu lệnh sau:
docker ps -a #sau đó tìm đúng tên containerNhư ta thấy bài CTF của chúng ta đang muốn host đang sử dụng port 8386 nghe từ tất cả IP tới port 8386 của container, thì chỉ cần điền phần port 8386 vào thôi


Sau đó thì create như bình thường, vào challenges để xem thì ta có giống dưới đây


Kiểm tra trên máy host đề, ta có container được tạo như sau:

Truy cập thử trang web:

