使用Docker复现CTF中的Web题

发布于 2023-11-06  130 次阅读


因为一些原因在学docker复现题目,这里做个笔记记录一下以便以后查阅

1.Docker安装

我用的是debian 10系统,使用daocloud一键安装命令

curl -sSL https://get.daocloud.io/docker | sh

提示curl未安装需要安装一下

apt-get update
apt-get install curl

安装完curl后再次执行安装docker的命令

2.Docker-Compose安装

使用以下命令安装docker compose

sudo curl -L "https://github.com/docker/compose/releases/download/v2.2.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

给予权限

sudo chmod +x /usr/local/bin/docker-compose

创建软链

sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose

可以使用以下命令检测是否安装成功

docker-compose --version

如果提示如

cker-compose version 1.24.1, build 4667896b

则安装成功

3.Docker基础命令

Dockerfile需要先了解docker的基础的命令,了解runcpexecbuild等基础使用即可。

attach      Attach local standard input, output, and error streams to a running container
  #当前shell下 attach连接指定运行的镜像
  build       Build an image from a Dockerfile # 通过Dockerfile定制镜像
  commit      Create a new image from a container's changes #提交当前容器为新的镜像
  cp          Copy files/folders between a container and the local filesystem #拷贝文件
  create      Create a new container #创建一个新的容器
  diff        Inspect changes to files or directories on a container's filesystem #查看docker容器的变化
  events      Get real time events from the server # 从服务获取容器实时时间
  exec        Run a command in a running container # 在运行中的容器上运行命令
  export      Export a container's filesystem as a tar archive #导出容器文件系统作为一个tar归档文件[对应import]
  history     Show the history of an image # 展示一个镜像形成历史
  images      List images #列出系统当前的镜像
  import      Import the contents from a tarball to create a filesystem image #从tar包中导入内容创建一个文件系统镜像
  info        Display system-wide information # 显示全系统信息
  inspect     Return low-level information on Docker objects #查看容器详细信息
  kill        Kill one or more running containers # kill指定docker容器
  load        Load an image from a tar archive or STDIN #从一个tar包或标准输入中加载一个镜像[对应save]
  login       Log in to a Docker registry #
  logout      Log out from a Docker registry
  logs        Fetch the logs of a container
  pause       Pause all processes within one or more containers
  port        List port mappings or a specific mapping for the container
  ps          List containers
  pull        Pull an image or a repository from a registry
  push        Push an image or a repository to a registry
  rename      Rename a container
  restart     Restart one or more containers
  rm          Remove one or more containers
  rmi         Remove one or more images
  run         Run a command in a new container
  save        Save one or more images to a tar archive (streamed to STDOUT by default)
  search      Search the Docker Hub for images
  start       Start one or more stopped containers
  stats       Display a live stream of container(s) resource usage statistics
  stop        Stop one or more running containers
  tag         Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE
  top         Display the running processes of a container
  unpause     Unpause all processes within one or more containers
  update      Update configuration of one or more containers
  version     Show the Docker version information
  wait        Block until one or more containers stop, then print their exit codes

4.Dockerfile基础命令

FROM # 基础镜像,一切从这里开始构建
MAINTAINER # 镜像是谁写的,姓名+邮箱
RUN # 镜像构建的时候需要运行的命令
ADD # 步骤,tomcat镜像,这个tomcat压缩包!添加内容
WORKDIR # 镜像的工作目录
VOLUME # 挂载目录
EXPOSE # 保留端口配置
CMD # 指定这个容器启动的时候要运行的命令,只有最后一命令会生效,可被替代
ENTRYPOINT # 指定这个容器启动的时候运行的命令,可以追加命令
ONBUILD # 当构建一个被继承Dockerfile这个时候就会运行ONBUILD的指令。
COPY # 类似ADD,将我们的文件拷贝到镜像中
ENV # 构建的时候设置环境变量

有一些需要注意的点

  • RUNCMD的区别 RUN是在镜像构建时运行的命令,CMD是在容器生成是运行的命令,RUNENTRYPOINT的区别同RUNCMD
  • RUNENTRYPOINT的区别 CMD:指定这个容器启动的时候要运行的命令,只有最后一命令会生效,可被替代。ENTRYPOINT:指定这个容器启动的时候运行的命令,可以追加命令。
  • docker容器需要一个永不退出的进程,否则docker会认为容器没有工作,自动关闭容器。

