使用 GZCTF 结合 GitHub 仓库搭建独立容器与动态 Flag 的 CTF 靶场以及基于 Docker 的 Web 出题与部署

本文主要是介绍使用 GZCTF 结合 GitHub 仓库搭建独立容器与动态 Flag 的 CTF 靶场以及基于 Docker 的 Web 出题与部署,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

写在前面

关于 CTF 靶场的搭建(使用 CTFd 或者 H1ve)以及 AWD 攻防平台的搭建,勇师傅在前面博客已经详细写过,可以参考我的《网站搭建》专栏,前段时间玩那个 BaseCTF,发现它的界面看着挺不错的,了解到也是一个开源项目-GZCTF,网上未见有这方面的详细介绍,看了下网上都只是简单说了下怎么搭出 GZCTF 这个靶场的界面,然而对于后续题目的部署并未进行详细的介绍与说明,因此这里分享下自己的部署经验以及可能遇到的问题、注意点与解决方案。

文章开始前给大家分享一个人工智能学习网站,通俗易懂,风趣幽默

人工智能教程icon-default.png?t=N7T8https://www.captainbed.cn/myon/

目录

一、靶场基础搭建

二、靶场基础配置与功能使用

三、Web 题目示例说明

四、Web 题目制作与部署

五、docker 镜像制作、上传、拉取


一、靶场基础搭建

首先我们肯定得把基础的框架搭好,也就是靶场的界面,之前的一般都是直接 git 克隆 github 的项目,这个的话我们是需要先准备两个文件。

参照官方手册:快速上手 - GZ::CTF Docs (gzti.me)

1、文件1:appsettings.json

内容:

