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.git
Sau 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 -a
Kiể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 -a
Dynamic 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 containers
Sau 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.sock
Rồ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
SSH
tớ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/config
bằng cấu hình sau:
Host <IP server>
HostName <IP server>
User <tên để login>
IdentityFile ~/.ssh/id_rsa
Như 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.yml
và 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.yml
và thêm các câu lệnh sau tai phầnservices/ctfd/volumes
- ./ssh_config:/root/.ssh:ro
Sau đó tiến hành restart lại Docker:
docker compose down
docker compose up
Sau đó 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 container
Như 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: