前言

前天搭GZ台子的时候看了很多教程,也踩了很多坑,所以就想记录下自己的安装步骤

一.GZCTF搭建及web环境搭建

1.docker安装(Windows)

1.1docker下载

英文版下载地址:Docker: Accelerated Container Application Development

image-20250615102239913

汉化版下载地址:Release 4.42.0 · asxez/DockerDesktop-CN

如果下载汉化版,还要下载配置文件,到c盘中的安装路径(默认路径安装的话就为C:\Program Files\Docker\Docker\frontend\resources),替换原来的配置文件即可,原配置文件应该是appxxxx.asar这个名字

image-20250615102638343

下载后安装的时候似乎没有其他多余选项了,直接下一步就行,但是路径目前不知道怎么修改,只有装在c盘

安装完成后重启电脑就行

1.2docker配置

首次进入docker会要求登录账户,可以注册一个Docker hub的账户,也可以跳过

然后就去更换拉取的镜像源,默认是从Docker Hub拉取的,但是国内的话,没用magic可能比较慢,所以可以去换个比如阿里云,百度云的镜像源

进入docker,在配置中找到Docker Engine(汉化后就是Docker引擎)

image-20250615103900590

这里阿里云的镜像地址要去自己找,有自己的id

容器镜像服务 ACR 控制台

image-20250615105057510

"registry-mirrors": [
"https://xxxxxxx.mirror.aliyuncs.com",
"https://mirror.baidubce.com"
]

注意json格式不要错了,最后保存即可

可以通过命令来验证

docker info

image-20250615105233549

这样就成功了

也可以简单拉取一个docker容器来验证

docker run hello-world

image-20250615105427124

这样就是配置完成了

2.GZCTF搭建

2.1下载

下载地址:GZTimeWalker/GZCTF: The GZ::CTF project, an open source CTF platform.

服务器上也可以直接通过git拉取,我这里是debian的服务器

git clone https://github.com/GZTimeWalker/GZCTF.git

服务器上也要提前下载docker,我这里就直接用宝塔下载了

2.2配置

下载后进入GZCTF文件夹,添加两个配置文件,注意,这两个文件一定要认真弄,那天就是卡在这里很久,appsettings.json复制使用时要删除注释内容,注意GZCTF使用的是PostgreSQL,而且如果反向代理要弄的话还要修改nginx配置文件

使用反向代理

appsettings.json
{
"AllowedHosts": "*",
"Kestrel": {
"Endpoints": {
"Http": {
"Url": "http://+:80", //这里是做了一个反向代理,80端口被占了
"Protocols": "Http1"
}
},
"Limits": {
"MaxRequestBodySize": 52428800
}
},
"ConnectionStrings": {
"Database": "Host=db;Port=5432;Database=gzctf;Username=postgres;Password=xxxxxx;Pooling=true;"
}, //这里最好是除了密码都不要更改
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"EmailConfig": {
"SendMailAddress": "123@qq.com",
"UserName": "xxx",
"Password": "xxx",
"Smtp": {
"Host": "smtp.163.com",
"Port": 465,
"EnableSsl": true
} //这里是邮箱配置,发送邮件的,如果用不上可以不用管
},
"XorKey": "xxxx", //这里是异或的密钥,必填
"ContainerProvider": {
"Type": "Docker",
"PortMappingType": "Default",
"EnableTrafficCapture": false,
"PublicEntry": "xx.xx.xx.xxx", //这里填写服务器ip(公网地址)
"DockerConfig": {
"DockerUri": "unix:///var/run/docker.sock"
}
},
"RequestLogging": false,
"DisableRateLimit": false,
"RegistryConfig": {
"UserName": "",
"Password": "",
"ServerAddress": ""
},
//谷歌验证码配置
"GoogleRecaptcha": {
"VerifyAPIAddress": "https://www.recaptcha.net/recaptcha/api/siteverify",
"Sitekey": "",
"Secretkey": "",
"RecaptchaThreshold": "0.5"
}
}
docker-compose.yml
services:
gzctf:
image: registry.cn-shanghai.aliyuncs.com/gztime/gzctf:develop
restart: always
environment:
- "GZCTF_ADMIN_PASSWORD=xxxxx" #管理员密码,账号默认为Admin
# choose your backend language `en_US` / `zh_CN` / `ja_JP` ...
- "LC_ALL=zh_CN.UTF-8"
- ASPNETCORE_URLS=http://+:80 # 强制指定监听端口
ports:
- "8080:80" #端口转发,将80端口转到8080端口
volumes:
- "./data/files:/app/files"
- "./appsettings.json:/app/appsettings.json:ro"
# - "./kube-config.yaml:/app/kube-config.yaml:ro" # this is required for k8s deployment
- "/var/run/docker.sock:/var/run/docker.sock" # this is required for docker deployment
depends_on:
- db

db:
image: postgres:alpine
restart: always
environment:
- "POSTGRES_PASSWORD=xxxxxx" #务必和appsettings.json数据库密码一致
volumes:
- "./data/db:/var/lib/postgresql/data"
nginx配置
# GZCTF 的代理配置(单独一个 server 块)
server {
listen 80;
server_name xx.xx.xx.xxx; # 改成你的域名或服务器IP

location / {
proxy_pass http://127.0.0.1:8080; # 指向 GZCTF 的 Docker 端口
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;
}
}

这里由于80端口已经被占用,所以去弄了一个反向代理,就需要在nginx配置文件中新加一个server块,如果不需要,就在上面两个配置文件删除对应配置即可

