About
ctf-docker-template 是一个用于支持动态 Flag 的Docker容器模板项目,支持主流的各类CTF平台.
项目存有一定局限性,但已可适用于绝大多数初中级别题目的命题需求。
本仓库内的Docker容器模板支持的 FLAG 注入类型如下:
$FLAG
(CTFd,NSSCTF)$GZCTF_FLAG
(GZCTF)$DASCTF
(DASCTF)
Structure
在一般情况下,每个模板的文件结构如下:
.
├── README.md
├── Dockerfile
├── config # Web容器 中间件配置需要定义的专属
│ └── nginx.conf
├── data # Web容器 且 有数据库需求容器专属
│ └── db.sql
├── docker
│ └── docker-compose.yml
├── service
│ └── docker-entrypoint.sh
└── src
└── main.py
Dockerfile
为docker容器编译文件,用于设计docker容器,可在其中设置换源、增添软件包等等config
文件夹内存放着容器内服务相关的配置文件,如nginx
的配置文件等等data
文件夹内存放着容器内服务相关的配置文件,如nginx
的配置文件等等docker
文件夹内存放与docker有关的文件,如docker-compose.yml
文件,内部已经设置好了端口转发和测试用flag,便于测试容器环境service
文件夹内存放着与服务有关的文件,如docker-entrypoint.sh
用于定义容器的入口点src
文件夹内存放着题目的项目源码,也可以是pwn题目的二进制文件,即为题目的相关文件flag.php
用于直接查看flag文件的测试文件,访问可直接查看当前题目根目录下的flag文件,如果文件不存在则会输出errorshell.php
一句话木马,用于测试web容器稳定性......
Detail
目前支持的各个方向模板和文档如下,每个容器模板均为独立包装,有独立的README文件,请在使用前仔细阅读,如有任何疑问请加入项目中的 CTF-Archives售后快速服务群 联系维护人员获取帮助。
Crypto
python_3.8/3.10-no_socket / with_socket
环境:
提供 Python 3.8 / Python 3.10
的基础环境,并已经添加 pycryptodome
库,并基于项目本身实现相关接口。
实现:当选手连接到对应服务端口(由项目自行定义)的时候,运行 .py项目
with_socket 适用于项目中引入了 socket
等库,需要镜像做到:
选手通过端口连接到容器/靶机 启动项目 项目自行处理会话
no_socket 适用于项目中没有引入 socket
等库,需要镜像做到:
选手通过端口连接到容器/靶机 服务启动项目,生成Python会话 将会话转发给选手的连接
使用:
将py文件/项目放入 ./src
目录后执行后续操作,文件名建议使用 main.py
,便于环境识别,如需更改文件名,请在 ./service/docker-entrypoint.sh
内更改。
sagemath_9.6
环境:
提供 SageMath 9.6
+ Python 3.10.3
的基础环境,并已经添加 pycryptodome
+ gmpy2
库,并基于 socat
实现服务转发,默认暴露端口位于9999
实现:当选手连接到对应端口(默认为9999端口,默认选手使用 netcat
)的时候,运行 .py项目
,并将会话转发至选手的连接
此环境适用于项目中没有引入 socket
等库,并依赖于 SageMath
核心,需要镜像做到:
选手通过端口连接到容器/靶机
服务启动项目,生成SageMath会话
将会话转发给选手的连接
使用:
直接将SageMath文件/项目放入 ./src
目录后执行后续操作,文件名建议使用 main.sage
,便于环境识别,如需更改文件名,请在 ./service/docker-entrypoint.sh
内更改
KOH(NSSCTF_Only)
KOH题目是基于HTTP服务与后端评判系统进行交互的,故题目容器需要启动一个标准的HTTP服务,并对外暴露HTTP服务端口。
为了确保题目能够正常与后端进行交互,HTTP服务需要包含以下路由并进行相应处理:
upload:
@app.route('/upload', methods=['POST'])
def upload():
pass
该路由负责接收用户上传的数据。数据将以表单数据的形式进行上传,参数名为file。
例如,后端向容器内的HTTP服务发送请求的代码如下,其中超时时间为5秒:
requests.post(f'http://{url}/upload', files={
'file': (filename, content)
}, timeout=5)
如果HTTP服务在5秒内正常处理该路由,并且没有异常发生,应返回以下JSON数据:
{
"code": 200
}
如果遇到异常(例如服务异常、连接异常、超时异常、返回值异常),则直接判定此次结果为错误。
(一般情况下,200以外的任何返回代码,我们都记为 错误 )
check:
@app.route('/check', methods=['POST'])
def check():
pass
当后端完成对/upload路由的访问且没有异常时,将访问/check路由。访问示例代码如下:
requests.post(f'http://{url}/check', timeout=10)
超时时间为10秒。靶机需要在此时间内评估用户上传内容的得分情况,并返回JSON结果,例如:
{
"code": 200,
"score": 100
}
如果遇到异常(例如服务异常、连接异常、超时异常、返回值异常),则直接判定此次结果为错误。如果以上过程没有异常,判断过程结束,并将得到的score更新为用户的得分。
判题靶机目前为一人一机,上次判题完成前无法上传新的文件,无需考虑多线程以及资源抢占的情况。
应尽可能保证服务的可用性。对于需要运行时要求的靶机,应使用chroot等沙盒技术来运行独立的进程,以防止用户代码直接控制靶机来控制HTTP服务的返回值。
HTTP返回数据应确保返回头包含Content-Type: application/json头,而不是直接返回JSON字符串。
DockerFile文件说明:
该题为文件上传KOH题,故只需要完成保存文件 比较文件即可判断得分,如果需要进行代码执行,可以参考app.py中注释代码中使用subprocess建立chroot沙盒的方式进行执行。
注意为了安全起见,在Dockerfile中删除了一些包,如有使用需要请手动更改。
RUN rm -f /home/ctf/usr/local/lib/python3.10/sockert.py &&
rm -f /home/ctf/usr/local/lib/python3.10/sockertserver.py &&
rm -rf /home/ctf/usr/local/lib/python3.10/site-package &&
rm -f /home/ctf/usr/local/lib/python3.10/subprocess.py
该靶机为python3靶机,如需使用其他环境,关于chroot部分依然可以参考Dockerfile中对/home/ctf的改造方法(/home/ctf即为沙盒环境根目录)
MISC
pyjail-python_3.10-socat / xinetd
环境:
提供 Python 3.10
的基础环境,并已经添加 pycryptodome
库,并基于 socat
/ xinetd
实现服务转发,默认暴露端口位于9999
实现:当选手连接到对应端口(默认为9999端口,默认选手使用 netcat
)的时候,运行 server.py
,并将会话转发至选手的连接
镜像做到:
选手通过端口连接到容器/靶机 socat
/xinetd
服务检测到连接,启动一个python3
会话python3
通过参数-u /home/ctf/server.py
限制了程序运行时的账户权限为ctf
,然后在限制环境中启动程序socat
/xinetd
将程序会话转发给选手的连接
使用:
将程序文件放入 ./src
目录后执行后续操作,文件名请修改为 server.py
作为文件名,便于镜像定位程序位置
如果需要更改为自己的文件名,需要在 ./config/ctf.xinetd
、./Dockerfile
和 ./service/docker-entrypoint.sh
中进行修改
PWN
ubuntu_16.04 /18.04 / 20.04 /22.04
环境:
提供 Ubuntu 16.04 GLIBC 2.23
/ Ubuntu 18.04 GLIBC 2.27
/ Ubuntu 20.04 GLIBC 2.31
/ Ubuntu 22.04 GLIBC 2.35
的基础环境,并已经添加 lib32z1
+ xinetd
软件包,并基于 xinetd
实现服务转发,默认暴露端口位于9999
实现:当选手连接到对应端口(默认为9999端口,默认选手使用 netcat
)的时候,运行 程序文件
,并将会话转发至选手的连接
镜像做到:
选手通过端口连接到容器/靶机 xinted服务检测到连接,启动一个 chroot
会话chroot
通过参数--userspec=1000:1000 /home/ctf
限制了程序运行时的账户权限,并更改了程序运行时的root根目录环境位置为/home/ctf
,然后在限制环境中启动程序xinted
将程序会话转发给选手的连接
使用:
将程序文件放入 ./src
目录即可,文件名请修改为 attachment
作为文件名,便于镜像定位程序位置
如果需要更改为自己的文件名,需要在 ./config/ctf.xinetd
、./Dockerfile
和 ./service/docker-entrypoint.sh
中进行修改
Web
flask-python_3.8 / 3.10
提供 Python 3.8 + Flask
/ Python 3.10 + Flask
的基础环境,默认暴露端口位于8080
直接将Flask文件/项目放入 ./src
目录即可,Flask项目主文件请使用 app.py
作为文件名,便于环境识别Flask项目位置
如使用了 pycryptodome
等第三方库,请在 ./Dockerfile
内补充pip安装语句
java-openjdk8
提供 Openjdk 1.8.0
的基础环境,默认服务暴露端口由程序决定
适用于基于 jar
程序包部署环境的需求
直接将 jar
程序包放入 ./src
目录即可,jar程序包请使用 app.jar
作为文件名,便于环境识别 jar
程序包
jetty-jdk8
提供 Jetty 9.4.49 Openjdk 1.8.0
的基础环境,默认服务暴露端口由程序决定
适用于基于 war
程序包部署环境的需求
直接将 war
程序包放入 ./src
目录即可,war程序包请使用 root.war
作为文件名,便于环境识别 war
程序包
tomcat-jdk8
提供 Tomcat 9.0.78 Openjdk 1.8.0
的基础环境,默认服务暴露端口由程序决定
适用于基于 war
程序包部署环境的需求
直接将 war
程序包放入 ./src
LAMP-php80 / LNMP-php73 / nginx-php73
Apache2
+PHP 8.0.30
+10.5.21-MariaDB
的基础环境,默认暴露端口位于 80
L: Linux alpine A: Apache2 M: MySQL P: PHP 7.3 PHP MySQL Ext mysql mysqli
Nginx
+PHP 7.3.33
+10.6.14-MariaDB
的基础环境,默认暴露端口位于 80
L: Linux alpine N: Nginx M: MySQL P: PHP 7.3 PHP MySQL Ext mysql mysqli
Nginx
+PHP 7.3.33
的基础环境,默认暴露端口位于 80
直接将 PHP 项目放入 ./src
目录后执行后续操作。
Problems
no_socket with crypto
no_socket
指的是源代码中没有引入socket
相关的库,当希望达到的效果是类似于当用户通过特定端口连接到靶机时,就运行python代码,并将代码的运行界面转发给用户。
如果已经引入了socket
相关的库,请直接使用如python app.py
这类语句启动python程序,并让程序自行监听特定端口。
软件源换源
环境中涉及软件包处理的情形,如apt、yum,均已换源为ustc源,如不处于中国大陆网络环境/启用了全局代理环境,请自行修改相关换源语句,避免由于还原带来的负优化。
日志sh文件错误
由于DOS/Windows 和 Linux/Unix的文件换行回车格式不同,DOS/Windows 的文本文件在每一行末尾有一个 CR(回车)和 LF(换行),而 UNIX 文本只有一个LF(换行),从而造成Linux的Docker出现下面的报错:
/docker-entrypoint.sh: line 2: $'r': command not found
/docker-entrypoint.sh: line 26: syntax error: unexpected end of file
解决方案如下:
sed -i ""s/r//"" docker-entrypoint.sh
即通过正则匹配,直接替换掉 r
字符,不过此方案不一定能完全解决问题。
建议直接在linux下执行 git clone
操作,或者直接从github下载zip版本的源码,避免一些奇奇怪怪的编码问题。
请注意,sed
指令在unix(macos)
下的预期执行效果与linux
下的预期执行效果不同。
推荐站内搜索:最好用的开发软件、免费开源系统、渗透测试工具云盘下载、最新渗透测试资料、最新黑客工具下载……
还没有评论,来说两句吧...