关于简单部署题目请参考:https://www.cnblogs.com/Cl0ud/p/13783325.html

如果需要进行较复杂部署,可参考本篇

PHP代码审计系列题目的部署,较之前的部署方案,改变的地方除了题目代码之外,还将题目权限进行了限制,题目结构更正规化,基础镜像没有进行修改,还是原来的 php:5.6-fpm-alpine,其不足在于该环境没有php.ini 文件,如果你出题不需要修改这个这一点可以直接忽略,优点在于该环境相比直接使用ubuntu的镜像环境占用的空间更小,这里当然就直接选择使用占用空间更小的php:5.6-fpm-alpine

目录结构如下:

-模板
--dockerfile
--docker-compose.yml
--start.sh
--www(这里面放题目的源代码)
---...
---...

这里以CTFTraining中0ctf_2016_unserialize题目的Dockerfile为例进行讲解:

其题目目录环境为:

FROM php:5.6-fpm-alpine

LABEL Author="Virink <virink@outlook.com>"
LABEL Blog="https://www.virzz.com" COPY files /tmp/ RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/g' /etc/apk/repositories \
&& apk add --update --no-cache nginx mysql mysql-client \
&& docker-php-source extract \
&& docker-php-ext-install mysql \
&& docker-php-source delete \
&& mysql_install_db --user=mysql --datadir=/var/lib/mysql \
&& sh -c 'mysqld_safe &' \
&& sleep 5s \
&& mysqladmin -uroot password 'qwertyuiop' \
&& mysql -e "source /tmp/db.sql;" -uroot -pqwertyuiop \
&& mkdir /run/nginx \
&& mv /tmp/docker-php-entrypoint /usr/local/bin/docker-php-entrypoint \
&& mv /tmp/nginx.conf /etc/nginx/nginx.conf \
&& mv /tmp/vhost.nginx.conf /etc/nginx/conf.d/default.conf \
&& mv /tmp/src/* /var/www/html \
&& chmod -R -w /var/www/html \
&& chmod -R 777 /var/www/html/upload \
&& chown -R www-data:www-data /var/www/html \
&& rm -rf /tmp/* \
&& rm -rf /etc/apk EXPOSE 80 VOLUME ["/var/log/nginx"] CMD ["/bin/sh", "-c", "docker-php-entrypoint"]