不使用反向代理

appsettings.json
{
"AllowedHosts": "*",
"ConnectionStrings": {
"Database": "Host=db;Port=5432;Database=gzctf;Username=postgres;Password=xxxxxx;Pooling=true;"
}, //这里最好是除了密码都不要更改
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"EmailConfig": {
"SendMailAddress": "123@qq.com",
"UserName": "xxx",
"Password": "xxx",
"Smtp": {
"Host": "smtp.163.com",
"Port": 465,
"EnableSsl": true
} //这里是邮箱配置,发送邮件的,如果用不上可以不用管
},
"XorKey": "xxxx", //这里是异或的密钥,必填
"ContainerProvider": {
"Type": "Docker",
"PortMappingType": "Default",
"EnableTrafficCapture": false,
"PublicEntry": "xx.xx.xx.xxx", //这里填写服务器ip(公网地址)
"DockerConfig": {
"DockerUri": "unix:///var/run/docker.sock"
}
},
"RequestLogging": false,
"DisableRateLimit": false,
"RegistryConfig": {
"UserName": "",
"Password": "",
"ServerAddress": ""
},
//谷歌验证码配置
"GoogleRecaptcha": {
"VerifyAPIAddress": "https://www.recaptcha.net/recaptcha/api/siteverify",
"Sitekey": "",
"Secretkey": "",
"RecaptchaThreshold": "0.5"
}
}
docker-compose.yml
services:
gzctf:
image: registry.cn-shanghai.aliyuncs.com/gztime/gzctf:develop
restart: always
environment:
- "GZCTF_ADMIN_PASSWORD=xxxxx" #管理员密码,账号默认为Admin
# choose your backend language `en_US` / `zh_CN` / `ja_JP` ...
- "LC_ALL=zh_CN.UTF-8"
- ASPNETCORE_URLS=http://+:80 # 强制指定监听端口
ports:
- "80:80" #对外端口号,前为外部端口
volumes:
- "./data/files:/app/files"
- "./appsettings.json:/app/appsettings.json:ro"
# - "./kube-config.yaml:/app/kube-config.yaml:ro" # this is required for k8s deployment
- "/var/run/docker.sock:/var/run/docker.sock" # this is required for docker deployment
depends_on:
- db

db:
image: postgres:alpine
restart: always
environment:
- "POSTGRES_PASSWORD=xxxxxx" #务必和appsettings.json数据库密码一致
volumes:
- "./data/db:/var/lib/postgresql/data"

2.3运行

以下均在GZCTF目录下运行

启动docker

sudo systemctl start docker

设置开机启动docker

sudo systemctl enable docker

运行docker(-d表示后台运行)

docker-compose up -d

查看docker

docker ps

image-20250615112901548

这里由于我已经初始化了,所以看着没多少,首次应该还是比较多的

看到出现了healthy字样就表示连接成功了,如果是unhealthy,那就慢慢去看log,丢ai找问题吧(那天数据库问题硬控我半天)

查看日志

docker logs gzctf-gzctf-1
docker logs gzctf-db-1

image-20250615113323356

这里的http://+80也可以表示设置80端口成功

访问后大概页面如下(这是我已经更改过的了)

image-20250615113429717

如果要修改docker文件后重启,用以下命令

docker-compose down && docker-compose up -d

3.web题目部署

3.1本地构建

首先有个大概的文件框架如下,大概思路就是本地搭建后上传到hub,在GZCTF上再从hub上拉取下来

image-20250615113930617

以一个简单的web环境举例

Dockerfile

FROM ctftraining/base_image_nginx_mysql_php_56     #使用docker.io上的模板

# 复制整个src目录到容器
COPY src /var/www/html

# 移动并设置flag.sh的权限
RUN mv /var/www/html/flag.sh /flag.sh && chmod +x /flag.sh

flag.sh

#!/bin/sh
sed -i "s/flag{testflag}/$GZCTF_FLAG/" /var/www/html/index.php

export GZCTF_FLAG=""

index.php

<!DOCTYPE html>
<html>
<head>
<title>签到</title>
</head>
<!--flag{testflag}-->
<body>
<?php
echo "Do u want 2 sign??<br>";
?>
</body>
</html>

构建好后进入Dockerfile所在文件夹下命令行

构建镜像(name为docker.io上的用户名,test1为该容器名字,.表示最新版本)

docker build -t name/test1 .

image-20250615114823395

这样就成功了,框的部分就是拉取镜像时需要用的

docker.io/name/test1

PS:这里当时配置镜像源之后还是拉不下来,要请求超时,如果遇到failed to resolve source metadata for docker.io,可以尝试直接先从docker上搜需要的模板,自己pull下来然后再build

3.2远程拉取

登录管理员账号,新建比赛,编辑比赛

image-20250615115355191

新建题目那里如果想要动态flag就选择动态容器,进来之后在下面容器镜像的位置粘贴刚刚的那个镜像再创建测试容器,如果成功了就行

image-20250615115815754

进入环境查看源码如果效果如下

image-20250615120833512

这样就代表成功了,之后的web题就可以类似实现动态flag部署了

4.结尾

搭建到这里就完成了,虽然看了很多教程但是还是踩了不少坑,所以写点文章记录记录,也给后人乘凉

(PS:学长说他之前写过教配置的文章,删了。。。。。。。。。)

环境搭建在http://38.55.99.186/,现在只有一个取证题,学长出了之后没机会展示的,先放那凑凑数,后面有时间了来研究点web题