5.部署环境(以[DASCTF]ezpop为例)

/建议先自己搭建成功一次后再写Dockerfile和Docker-compose文件/

根据实际情况选用不同版本的php等镜像,我这里选php7.3.4和apache的镜像

拉取镜像

docker pull php:7.3.4-apache

开启容器

docker run -it -d -p 2333:80 php:7.3.4-apache

进入容器

docker exec -it <CONTAINER ID> bash

CONTAINER ID可以使用命令docker ps查看

进入容器后默认在工作目录,也就是/var/www/html目录

将题目源代码环境添加进目录中

touch index.php
vim index.php

vim未安装情况使用以下命令安装

apt-get install vim
# 题目源代码,放进index.php中

<?php

class crow
{
    public $v1;
    public $v2;

    function eval() {
        echo new $this->v1($this->v2);
    }

    public function __invoke()
    {
        $this->v1->world();
    }
}

class fin
{
    public $f1;

    public function __destruct()
    {
        echo $this->f1 . '114514';
    }

    public function run()
    {
        ($this->f1)();
    }

    public function __call($a, $b)
    {
        echo $this->f1->get_flag();
    }

}

class what
{
    public $a;

    public function __toString()
    {
        $this->a->run();
        return 'hello';
    }
}
class mix
{
    public $m1;

    public function run()
    {
        ($this->m1)();
    }

    public function get_flag()
    {
        eval('#' . $this->m1);
    }

}

if (isset($_POST['cmd'])) {
    unserialize($_POST['cmd']);
} else {
    highlight_file(__FILE__);
}
?>

返回根目录创建一个flag文件

使用ip:2333进入靶机,能够正常获取flag

6.文件组成

--|ezpop
   |--| _files
      |--| aa
         |-- index.php #装有源代码
      |-- docker-php-entrypoint
      |-- php.ini
      |-- start.sh
   |-- docker-compose.yml #docker-compose文件
   |-- Dockerfile #Dockerfile文件

7.Dockerfile

FROM php:7.3.4-apache #拉取镜像

COPY _files /tmp/ #复制_files文件夹中所有文件进容器的/tmp/目录下

RUN rm -rf /var/www/html/* \ #删除/var/www/html/目录下的所有文件
    && mv /tmp/docker-php-entrypoint /usr/local/bin/docker-php-entrypoint \ #移动docker-php-entrypoint到/usr/local/bin/docker-php-entrypoint
    && chmod +x /usr/local/bin/docker-php-entrypoint \ #给予权限
    && mv /tmp/aa/* /var/www/html/ \ #移动aa/目录下所有文件到/var/www/html/目录下
    && chown -R www-data:www-data /var/www/html \ #给予权限
#   && mv /tmp/php.ini /usr/local/etc/php/php.ini \ 移动php.ini到/usr/local/etc/php/php.ini (部分题目需要)
    && mv /tmp/start.sh /start.sh \ #移动start.sh到根目录
    && chmod +x /start.sh \ #给予权限
    && rm -rf /tmp/* #删除/tmp/目录下所有文件

WORKDIR /var/www/html #设置工作目录为/var/www/html

EXPOSE 80 #开放80端口

CMD ["/bin/bash", "-c", "docker-php-entrypoint"] #容器开启时执行命令

8.docker-compose.yml

version: "2" 

services:
  web:
    build: .
    image: ezpop #镜像名称
    restart: always
    ports:
      - "2333:80" #设置映射端口
    environment:
      - FLAG=flag{jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj} #设置FLAG为环境变量,为了ctfd实现动态flag

9.docker-php-entrypoint

#!/bin/sh

sh /start.sh #启动脚本

tail -F /dev/null #永不停止的进程

10.start.sh

#!/bin/sh

echo $FLAG > /f14g #将全局变量$FLAG放入根目录的/f14g文件中

export FLAG=not_flag
FLAG=not_flag #设置动态flag

/etc/init.d/apache2 start #启动apache

rm -f /start.sh #删除start.sh

11.测试

将打包好的文件压缩包上传至服务器,解压后进入文件夹

使用以下命令启动容器

docker-compose up -d

等待启动成功后进入网址

ip:2333

成功进入,能够通过解题获取flag

12.动态flag

使用ctfd的插件实现,在前面的文件中已经设置了全局变量

具体方法这里不再赘述

已经有太多美好从身边流逝......
最后更新于 2023-11-06