GZCTF平台搭建相关知识
GZCTF平台搭建
环境:
1 | Ubantu22.04.1 |
GZCTF官方文档: https://docs.ctf.gzti.me/zh/quick-start
一. 安装Docker和Docker-compose
1 | sudo apt update |
执行命令后, 检查是否成功安装
1 | docker -v |
二. 部署GZCTF
0x01.创建GZCTF部署目录
1 | cd / |
0x02. 编辑GZCTF配置文件appsettings.json, docker-compose.yml并保存于 /GZCTF 目录下
appsettings.json:
1 | <Your POSTGRES_PASSWORD>设置为数据库密码 |
1 | { |
:
1 | <Your POSTGRES_PASSWORD> 设置为数据库密码, 与上文json文件的一致即可 |
1 | version: "3.0" |
0x03. 启动GZCTF
1 | #在docker-compose.yml所在目录 |
但是启动之前需要换源,因为未知原因国内大部分docker镜像站都不可用了
0x04.在wsl搭建时遇到了问题
当我在/mnt文件夹也就是本机和ubuntu互通文件夹下运行时出现了db一直重启无法启动的问题, 产生这个问题是在WSL中运行Docker时,PostgreSQL容器因挂载目录的权限问题无法启动。根本原因是WSL挂载的Windows目录(如/mnt/c/...
)默认权限限制较严格,导致容器内的PostgreSQL用户(UID 999)无法修改目录权限。以下是解决方案:
方法一:将数据目录移到WSL的Linux文件系统中
避免使用Windows路径挂载
将docker-compose.yml
中的挂载路径改为WSL内部的Linux路径(如~/data/db
),而非Windows挂载路径(如/mnt/c/...
)。例如:yaml
复制
1
2
3
4volumes:
- "./data/db:/var/lib/postgresql/data"
# 改为WSL内部的路径,例如:
# - "/home/your_user/data/db:/var/lib/postgresql/data"确保目录权限
在WSL终端中执行:bash
复制
1
2mkdir -p ./data/db
chmod 777 ./data/db # 临时放宽权限(生产环境需细化权限)然后重新启动容器。
三. docker走本机代理
1 | vi /etc/docker/daemon.json |
修改 Docker 代理配置
修改配置文件(如果没有就创建)
1
2
3mkdir /etc/systemd/system/docker.service.d
touch /etc/systemd/system/docker.service.d/proxy.conf
vim /etc/systemd/system/docker.service.d/proxy.conf
按照以下模板修改代理的 IP 和 端口号信息:
1
2
3[Service]
Environment="HTTP_PROXY=http://192.168.31.1:7890"
Environment="HTTPS_PROXY=http://192.168.31.1:7890"加载配置,重启 Docker
1
2
3
4
5
6# 加载配置
systemctl daemon-reload
# 重启docker
systemctl restart docker
# 查看代理配置是否生效
systemctl show --property=Environment docker
到这里你已经成功了99%接下来
1 | docker compose up -d |
你会看到这两个容器
四. 进入靶场, 登陆管理员
1 | 账户:admin |
如果出现了没有admin账号或者登不上去的情况
1. 先在靶场页面上创建一个用户
2. 进入服务器执行如下命令
1 | docker compose exec db psql -U postgres |
再执行该条语句
1 | \c gzctf |
执行数据库语句, 比如(your_admin_user_name改为上文创建用户的用户名)
1 | UPDATE "AspNetUsers" SET "Role"=3 WHERE "UserName"='your_admin_user_name'; |
再次登入这个用户就可以进入管理页面了
五. 创建比赛, 编辑题目
0x01. Web动态Flag题目部署
01. 创建如下结构目录(这里只做一个演示)
1 | +-- src |
接下来分别讲解每个文件的用处
02. index.php
1 |
|
03. flag.sh
1 |
|
官方文档中提到, 容器采用 $GZCTF_FLAG 环境变量进行注入(通俗易懂的讲, 就是GZCTF会生成一个Flag放在 $GZCTF_FLAG 环境变量中), 所以我们只要把 $GZCTF_FLAG 放到我们想放的位置就可以了
所以就采用如上命令, 把预先留的flag{testflag}替换为 $GZCTF_FLAG 的值
export GZCTF_FLAG=””这一句的用处, 我觉得是, 为了防止从环境变量中得到Flag, 从而绕过了原本题目
踩坑:
当时我是利用windows系统创建的flag.sh文件然后再拖入到ubuntu中的,结果每次flag.sh文件的执行都有各种问题,解决方案就是在ubuntu中创建,然后把内容复制到ubuntu的flag.sh文件中就可以了
04. Dockerfile
1 | FROM ctftraining/base_image_nginx_php_73 |
上文选用了 ctftraining/base_image_nginx_php_73 来作为基础镜像, 该镜像可以自动运行flag.sh帮助实现动态Flag, 关于该镜像的更多信息可以通过如下仓库
1 | https://github.com/CTFTraining/base_image_nginx_php_73 |
这里再提一句, GZCTF中, Dockerfile不需要写 EXPOSE 来暴露端口, 直接在Web页面创建题目时填写即可, 如果写了反而会导致占用端口资源等问题
05. 创建镜像
1 | 在Dockerfile所在目录下, 运行 |
name为dockerhub名(当然如果你不push到DockerHub上这里乱写也行)
testweb为镜像名(自定义)
“.”为版本号,代表latest
1. 查看镜像
1 | docker images |
3.添加代理
想要push到仓库,我们如果虚拟机是nat模式就需要配置代理
1 | sudo su |
这里的 ip 就是 VMnet8 的 ip,端口是代理的端口
通过 curl www.google.com 测验代理是否成功
2. push镜像
1 | docker login |
0x01. 进入GZCTF平台, 部署题目
01. 创建比赛
02. 创建题目时, 选择动态容器
03. 设置容器镜像
容器镜像填入刚刚我们push上去的地址(即上文框出的地址, name/web1),
服务端口根据传入的容器需求填写(即容器对外开放的端口)
剩下的参数自行决定
04. 设置Flag生成规则
点击上文界面的编辑附件及flag
如果没有需求, 直接这样也可以, 有更多需求可以查看官方文档
六. 如果需要连接数据库
由于镜像
1 | ctftraining/base_image_nginx_mysql_php_73 |
内置mysql并且已经和初始化存在一个ctftraining表供我们利用
我们只需要对应添加flag进数据库即可
1 | flag.sh |
1 | Dockerfile |
七. 常用docker命令
0x01. docker重启容器
1 | docker restart 名称/ID #重启容器,保留状态和数据。 |
0x02. docker删除镜像
1 | docker rmi 名称/ID #删除已经生成的镜像 |
0x03. docker停止并删除容器
1 | docker stop 名称/ID #停止容器 |
0x04. docker打包镜像
1 | docker save 镜像名 > xxx.tar |
0x05. docker解压镜像
1 | docker load -i image.tar |
0x06. docker启动镜像
1 | docker run -d -p 8080:80 -e GZCTF_FLAG=flag{111} image_name |
0x07. docker进入到容器内部
1 | docker exec -it 容器id /bin/sh |
参考文章: