前言

上篇文章中我们成功搭建了CTFd平台。为了让平台更加美观、访问体验更好,现在需要优化下我们的平台。

同时针对web、pwn这些动态靶机的题目,制作自己的镜像并部署到CTFd中。

注意了,上篇文章我使用的版本是v2.3.1,这次我同样使用这个版本演示,关于这个版本的汉化、主题都很少,兼容性不行。

建议使用v3.0以上的版本做平台,版本都尽量新一点,一是功能多,二是支持的主题、插件比较多。兼容性好。

汉化

1.下载汉化包

git clone https://github.com/Gu-f/CTFd_chinese_CN.git

这里有很多版本,包含 v2.1.4、v3.0.2、v3.1.0、v3.1.1、v3.4.0、v3.4.1 这几个版本


每个版本使用的方法都不太一样,最好参考github文档来做。

我这里是v2.3.1 好不容易在github找到对应的版本:

https://github.com/eonun/CTFd_themes_cn

作者有提到使用方法:(不仅要替换themes文件,还要替换plugins文件)

2.了解自己的平台是什么版本

打开自己平台的后台,在首页底下有显示版本

3.替换文件

将对应的版本的theme目录替换至CTFd/CTFd/的themes目录即可 (记得备份以免版本不兼容等问题可以还原)

一般的版本操作方法:

#同级目录下执行
mv CTFd/CTFd/themes CTFd/CTFd/themes.bak
cp -R CTFd_chinese_CN/V2.1.4/themes/ CTFd/CTFd/themes

这里是我的版本v2.3.1的操作方法:

下载汉化包

git clone https://github.com/eonun/CTFd_themes_cn.git

备份themes和plugnis

cp CTFd/CTFd/themes CTFd/CTFd/themes.bak
cp CTFd/CTFd/plugins CTFd/CTFd/plugins.bak

导入汉化包