{"AllowedHosts": "*","ConnectionStrings": {"Database": "Host=db:5432;Database=gzctf;Username=postgres;Password=<Your POSTGRES_PASSWORD>"},"EmailConfig": {"SendMailAddress": "a@a.com","UserName": "","Password": "","Smtp": {"Host": "localhost","Port": 587}},"XorKey": "<Your XOR_KEY>","ContainerProvider": {"Type": "Docker", // or "Kubernetes""PortMappingType": "Default", // or "PlatformProxy""EnableTrafficCapture": false,"PublicEntry": "<Your PUBLIC_ENTRY>", // or "xxx.xxx.xxx.xxx"// optional"DockerConfig": {"SwarmMode": false,"Uri": "unix:///var/run/docker.sock"}},"RequestLogging": false,"DisableRateLimit": true,"RegistryConfig": {"UserName": "","Password": "","ServerAddress": ""},"CaptchaConfig": {"Provider": "None", // or "CloudflareTurnstile" or "GoogleRecaptcha""SiteKey": "<Your SITE_KEY>","SecretKey": "<Your SECRET_KEY>",// optional"GoogleRecaptcha": {"VerifyAPIAddress": "https://www.recaptcha.net/recaptcha/api/siteverify","RecaptchaThreshold": "0.5"}},"ForwardedOptions": {"ForwardedHeaders": 5,"ForwardLimit": 1,"TrustedNetworks": ["192.168.12.0/8"]}
}

该文件中必须修改的参数:

(1)数据库密码

Password=<Your POSTGRES_PASSWORD>"

(2)用于加密比赛私钥的随机字符串(随便输入一串字符就行了)

"XorKey": "<Your XOR_KEY>"

(3)外部访问地址,可以是 IP 或域名,用于提供给选手访问题目容器的地址

"PublicEntry": "<Your PUBLIC_ENTRY>"

2、文件2:compose.yml

内容:

services:gzctf:image: registry.cn-shanghai.aliyuncs.com/gztime/gzctf:developrestart: alwaysenvironment:- "GZCTF_ADMIN_PASSWORD=<Your GZCTF_ADMIN_PASSWORD>"# choose your backend language `en_US` / `zh_CN` / `ja_JP`- "LC_ALL=zh_CN.UTF-8"ports:- "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 deploymentdepends_on:- dbdb:image: postgres:alpinerestart: alwaysenvironment:- "POSTGRES_PASSWORD=<Your POSTGRES_PASSWORD>"volumes:- "./data/db:/var/lib/postgresql/data"

该文件中必须修改的参数:

(1)初始管理员密码

"GZCTF_ADMIN_PASSWORD=<Your GZCTF_ADMIN_PASSWORD>" 

特别注意:该密码需要满足要求的密码复杂度,至少应包括大小写字母加数字,如果配置文件中设置的密码太简单是无法成功创建管理员这个账户的,默认管理员登录用户名是 Admin。

(2)数据库密码

"POSTGRES_PASSWORD=<Your POSTGRES_PASSWORD>"

文件改好后,都放到某个目录下,对了你需要提前装好 docker 和 docker-compose 。

在该目录下执行如下命令拉取并启动容器:

docker-compose up -d

确保你的 80 端口未被占用,如果你之前开了中间件 nginx、Apache 这些可能就会报错端口被占用,需要停掉再拉取。

拉取后会多出一个叫 data 的文件夹:

访问你前面配置文件 appsettings.json 里填的 "PublicEntry" 那个地址:

没什么问题的话,就可以看到靶场的页面了。

至此,靶场的基本搭建完成。

二、靶场基础配置与功能使用

使用 Admin 管理员账号和 compose.yml 中设置的密码进行登录(必须满足密码的复杂度,否则会提示用户不存在或者密码错误,其实是数据库里压根就没创建这个用户)。

首先肯定是需要新建一个比赛 

里面可以修改的内容如下: 

下面我自己创建的用户或者叫朋友创建的用户进行测试 

都是图形界面化的操作,很容易理解,到处点点就熟悉了,这里不过多赘述。

三、Web 题目示例说明

新建一个题目

选择动态容器,填好一些基础的信息。

最主要的是:容器镜像 * 这里,下面给出一些可以用于测试的镜像:

vaalacat/push_f12glzjin/hctf_2018_warmupctftraining/hbctf_2017_dameixianctftraining/qwb_2019_smarthackerctftraining/buuctf_2018_online_toolctftraining/qwb_2019_uploadctftraining/qwb_2019_supersqli

比如我们使用 vaalacat/push_f12 进行测试:

填好镜像名后,点击创建测试容器。

创建成功后就可以访问题目环境了

题目容器的端口是 32791(随机生成的) 

此时在终端 docker ps 可以看到这个被新创建的容器:

将题目设置为可见的

我们再创建一个用户对这个题目进行测试,创建好后需要先报名参赛,如果没有开启免审核则还需要管理员账号通过下,然后就可以看到比赛题目了。

(这里似乎一个 ip 只能登录一个用户,因为我在 Admin 和 test 用户间切换会影响到另一个用户)

可以看到,新建容器的端口是 32792

终端会发现又多出了一个新建的容器,这些容器间是相互独立的,也就是说每个选手访问的地址不同,题目环境也是相互独立的,flag 也是不同的。 

四、Web 题目制作与部署

写这篇文章最重要的就是我们如何上 web 题目呢?如何生成不同容器的动态 flag?

ok,来到最重要的部分,说白了也就是我们题目该怎么制作?

下面我将带大家一起来制作 docker 镜像,以及将 docker 镜像上传到自己的镜像仓库,最后拉取镜像到自己的靶场。

先给大家看一下至少需要准备哪些文件,文件的位置:

废话少说,上文件:

(1)docker-compose.yml

相比之前的 docker-compose.yml 文件,我们不需要再单独暴露某个端口作为题目的访问端口,同时我们新增了镜像名称和标签信息。

version: "3"
services:web1:build:context: ./web1  # 指定 Dockerfile 所在的构建上下文目录dockerfile: Dockerfile  # 指定 Dockerfile 的名称image: myon6/testweb1:latest  # 为构建的镜像指定名称和标签,需要改成你自己 github 的名字restart: always

我不知道大家对于 github 仓库是否熟悉,我最开始测试的其实是 docker hub 仓库,但是在执行 push 命令的时候一直无法解决超时的问题,无论是开了加速器还是换了 docker 源还是开全局代理都没有解决,解决 pull 命令无法拉取倒是完全可以的,主要是 push 命令有问题,最后还是选择使用 github 的仓库。

首先我们来看看 github 上自己的仓库在哪儿

下面这个 myon6/testweb1 就是我制作好的 docker 镜像,然后 push 到了 github 上的仓库。

好,你大概知道 github 的仓库在哪儿了,我们继续说出题需要的其他文件。

(2)Dockerfile

# 指定基础镜像
FROM php:7.0-fpm-alpine# 删除默认的 web 根目录中的所有内容
RUN rm -rf /var/www/html/*# 将本地的 html 目录复制到容器中
COPY html /var/www/html# 将初始化脚本复制到容器的 /etc 目录中
COPY init.sh /etc/init.sh# 设置权限
RUN chown -R root:root /var/www/html && chmod -R 755 /var/www/html# 设置初始化脚本为可执行
RUN chmod +x /etc/init.sh# 暴露 web 服务器的端口
EXPOSE 80# 使用初始化脚本来启动容器
ENTRYPOINT ["/etc/init.sh"]

这里其实应该做一个权限控制,因为直接给 root 还是有一定风险在里面,比如 docker 逃逸。

 (但是我在测试中给 www-data 权限会导致 flag 无法成功写入根目录,后面再继续研究)

(3)初始化脚本 init.sh

#!/bin/sh# Write the value of GZCTF_FLAG environment variable to /flag
echo "$GZCTF_FLAG" > /flag
chmod 444 /flag# Unset the GZCTF_FLAG environment variable
unset GZCTF_FLAG# Start the PHP built-in web server
php -S 0.0.0.0:80 -t /var/www/html

这个脚本是最容易出问题,也是当时折腾我最久的,最好不要使用 Windows 相关的东西去编辑这个初始化脚本,否则可能会导致 init.sh 文件中包含 Windows 风格的换行符 ^M:

这些字符会导致 Unix 系统无法正确解释脚本文件的内容,那么你在创建容器的时候就会遇到容器一直处于 restarting 的状态,无法看到映射的端口,实际就是容器刚启动就崩溃掉了。

当然我们也可以在 Dockerfile 中使用工具来处理这个问题:

# 安装 dos2unix 工具以转换脚本格式
RUN apk add --no-cache dos2unix# 使用 dos2unix 转换脚本格式
RUN dos2unix /etc/init.sh

只要你操作得当,就不会遇到这个容器崩溃的问题,就可以不用加上面的内容。

(4)html 文件夹

这个就是大家很熟悉的题目环境文件了,我这里只做测试,因此就放了一个 index.php。

五、docker 镜像制作、上传、拉取

准备好上面说的文件后,在 web 目录下,使用 docker-compose build 来构建镜像:

docker-compose build

构建成功 

使用 docker images 查看镜像:

可以看到 myon6/testweb1

但是这是我们本地的镜像,我们需要将镜像标记为 GitHub Container Registry 的格式:

使用 docker tag 命令,注意一定要修改成你自己 github 账户的名字

docker tag myon6/testweb1:latest ghcr.io/myon5/myon6/testweb1:latest

可以看到现在就有了一个叫 ghcr.io/myon5/myon6/testweb1 的镜像 

我们将这个镜像 push 到 github 仓库,首先你需要先登录 github 账号:

关于这个 key 在哪里获取,就是在 github 的扩展设置里生成你自己账户的 token 用于验证。

echo <your_key> | docker login ghcr.io -u <your_username> --password-stdin

注意生成的 token 权限需要允许上传 packages,勾上。

 

登录成后就可以上传镜像到自己的仓库了:注意替换成自己账号

docker push ghcr.io/myon5/myon6/testweb1:latest

为了给你们再演示一遍我是删掉了原来仓库的东西重新构建上传的 

默认是私有的,如果你要所有人都能直接拉取到,需要设为 public:

至此,我们成功将镜像从本地上传到了 github 公开镜像。

接下来我们就可以在靶场-题目管理-容器镜像里填上我们题目镜像的名字了,然后创建容器。

这个是我自己做的一个简单题目

直接截断就可以 RCE ,命令执行成功

可以看到根目录下已经成功创建了 flag

为什么端口不一样了,因为我前面测试的是 www-data 用户,发现 flag 无法成功写入根目录,下面是 root 权限:

这也是我前面说的对用户权限的控制其实我还没有调整好,一般我们给 nobody 是最安全的,或者给 www-data,但是我试了这两个都有点问题,权限给高倒不是怕它影响到其他选手,因为每个容器是独立的,无论它怎么玩,就算把 flag 删了都没事,但是就担心它从 docker 容器里逃逸到服务器本地,所以还需要继续调整吧。

下面是测试不同用户选手访问不同端口,读取到的 flag 都是不同的:

经测试,两个 flag 都可以正确提交。

关于 flag 的随机生成规则我们也是可以进行设置的:

至此,我们实现了独立容器、动态 flag 的 web 题目制作与部署。

关于 GZCTF 那些界面的操作、功能点、设置等都是图形化的,我也不做过多介绍,大家到处点点就熟悉了。关于那种直接放附件的题,静态 flag 的,比如杂项、逆向这些和 CTFd、H1ve 方法一样,那么对于 web 题目的部署,我上面讲的是自己部署的方法以及注意事项,其实也就是新增了一个初始化 flag 的脚本,对于 pwn 题我目前还没试过,看了下官方给的示例是结合 xinetd 来部署的,应该和 web 题类似,大家自行摸索,如果不知道 xinetd 是什么,那么还是建议你先去看一下我前面介绍使用 xinted 部署 pwn 题的文章,也在专栏 《网站搭建》 里面。

创作不易,期待大家的关注与支持!

这篇关于使用 GZCTF 结合 GitHub 仓库搭建独立容器与动态 Flag 的 CTF 靶场以及基于 Docker 的 Web 出题与部署的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1129139

相关文章

闲置电脑也能活出第二春?鲁大师AiNAS让你动动手指就能轻松部署

对于大多数人而言,在这个“数据爆炸”的时代或多或少都遇到过存储告急的情况,这使得“存储焦虑”不再是个别现象,而将会是随着软件的不断臃肿而越来越普遍的情况。从不少手机厂商都开始将存储上限提升至1TB可以见得,我们似乎正处在互联网信息飞速增长的阶段,对于存储的需求也将会不断扩大。对于苹果用户而言,这一问题愈发严峻,毕竟512GB和1TB版本的iPhone可不是人人都消费得起的,因此成熟的外置存储方案开

中文分词jieba库的使用与实景应用(一)

知识星球:https://articles.zsxq.com/id_fxvgc803qmr2.html 目录 一.定义: 精确模式(默认模式): 全模式: 搜索引擎模式: paddle 模式(基于深度学习的分词模式): 二 自定义词典 三.文本解析   调整词出现的频率 四. 关键词提取 A. 基于TF-IDF算法的关键词提取 B. 基于TextRank算法的关键词提取

使用SecondaryNameNode恢复NameNode的数据

1)需求: NameNode进程挂了并且存储的数据也丢失了,如何恢复NameNode 此种方式恢复的数据可能存在小部分数据的丢失。 2)故障模拟 (1)kill -9 NameNode进程 [lytfly@hadoop102 current]$ kill -9 19886 (2)删除NameNode存储的数据(/opt/module/hadoop-3.1.4/data/tmp/dfs/na

Hadoop数据压缩使用介绍

一、压缩原则 (1)运算密集型的Job,少用压缩 (2)IO密集型的Job,多用压缩 二、压缩算法比较 三、压缩位置选择 四、压缩参数配置 1)为了支持多种压缩/解压缩算法,Hadoop引入了编码/解码器 2)要在Hadoop中启用压缩,可以配置如下参数

Makefile简明使用教程

文章目录 规则makefile文件的基本语法:加在命令前的特殊符号:.PHONY伪目标: Makefilev1 直观写法v2 加上中间过程v3 伪目标v4 变量 make 选项-f-n-C Make 是一种流行的构建工具,常用于将源代码转换成可执行文件或者其他形式的输出文件(如库文件、文档等)。Make 可以自动化地执行编译、链接等一系列操作。 规则 makefile文件

如何用Docker运行Django项目

本章教程,介绍如何用Docker创建一个Django,并运行能够访问。 一、拉取镜像 这里我们使用python3.11版本的docker镜像 docker pull python:3.11 二、运行容器 这里我们将容器内部的8080端口,映射到宿主机的80端口上。 docker run -itd --name python311 -p

第10章 中断和动态时钟显示

第10章 中断和动态时钟显示 从本章开始,按照书籍的划分,第10章开始就进入保护模式(Protected Mode)部分了,感觉从这里开始难度突然就增加了。 书中介绍了为什么有中断(Interrupt)的设计,中断的几种方式:外部硬件中断、内部中断和软中断。通过中断做了一个会走的时钟和屏幕上输入字符的程序。 我自己理解中断的一些作用: 为了更好的利用处理器的性能。协同快速和慢速设备一起工作

使用opencv优化图片(画面变清晰)

文章目录 需求影响照片清晰度的因素 实现降噪测试代码 锐化空间锐化Unsharp Masking频率域锐化对比测试 对比度增强常用算法对比测试 需求 对图像进行优化,使其看起来更清晰,同时保持尺寸不变,通常涉及到图像处理技术如锐化、降噪、对比度增强等 影响照片清晰度的因素 影响照片清晰度的因素有很多,主要可以从以下几个方面来分析 1. 拍摄设备 相机传感器:相机传

阿里开源语音识别SenseVoiceWindows环境部署

SenseVoice介绍 SenseVoice 专注于高精度多语言语音识别、情感辨识和音频事件检测多语言识别: 采用超过 40 万小时数据训练,支持超过 50 种语言,识别效果上优于 Whisper 模型。富文本识别:具备优秀的情感识别,能够在测试数据上达到和超过目前最佳情感识别模型的效果。支持声音事件检测能力,支持音乐、掌声、笑声、哭声、咳嗽、喷嚏等多种常见人机交互事件进行检测。高效推

动态规划---打家劫舍

题目: 你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。 给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。 思路: 动态规划五部曲: 1.确定dp数组及含义 dp数组是一维数组,dp[i]代表