CTFd动态flag镜像编写

先说点题外话,前天刚把CTFd平台改用docker搭建,以便使用赵今师傅写的支持动态靶机的插件,只需按照

https://blog.csdn.net/fjh1997/article/details/100850756

步骤来即可,搭建过程中碰到一点问题卡了半天:),文章里没有提示,就是这个地方需要填写创建的网络:

之后就可以使用题目镜像来直接部署题目了,但是题目形式首先得是镜像,其次有的题目还可支持动态flag,写这篇文章的目的就是来记录下实现的步骤。

Dockerfile编写

基本指令和作用可以参考:

https://blog.csdn.net/qq_33256688/article/details/80319673
https://www.cnblogs.com/panwenbin-logs/p/8007348.html

通过读一道支持动态flag的题目的Dockerfile文件来学习如何编写:

https://github.com/CTFTraining/lctf_2018_bestphp_s_revenge/blob/e862a5b2ca17a6f955c82bf4a43dbf96e85779ed/Dockerfile

1.FROM php:7.0-fpm-alpine:表明以php:7.0-fpm-alpine为基础镜像进行构建

2.LABEL Author="Virink <virink@outlook.com>"LABEL用于为镜像设置标签

3.COPY files /tmp/:将当前(Dockerfile所在)目录下files文件(夹)拷贝到docker容器的/tmp目录下

4.RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/' /etc/apk/repositories \:运行shell指令,通过语句末尾的\&&以便一次执行多条命令

5.EXPOSE 80:指定和外界交互的端口为80

6.VOLUME ["/var/log/nginx"]:Volume可以绕过默认的联合文件系统,以正常的文件或者目录的形式存在于宿主机上。详细作用可参考:http://dockone.io/article/128

7.CMD ["/bin/sh", "-c", "docker-php-entrypoint"]CMD的作用是在容器启动后进行调用shell指令,可以理解为开机自动启动项;与RUN的区别是RUN用于指定镜像构建时所要执行的命令;

最后一步正是创建动态flag的步骤

创建动态flag

动态flag的存在形式一般有以下三种:文件中、执行readflag、数据库中

文件

linux下,sed命令可以将file中每行的字符串进行替换:

sed -i 's/原字符串/新字符串/' file

export命令可以查看、设置环境变量

那么在docker-php-entrypoint文件中写入:

#!/bin/sh

sed -i "s/flag_here/$FLAG/" flag.php
export FLAG=not_flag
FLAG=not_flag

就会根据当前环境变量的FLAG值来替换掉flag.php中的flag_here,因此还需要在flag.php中设置:

<?php
$flag = flag_here

这样,在Dockerfile目录执行docker build -t test .将Dockerfile文件打包为镜像test,使用安装了动态靶机插件的CTFd平台部署后,该插件在启动靶机时会自动生成flag并应用到环境变量中,这样便实现了生成动态flag,实现过程可以查看插件源码:

1.引入uuid模块来生成flag,该模块可通过MAC地址, 时间戳, 命名空间, 随机数, 伪随机数来保证生成ID的唯一性:

2.设置环境变量:

readflag

先来看下写法:

#!/usr/bin/env bash

echo $FLAG > /flag
chmod u+s /readflag
chmod 400 /flag

export FLAG=not_flag
FLAG=not_flag

首先将环境变量$FLAG写入到/flag中,之后进行权限配置:

1.chmod u+s /readflag : 为/readflag文件加上setuid标志,设置使文件在执行阶段具有文件所有者的权限

2.chmod 400 /flag :将flag文件权限设为文件拥有者只读,群组和其他用户没有任何权限

那么执行./readflag时,就会拥有文件所有者的权限,可以读取/flag

数据库

flag.sh:

#!/bin/bash

# 修改数据库中的 FLAG
mysql -e "CREATE DATABASE IF NOT EXISTS supersqli;USE supersqli; CREATE TABLE IF NOT EXISTS \`1919810931114514\` (\`flag\` varchar(100) NOT NULL) ENGINE=MyISAM  DEFAULT CHARSET=utf8;INSERT INTO \`1919810931114514\` VALUES ('$FLAG');" -uroot -proot

export FLAG=not_flag
FLAG=not_flag

rm -f /flag.sh

打包镜像到Docker Hub

为了方便搜索和下载自己编写的镜像,可以通过以下步骤来实现:

1.到https://hub.docker.com/注册一个账号

2.登录:

docker login -u 用户名 -p 密码

3.更改镜像标签,格式为用户名/标签名

docker tag test 用户名/镜像名

4.推送:

docker push 用户名/镜像名

5.登出:

docker logout

这时就可以在Docker Hub上找到刚上传的镜像了,将其添加描述后就能使用docker search搜索到自己的镜像了以上就是一些基本的创建动态flag镜像的方法,当然还有很多docker的知识没学到,还是要多读Dockerfile8说了复现题目去了:)