cp -R CTFd_themes_cn/themes_cn/* CTFd/CTFd/themes
cp -R CTFd_themes_cn/plugins_cn/* CTFd/CTFd/plugins

打开平台发现已经汉化了:

美化(主题、插件)

主题

● 仿BUU主题:https://github.com/fjh1997/float_buu
● 像素风格主题:https://github.com/hmrserver/CTFd-theme-pixo
● 题目分类主题(类似于ctfshow、buuoj):https://github.com/frankli0324/ctfd-pages-theme
● 官网主题:https://github.com/CTFd/themes

安装

将下载过来的主题或插件解压放入CTFd/CTFd/目录下的themes或plugins文件夹下。


然后在后台 - 设置 - 外观 找到主题,选择对应的主题即可。


然后更新配置即可。

如果访问首页报错:


大概率就是不支持该版本了(就比如说我这个2.3.1版本,找了很久都没找到兼容的主题)

主题颜色

如果没有主题,也是可以更改颜色的 换个喜欢的颜色然后更新


一些好看的主题

(版本要求v3.3.0)

ctfd-neon-theme

https://gitee.com/yichen115/ctfd-neon-theme

img

img

img

CTFd-theme-pixo

https://gitee.com/yichen115/CTFd-theme-pixo

这个对动态靶机支持不好,字体是真的好看

img

img

插件

● 多选题插件:https://github.com/liuxin2020/ctfd-plugin-multichoice
● 兼容CTFd3.x版本的CTFd-Whale插件:https://github.com/frankli0324/CTFd-Whale
● 汉化包:https://github.com/Gu-f/CTFd_chinese_CN
● 前三血奖励插件:
● 选择题插件(官方版本):
● CTFd结合qqbot播报前三血搭建指南:https://liuxin2020.github.io
● 官网插件:https://github.com/CTFd/plugins

插件在 Plugins 一栏中 选择后按照插件的来配置即可。

自定义页面

网页 - 所有页面 里 编辑首页,可以更改首页的内容,也可以新建几个页面,丰富一些功能。

都是html语法,根据自己的需求DIY。


需要上传图片点击资料库上传


然后重新打开,选择上传的图片会有链接显示,将链接复制到你的img标签里即可


国内有很多CTF平台都是用CTFd搭建,比如buuoj ctfshow等,可以参考参考它们的网页是咋写的,

如果是自己给学校、公司搭个平台前端随便改改就好了,要对外可以搞些宣传图 logo等等。

贴下一个简单的前端:

<div class="row">
<div class="col-md-6 offset-md-3">
<img class="w-100 mx-auto d-block" style="max-width: 500px;padding: 50px;padding-top: 14vh;" src="files/440dadad42d852a3fa28c08a82234dc8/aj4eg-i1kqp.jpg" />
<h3 class="text-center">
<p>Welcome to WZZCTF</p>
<p>There is the test area!!</p>
</h3>
</div>
</div>


效果还可以hh

动态靶机镜像制作以及部署

Java镜像模板

*转载自https://www.yuque.com/dat0u/ctfd/wcsg47

介绍

一个Java动态靶机镜像构建模板,用于CTFd搭建构建动态靶机镜像,本篇以2021年东华杯ezgadget作为例子

项目地址:https://github.com/LxxxSec/CTFd-JavaWeb-Template

随缘更新~

演示

docker镜像:lxxxin/dhctf_2021_web_ezgadget

img

img

如何使用

镜像构建

首先将本项目clone下来

git clone https://github.com/LxxxSec/CTFd-JavaWeb-Template

进入Template目录

cd Template

目录如下:

img

其中_files文件夹内存放了三个文件

  • flag.sh:设置动态flag的脚本

  • start.sh:启动JavaWeb的脚本

  • flag:flag文件

其中src文件夹内存放jar包

img

使用时,放入替换src目录中的jar包

然后修改Dockerfile文件中的jar包文件名,并且根据自己的Tomcat等Web服务器端口情况开放

img

同理,修改_files目录下的start.sh的jar包文件名

img

进入到Template目录,使用下方的命令构建镜像(最后的点号不要漏掉!)

docker build -t 你的昵称/镜像名称 .

构建完成后,建议本地启动验证一下,防止push到dockerhub后有错:

docker run -it -d -p 本地端口:JavaWeb端口 你的昵称/镜像名称

进入本地镜像:

docker exec -it 容器ID /bin/sh

首先在浏览器验证JavaWeb是否能够正常运行

img

然后进入容器执行cat /flag

img

如果返回为空即正常

因为CTFd动态靶机是通过传入环境变量$FLAG实现动态flag的效果,本地因为$FLAG为空,经过替换后自然为空

接下来把镜像push到docker hub即可

docker push 你的昵称/镜像名称
CTFd部署

首先当然需要一个CTFd动态靶场平台

然后进入后台创建题目

img

选择动态镜像

img

分数根据自己需求即可,主要是下面三样设置,一定要配置好,容器内部端口不可以错

img

搭建完成后,不出意外的话,就可以访问了!

img

可以进入自己的云服务器题目对应的容器,动态flag也就生成啦!

img

TODO
  • 对文件夹的权限没有控制好,这个到时候修改

  • 争取支持更多的JavaWeb中间件

PHP镜像模板

目录结构

.
├── docker-compose.yml ##可有可无
├── Dockerfile ##生成镜像的脚本
└── files
├── flag.sh ##FLAG生成文件
└── html
└── index.php ##源码

2 directories, 4 files
index.php
<style type="text/css">
.passwd {
padding: 0 500px;
}
.content{
padding: 0 500px;
}
</style>
<form method="post" action="">
<div class="content">
<p>请输入密码:</p>
</div>
<div class="passwd">
<input type="text" placeholder="密码" name="password">
<input type="submit" value='点我提交'>
</div>
</form>

<?php
include('flag.php');
$password=$_POST['password'];
if(isset($password) && $password == '32767'){
echo '<div class="content"><p>Password is True!'.$flag.'</p></div>';
}else{
echo '<div class="content"><p>密码错误</p></div>';
}

一个简单的密码爆破,正确则返回FLAG

DockerFile
FROM ctftraining/base_image_nginx_php_73

LABEL Author = "Anyyy <anyiguys@qq.com>"
LABEL Website = "www.anyiblog.top"

COPY ./files /tmp/
RUN cp -rf /tmp/html /var/www/ \
&& chown -R www-data:www-data /var/www/html \
&& cp -f /tmp/flag.sh /flag.sh
  • FROM表示基础镜像是从哪里来的 我们这里使用了 ctftraining/base_image_nginx_mysql_php_73 这个镜像,它包含nginx,mysql和7.3版本的php,而是不用自己写nginx.conf配置文件之类的,十分方便。
  • LABEL相当于给这个Dockerfile打上一个标签,标明作者名字,作者邮箱,和博客。
  • COPY就是把当前文件目录里的files文件夹复制到容器内部的/tmp文件夹里。这里要注意这个动作是发生在宿主机和docker容器之间的,要区别去接下来RUN命令里的cp,那里面的cp发生在docker容器内部。
  • 之后的RUN相当在容器内部来执行命令,我们看到把html文件夹以-rf的方式(迭代且覆盖)的方式复制到www文件夹中,并且把flag.sh放到根目录下。修改www-data用户对于html文件夹的权限(php默认的用户貌似就是www-data)
flag.sh
#!/bin/bash
echo \<?php \$flag=\"$FLAG\"\;?\> > /var/www/html/flag.php
export FLAG=not_flag && FLAG=not_flag
rm -rf /flag.sh
  • 将$FLAG变量输入到flag.php,可以输入到任何地方 只需要在flag.sh配置好即可。这里如果是php这类文件要注意用 \ 来转义。

    如果是将flag添加到/flag,那就这样写:

    #!/bin/bash
    echo $FLAG > /flag
    export FLAG=not_flag && FLAG=not_flag
    rm -rf /flag.sh
  • 利用完$FLAG变量后,将变量清除,以免造成别的影响。

  • 运行完后rm -rf 删除自身

如果是 sql 注入这类的题,需要写到数据库中

#!/bin/bash
# 修改数据库中的 FLAG,自定义sql语句把
mysql -e "USE ctf;INSERT INTO Flag VALUES('$FLAG');" -uroot -proot
export FLAG=not_flag
FLAG=not_flag
rm -f /flag.sh
docker-compose.yml
version: "3"

services:
web:
build: .
image: ctftraining/base_image_nginx_mysql_php_73 #这里也可以填你的镜像(得是dockerhub的)
restart: always
ports:
- "0.0.0.0:8302:80"
environment:
- FLAG=flag{demo}
  • 有了docker-compose.yml ,我们就可以用 docker-compose up -d来快速构建容器,因为在文件里已经标明了build ports和environment 相当与代替了

注意,这里flag.sh之所以能被运行是因为 ctftraining 的镜像带着,docker-php-entrypoint 里面有个

if [[ -f /flag.sh ]]; then
source /flag.sh
fi

所以如果不是ctftraining的镜像可能需要自行运行flag.sh。

PWN题、Python题镜像

PWN

Pwn题可以参考这个项目:https://github.com/TaQini/pwn_docker

生成docker镜像

$ ./deploy.py your_pwn_challenge docker_REPOSITORY_name

your_pwn_challenge: ELF类型的题目文件

docker_REPOSITORY_name: Docker镜像名(只允许小写)

举个栗子:

  • 题目位置:/home/TaQini/pwn/hellopwn

  • 镜像名:hellopwn

  • 一键生成镜像:

    $ ./deploy.py /home/TaQini/pwn/hellopwn hellopwn

部署到CTFd平台

CTFd-whale插件安装教程:CTFd-Whale 推荐部署实践

新建题目,选择题目类型为dynamic_docker ,并进行如下配置:

Docker Image: 刚刚生成的镜像名

Frp Redirect Type: Direct

Frp Redirect Port: 9999

Python

Python的应用场景比较多,可以应用到Crypto、Reverse、Misc等。

所以这里贴出一个参考项目以及Dockerfile:

项目https://github.com/CTFTraining/qwb_2019_crypto_copperstudy

Dockerfile

FROM python:2-slim-stretch #这里是python2环境,你也可以在dockerhub找找关于python3的镜像

LABEL Organization="CTFTraining" Author="blus <851579181@qq.com>"
MAINTAINER blus@CTFTraining <851579181@qq.com>

RUN sed -i 's/deb.debian.org/mirrors.tuna.tsinghua.edu.cn/' /etc/apt/sources.list && \
sed -i '/security/d' /etc/apt/sources.list && \
apt-get update -y && \
apt-get install socat -y

COPY copperstudy2.py /app/copperstudy2.py #复制到/app/目录

EXPOSE 10000

ENTRYPOINT socat TCP4-LISTEN:10000,tcpwrap=script,reuseaddr,fork EXEC:"/usr/bin/env python2 -u /app/copperstudy2.py" #如果是python3这里要注意修改python2为3

本地镜像部署

构建镜像

切换目录到已经准备好了的路径下,然后输入

docker build -t <你的镜像名> .


由于Dockerfile需要一个基础的镜像,所以第一次要下载别人的镜像 要等待一会。

完成后输入 docker images 可以看到已经在本地的镜像库里了

调试镜像

*如果无需调试跳过这步即可

映射到本地网页端口

如果是WEB题,我们制作好镜像可以映射到本地的80端口来查看镜像:

docker run -d --name=<随便一个name 会显示在进程中> -p 8302:80 --rm <docker images的镜像>

这里-p是映射端口到本地的80端口,前面一个端口要根据docker-compose.yml里的配置port来设置


显示up就可以访问http://ip/来查看了。(如果访问不到可能是端口被占用,访问8302端口即可)


正常运行。注意本地FLAG是获取不到的,要部署在ctfd才能分配到。

停止docker运行:

docker stop <ID>

删除镜像:

docker rmi <IMG_name>
进入镜像内部查看情况

使用 docker ps 找到镜像对应的ID

然后执行

docker exec -it ID sh

部署至CTFd

由于我们本地服务器的镜像库已经有了这题的镜像,所以这里可以直接导入

挑战 - dynamic_docker



题目信息什么的随便填填,主要是镜像这里:


这里直接填入 docker images 镜像库里的镜像,也就是我们上面创建的新镜像。

然后点击 Create


注意了,动态靶机这里flag不需要设置,会自动分配。

然后完成测试下题目即可:




题目一切正常。docker ps里也是正常运行:

注意事项

本地部署比较方便,并且镜像部署后服务器不需要出网就可以使用。

但是如果当前服务器没有指定的镜像,就会导致题目开不起来,同时别人也用不了你的镜像。

实际上调用dockerhub的镜像就是远程下载到你本地的镜像库,如果你本地原先就有就可以直接用,不过这样做的好处就是保险。

所以这里比较推荐将镜像上传至dockerhub,远程调用任何人都可以使用。

利用Dockerhub镜像库部署

注册dockerhub账号

首先先在dockerhub https://www.docker.com/ 注册一个账号,这个账号用来放置我们上传的镜像,名字尽量取得好记一些因为后续使用要用到你的ID

然后最好是用梯子来访问,这样速度会快一些。


dockerhub可有可无,可以方便查看自己的镜像。

将制作好的镜像上传dockerhub

注意如果要上传dockerhub,你的镜像名需要规范,不能随便填。

1. docker login

首先命令行 docker login 登录自己的账号(username: password: 输入自己的账号密码),这样才能将镜像上传到你的账户


看到success就是登录成功了

2.docker build

这步和上面本地部署是一样的,只是要注意这里的镜像名得是你的 <用户名>/<镜像名>

镜像名保持小写。

比如这样:

docker build -t Hacker/passwdpass .

到时候ctfd选择的镜像就是你这里输入的镜像名。


部署成功即可。

3.docker push

这里将上一步制作好的镜像名上传到dockerhub即可,名字填上一步你填的名字即可。

docker push <IMG_name>


等待上传成功后,此时你的镜像就成功上传到dockerhub了!

(同样有一个docker pull,是用于下载镜像到你本地的镜像库的)

检查dockerhub仓库

访问 https://hub.docker.com/ 登录自己的账户,如果无误那么你将看到自己的镜像:


大功告成,现在开始部署至CTFd

部署至CTFd

挑战 - dynamic_docker



题目信息什么的随便填填,主要是镜像这里:


这里要填入你dockerhub镜像库里的镜像,也就是刚刚 docker push <IMG_name> 的镜像 。

同样的,如果你想使用别人的镜像就填入别人的镜像名,格式要 **<用户名>/<名称>**。

然后点击 Create


同样这里flag不需要设置,会自动分配。

测试:




一切正常。

注意事项

如果题目使用的是dockerhub的镜像,一定要确保服务器出网,DNS要正常!!,否则会出现镜像开不起来的情况。

常见问题

题目页面加载缓慢

*转载自https://www.yuque.com/dat0u/ctfd/vcoic6

vendor加载缓慢

注意:在使用本方法之前请做好备份,本方法使用CTFd3.5.0实测有效,建议使用默认主题的师傅使用本方法。

现象

img

访问时占用很高

img

解决方案

访问的比较慢的这个其实是CTFd/CTFd/themes/core/static/js/vendor.bundle.min.js这个文件

把这个文件下载下来,在Github上新建一个项目,将这个文件传上去

img

然后再jsdelivr这类CDN网站将Github的js链接转换为cdn加速的链接:

img

把转换后的链接复制下来,这个转换后的链接就是js的链接,可以尝试访问一下,应该是比较快的(至少在可接受范围之内)

将CTFd/CTFd/themes/core/templates/base.html中下方这一段代码

<script defer src="{{ url_for('views.themes', path='js/vendor.bundle.js') }}"></script>

修改如下:

  • 此处的src值最好用自己的js链接(防止不同版本有冲突,如果实在懒狗也可以试试我下面这个,记得备份)
<script src="https://cdn.jsdelivr.net/gh/LxxxSec/static@master/vendor.bundle.min.js"></script>

修改后效果如下,快了非常多哦

后台表格加载缓慢

现象

转圈圈,转圈圈

img

这个vendor.bundle.min.js转了20多秒

img

解决方案

这里的vendor.bundle.min.js和前面不一样,前面的是在core目录,后台的是在admin目录

img

和上面的方法一样,自己换一下,我就懒得换了,毕竟我不常点这个页面

fonts.min.css加载缓慢

参考这一篇文章,换成cdn的css即可

自定义flag前缀

*转载自https://www.yuque.com/dat0u/ctfd/oq04e2

注意

在操作前请先备份好自己的源文件!

新版CTFd-Whale已支持在后端修改flag前缀及flag格式

img

问题

默认情况下,flag的形式为:flag{uuid},flag前缀可能不能很好的彰显比赛名称。

解决方案

还是改CTFd-Whale的配置文件,只需要改一个位置即可:

img

flag = "flag{" + str(uuid.uuid4()) + "}"
flag = "ctf{" + str(uuid.uuid4()) + "}"

修改完成之后重启ctfd_ctfd_1容器才能生效哦

docker restart ctfd_ctfd_1

img

image.png

启动容器后没有超链接

*转载自https://www.yuque.com/dat0u/ctfd/ck1031

注意

不保证全版本通用!!!请一定要先备份原有文件!!!

文章最后给出文件修改后的下载地址!

问题现象

旧版本的CTFd-Whale中CTFd启动容器后可能没有超链接,如下图所示,对于参赛选手很不方便

img

解决方案

其实只需要修改一下CTFd-Whale插件中的view.js即可

'<a target="_blank" href="http://' + response.ip + ':' + response.port + '"><p class="card-text">' + response.ip + ':' + response.port + '</p>' + '</a>' +
'<p></p>' +

img

修改完成之后,如下图:

img

img

下面是修改好之后的view.js的下载链接

https://lark-assets-prod-aliyun.oss-cn-hangzhou.aliyuncs.com/yuque/0/2022/js/28160573/1651909636749-cdbfdda4-4ede-4aa6-9640-8af123352982.js?OSSAccessKeyId=LTAI4GGhPJmQ4HWCmhDAn4F5&Expires=1681367572&Signature=co7NFVy8gpNGNMeTjAJwrZ6czEA%3D&response-content-disposition=attachment%3Bfilename*%3DUTF-8%27%27view.js

参考文章

转载的地方文章中都声明了。

感谢师傅们提供的帮助~~~

https://www.v0n.top/2020/05/01/如何正确使用Docker出一道CTF题目/

https://www.cxyzjd.com/article/Cypher_X/115359957

https://www.yuque.com/dat0u/ctfd

结尾End

耗时一周的CTFd平台搭建工作已完结!方便将来要搭建的时候回顾,同时也能给要搭建的人指条明路。

下个文章大概率是几个月后了XD 比较看心情 想写我就会写的!文章对你有帮助的话也可以评论交流~