简单查看这段dockerfile,很容易注意到这一点:(简单截取一部分

RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/g' /etc/apk/repositories \
&& apk add --update --no-cache nginx mysql mysql-client \

为什么这里要用两个&&而不是直接使用两个RUN

原因在于从 Docker 1.10 开始,COPY、ADD 和 RUN 语句会向镜像中添加新层。前面的示例创建了两个层而不是一个。

镜像的层就像 Git 的提交(commit)一样。

Docker 的层用于保存镜像的上一版本和当前版本之间的差异。就像 Git 的提交一样,如果你与其他存储库或镜像共享它们,就会很方便。

实际上,当你向注册表请求镜像时,只是下载你尚未拥有的层。这是一种非常高效地共享镜像的方式。

但额外的层并不是没有代价的。

层仍然会占用空间,你拥有的层越多,最终的镜像就越大。Git 存储库在这方面也是类似的,存储库的大小随着层数的增加而增加,因为 Git 必须保存提交之间的所有变更

所以在这里我们将其合并成一条命令,就是为了减少其层数而降低占用空间的大小。

现在从头开始阅读Dockerfile代码

FROM php:5.6-fpm-alpine

LABEL Author="Virink <virink@outlook.com>"
LABEL Blog="https://www.virzz.com"

FROM 命令指定基础镜像

LABEL指令用于为镜像添加元数据,多用于声明构建信息,作者、机构、组织等,每一个LABEL指令会生成一个新的镜像层,如果你使用多个label,将导致构建出一个低效的镜像,跟RUN命令类似,同时对我们几乎没啥帮助,可以略过了。

COPY files /tmp/

复制主机当前文件夹下的files文件夹到容器/tmp文件夹下

详细讲解一下RUN命令下的各条指令

sed -i 's/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/g' /etc/apk/repositories

在国内访问 apk 仓库较缓慢,修改docker容器下载源为中科大镜像,加速后面几步的更新和下载

apk add --update --no-cache nginx mysql mysql-client

Alpine 提供了自己的包管理工具 apk,可以通过 https://pkgs.alpinelinux.org/packages 网站上查询包信息,也可以直接通过 apk 命令直接查询和安装各种软件。

这里使用apk进行下载nginx,mysql,mysqli-client

接着是三条:

docker-php-source extract
docker-php-ext-install mysql
docker-php-source delete

关于docker-php-source , docker-php-ext-install ,docker-php-enable-docker-configure,详情参考:https://www.cnblogs.com/yinguohai/p/11329273.html

这里简单介绍:

docker-php-source extract

在php容器中创建一个/usr/src/php目录,里面放了一些自带的文件

docker-php-ext-install mysql

安装并启动PHP扩展,命令格式:

docker-php-ext-install “源码包目录名”

这里即安装并启动了mysql服务

docker-php-source delete

这里对 docker-php-source extract 初始化的 /usr/src/php目录进行了删除

接着是一段mysql的操作

mysql_install_db --user=mysql --datadir=/var/lib/mysql
sh -c 'mysqld_safe &'
sleep 5s
mysqladmin -uroot password 'qwertyuiop'
mysql -e "source /tmp/db.sql;" -uroot -pqwertyuiop

使用mysql_install_db命令初始化MySQL数据库目录

mysql_install_db --user=mysql --datadir=/var/lib/mysql

mysqld_safe是服务端工具,用于启动mysqld,并且是mysqld的守护进程,在后面加&符号令其在后台运行,而因为mysqld_safe是mysqld的守护进程,所以mysqld_safe会在启动MySQL服务器后继续监控其运行情况,并在其死机时重新启动它。

sh -c 'mysqld_safe &'

等待五秒

sleep 5s

一般dockerfile里面的sleep都是为了等待一些服务启动,防止运行到后面的命令时前面的服务还没启动,这样就会导致报错退出,sleep很大程度上降低了出现这种情况的概率。

mysqladmin -uroot password 'springbirdtcl11111'

mysqladmin命令是mysql服务器管理任务的客户端工具,它可以检查mytsql服务器的配置和当前工作状态,创建和删除数据库,创建用户和修改用户密码等操作。

这里用于修改密码了

mysql -e "source /tmp/db.sql;" -uroot -pqwertyuiop

导入并执行sql文件

mkdir /run/nginx
mv /tmp/docker-php-entrypoint /usr/local/bin/docker-php-entrypoint
mv /tmp/nginx.conf /etc/nginx/nginx.conf
mv /tmp/vhost.nginx.conf /etc/nginx/conf.d/default.conf

这一段是创建nginx文件夹以及导入我们自己写的配置文件

mv /tmp/src/* /var/www/html
chmod -R -w /var/www/html
chmod -R 777 /var/www/html/upload
chown -R www-data:www-data /var/www/html

移动源代码到html文件夹下,这样外部可访问

mv /tmp/src/* /var/www/html

进行权限限制

chmod -R -w /var/www/html
chmod -R 777 /var/www/html/upload
chown -R www-data:www-data /var/www/html

-R : 对目前目录下的所有文件与子目录进行相同的权限变更(即以递归的方式逐个变更)

+表示增加权限、- 表示取消权限、= 表示唯一设定权限。

r 表示可读取,w 表示可写入,x 表示可执行,X 表示只有当该文件是个子目录或者该文件已经被设定过为可执行。

这里递归取消了html目录下的可写入权限

因为7的二进制数为111,即递归增加了任意用户对于/upload目录下的读写执行权限

然后将/html目录下的权限限制为www-data权限

rm -rf /tmp/*
rm -rf /etc/apk

删除之前产生的源文件,以及清除apk安装包们

对外暴露80端口

EXPOSE 80

接着声明容器中/var/log/nginx为匿名卷

VOLUME ["/var/log/nginx"]

当Dockerfile中声明了匿名卷但是run的时候没有使用 -v绑定匿名卷的话那么docker就会在/var/lib/docker/volumes这个目录下创建一个目录来绑定匿名卷。

也就是容器内的nginx的log日志会被挂载到主机的/var/lib/docker/volumes的一个新的目录下

最后是

CMD ["/bin/sh", "-c", "docker-php-entrypoint"]

该docker-php-entrypoint文件在原目录的files下,其内容为:

#!/bin/sh

sed -i "s/flag{0ctf_2016_unserialize_is_very_good!}/$FLAG/" /var/www/html/config.php

export FLAG=not_flag
FLAG=not_flag php-fpm & nginx & mysqld_safe & tail -F /var/log/nginx/error.log /var/log/nginx/access.log

其实就是实现动态flag,并且启动相关服务,校内平台暂时还没有用到动态flag,所以暂时不需要考虑该问题。

下面的部分摘抄自v0n师傅的博客(写到这里的时候才发现v0n师傅写过相关的文章了,早知道分析另外一个dockerfile了呜呜呜

摘抄:

从上面的过程中,我们看到对于一道题目来说,除了源码以外,最大的不方便之处就是还要有相关的nginx文件配置,在这里我推荐virink写的base_image_nginx_mysql_php_56来辅助我们快速出题。 这个镜像主要好在不需要我们去配置其他的nginx设置,而且还支持自动导入db.sql文件,支持自动执行flag.sh文件。以我在minil出的一道题为例。题目中主要是需要配置数据库.

我们只需要src文件夹中放入源码、flag.sh、db.sql(flag.sh、db.sql文件名不能变),现在我们dockerfile只需要这么写:

FROM ctftraining/base_image_nginx_mysql_php_56

COPY src /var/www/html

RUN mv /var/www/html/flag.sh / \
&& chmod +x /flag.sh

这个镜像就会自动为我们配置相关的nginx文件,同时自动导入要执行的db.sql文件来配置数据库(默认用户为root,密码也为root,执行后db.sql会被删掉)

同时镜像还会自动执行flash.sh来从环境变量中读取flag写入到flag.php中(需要注意的是,flag.sh必需在根目录下,也就是我们需要执行mv /var/www/html/flag.sh /这一步的原因所在)。 可以看到,这个镜像极大的方便了我们对Dockerfile的编写,把Dockerfile简化到只需要两三句话就能搞定。

如果是要在php7的环境下出题,可以采用base_image_nginx_mysql_php_73

至于python还是java环境的出题,我暂时还没尝试过,就不班门弄斧了。

如果还想通过更多的环境学习如何出题,可以在这个项目中查看更多的题目。

参考链接:

代码审计系列题目CTFD部署(上)的更多相关文章

  1. [代码审计]PHP_Bugs题目总结(1)

    0x00 简介 最近这几天看到了许多关于代码审计的ctf题,在电脑里也翻出来好长时间没看过的php_bugs,干脆最近把这个好好看看! 下载地址:https://github.com/bowu678/ ...

  2. [代码审计]PHP_Bugs题目总结(2)

    写的有点多了,上一篇放在一起显得有点臃肿,就再起一篇吧~ 迷路的老铁点这里:[代码审计]PHP_Bugs题目总结(1) 0x14 intval函数四舍五入 <?php if($_GET[id]) ...

  3. NPM 使用介绍(包管理工具,解决NodeJS代码部署上的很多问题)

    引用地址:http://www.runoob.com/nodejs/nodejs-npm.html NPM 使用介绍 NPM是随同NodeJS一起安装的包管理工具,能解决NodeJS代码部署上的很多问 ...

  4. LeetCode《买卖股票的最佳时机》系列题目,最详解

    目录 说在前面 引例:只能交易一次 一.动态数组定义 二.状态转移方程 三.初始化 四.优化 无限制买卖 一.动态数组定义 二.状态转移方程 三.初始化 四.优化 交易 2 次,最大利润? 一.动态数 ...

  5. C#开发BIMFACE系列48 Nginx部署并加载离线数据包

    BIMFACE二次开发系列目录     [已更新最新开发文章,点击查看详细] 在前一篇博客<C#开发BIMFACE系列47 IIS部署并加载离线数据包>中详细介绍了IIS部署并访问的完整步 ...

  6. C#进阶系列——MEF实现设计上的“松耦合”(二)

    前言:前篇 C#进阶系列——MEF实现设计上的“松耦合”(一) 介绍了下MEF的基础用法,让我们对MEF有了一个抽象的认识.当然MEF的用法可能不限于此,比如MEF的目录服务.目录筛选.重组部件等高级 ...

  7. C#进阶系列——MEF实现设计上的“松耦合”(四):构造函数注入

    前言:今天十一长假的第一天,本因出去走走,奈何博主最大的乐趣是假期坐在电脑前看各处堵车,顺便写写博客,有点收获也是好的.关于MEF的知识,之前已经分享过三篇,为什么有今天这篇?是因为昨天分享领域服务的 ...

  8. 学习ASP.NET Core Razor 编程系列十五——文件上传功能(三)

    学习ASP.NET Core Razor 编程系列目录 学习ASP.NET Core Razor 编程系列一 学习ASP.NET Core Razor 编程系列二——添加一个实体 学习ASP.NET ...

  9. PCIE_DMA实例四:xapp1052在Xilinx 7系列(KC705/VC709)FPGA上的移植

    PCIE_DMA实例四:xapp1052在Xilinx 7系列(KC705/VC709)FPGA上的移植 一:前言 这段时间有个朋友加微信请求帮忙调试一块PCIe采集卡.该采集卡使用xilinx xc ...

随机推荐

  1. 跟我一起学Redis之Redis事务简单了解一下

    前言 关系数据库中的事务,小伙伴们应该是不陌生了,不管是在开发还是在面试过程中,总有两个问题逃不掉: 说说事务的特性: 事务隔离级别是怎么一回事? 事务处理不好,数据就可能不准确,最终就会导致业务出问 ...

  2. 21迁移python项目到另一台电脑

    在虚拟环境中将第三方库打包到一个TXT文件:1,在项目保存在项目所在目录,文件可以自定义.pip freeze> requirements.txt命令2,将requirements.txt放入另 ...

  3. JS缓冲运动案例

    点击"向右"按钮,红色的#red区块开始向右缓冲运动,抵达到黑色竖线位置自动停止,再次点击"向右"#red区块也不会再运动.点击"向左"按钮 ...

  4. 采用“传统”方式获取当前HttpContext

    我们知道"依赖注入"已经成为了.NET Core的基本编程模式,表示当前请求上下文的HttpContext可以通过注入的IHttpContextAccessor服务来提取.有时候我 ...

  5. 字符串匹配算法之Sunday算法(转)

    字符串匹配算法之Sunday算法 背景 我们第一次接触字符串匹配,想到的肯定是直接用2个循环来遍历,这样代码虽然简单,但时间复杂度却是Ω(m*n),也就是达到了字符串匹配效率的下限.于是后来人经过研究 ...

  6. ceph卡在active+remapped状态

    最近看到了有人的环境出现了出现了卡在active+remapped状态,并且卡住不动的状态,从pg的状态去看,这个pg值分配了主的pg,没有分配到副本的osd,集群的其他设置一切正常 这个从网上搜寻到 ...

  7. 利用移动硬盘安装windows7系统

    首先把win7系统镜像的iso文件解压到移动硬盘中 将移动硬盘设置为活动分区 设置活动分区的方法 Diskpart程序实现U盘安装WIN7的方法: 将Win7安装盘中的所有文件拷贝到硬盘文件夹中,我们 ...

  8. 微信_跳一跳辅助程序_Python_(带GitHub项目地址)

    1.安装Python(推荐3.6) https://www.python.org/downloads/ 2.在github上下载脚本 [github项目地址](https://github.com/w ...

  9. sql bypass waf fuzz python

    从freebuf copy过来的,先保存,有空再改 #encoding=utf-8 import requests url = "http://127.0.0.1/index.php?id= ...

  10. XSS(跨站脚本攻击) - 常用代码大全

    XSS(跨站脚本攻击) - 常用代码大全-版本一 1'"()&%<acx><ScRiPt >prompt(915149)</ScRiPt> < ...