About WebSec

这是网络安全课程设计的一部分思路。

致谢

把这篇文章献给我的网络安全任课教授,李舜鹏教授。

他是我大一入门 CTF 的启蒙导师,感谢他。

开始

在开始文章之前,请确认自己的网络是可以访问 GoogleWiki 等非常规网站。

因为本文大量链接引用了相关内容,若无法访问,可能会影响您的阅读质量。

本文章只用于分享知识、探讨问题,笔者不保证所有内容的正确性,请用辩证的眼光阅读本文章。

为了避免给初学者造成误导,请注意:

在一个 Docker 容器中运行多个服务的行为是错误的!

准备阶段

课设目标

完成在 Docker 单个镜像下部署五个 flag ,最终做成 CTF 靶场夺旗的形式。

本机环境

笔者采用的环境是 Arch Linux + Docker 。

不建议在 MacOS 下使用 Docker ,因为您可能会遇到无法扫描目标容器的情况,具体原因

知识储备

漏洞设计

关于漏洞设计可以 Google 关键词 writeup ,参考别人的漏洞设计。

本靶场采用的 Flag 埋点以及流程为:

  1. 大端口明文信息 flag0 + base64 下一步的提示。

  2. 网站 robot.txt 模拟爬虫协议信息泄漏明文 flag1 + 下一步提示。

  3. 网页白色字体隐写 + JsFuck flag2 +下一步提示。

  4. Golang + Sqlite3 实现的 SQL 注入绕过登录鉴权获得 flag3 +下一步提示。

  5. 一个简单的任意目录读漏洞,可以从提示信息中得到在 /root 下的最后一个 flag4 。

编写阶段

本次 Dockerfile 基础镜像采用 Centos ,这是服务器最常用的 Linux 系统之一,笔者也比较熟悉,所以建议您采用您最熟悉的系统作为基础镜像。

因为本镜像的 flag0 以及 flag3 相关程序采用的是 Golang 编写,所以会在根目录下存放两个 Golang 文件,在构建镜像时采用 COPY 命令拷贝进 /root 文件夹。

而对于 Golang 连接数据库的包依赖采用的是直接下载在Docker build根文件夹,用 COPY 命令拷贝到相关路径下,而不是采用go get命令直接拉取,是因为该命令执行时间过长。

本镜像在构建时写入文件采用了echo > 目标文件以及 Dockerfile COPY 命令两种方式。前一种用于写入较短的文件内容,为保证 Dockerfile 的可读性,较长的文件内容采用了后一种文件拷贝方式。

本镜像数据库选用了 Sqlite3 而不是 MySQL 或者 MariaDB ,因为在 Docker 容器中执行 Systemctl 指令会被禁止

相关的漏洞复现的网页编写以及程序源代码就不在此展现了。

在使用 Dockerfile 执行包管理软件时可能会遇到需要输入 y 以继续执行的情况,此时可以通过 -y 参数跳过所有的输入,此条建议适用于 Centos ,其他发行版本请自行查阅。

部署阶段

此部分不同机器操作差异较大,请按照步骤指引进行,不需要获得和屏幕一样的运行效果。

进入编写好 Dockerfile 根目录下。

打包构建 Docker 镜像 Docker build -t 你打算取的镜像名称 .,注意不要丢掉最后的点,这代表构建的根目录处于当前目录下。

在运行一系列指令后显示构建成功,接下来开始运行容器。docker run -d --rm --name 你为容器取得名字 你之前为镜像取得名字

此处 -d 表示后台运行 --rm 表示容器停止后自动删除。

容器在运行成功后会返回一串标识码,此时就可以进入容器。docker exec -it 你为容器取得名字 bash

就进入了容器的 bash 。此时可以通过包管理软件安装 net-tools 程序,用 ifconfig 指令获得本容器的 ip 后,就可以进行渗透测试。

渗透阶段

我们得知容器的 ip 为 http://172.17.0.2/

首先,在宿主机下运行 Nmap 进行扫描。

使用 nc 命令连接 1234 号端口获得如下。

获得了第一个 flag0 ,以及一串 Base64,我们对 Base64 进行多次解码

获得提示 /robot.txt 。

浏览器进入 http://172.17.0.2/robot.txt

获得 flag1 ,以及下一个的提示。进入页面,显示找一找。

按 Ctrl+A 网页全选,获得内容:查看JS方法。

F12 打开控制台,找到 JS 方法。

然后执行方法,获得一串括号,这个一眼可以看出是JsFuck。

复制括号,在控制台输入这串括号,得到 flag2 以及下一个的提示。

进入该页面,一眼看出是SQL注入。

测试。

构造 SQL 注入语句。

SQL 注入成功并反选网页获得 flag3,获得下一个提示。

获得提示信息,通过拼接 URL 查看目录 /root。

渗透结束,获得了所有的 flag 。

附录

为保证课程设计的多样性,此处只放上相关的 Dockerfile 文件,而根目录下的其他文件都被省略,故无法直接 build 镜像

#  centos
FROM centos as prod

# 定义后层镜像根目录
WORKDIR /root/

# 复制flag0的源码到容器内
COPY flag*.go ./

# 安装 Nginx
RUN yum install -y nginx sqlite-devel golang

# 拷贝 Flag2 文件
COPY index.html /usr/share/nginx/html/FindSomething/

# 拷贝 Nginx 配置文件
COPY nginx.conf /etc/nginx/nginx.conf

# 写入 robot.txt
RUN echo -e "User-agent: *\nDisallow: /FindSomething/index.html\nDisallow: /flag1{this_f1ag1_easy}" > /usr/share/nginx/html/robot.txt \
# 写入网页
&& mkdir /usr/share/html/ && echo "<html><head><meta charset="utf-8" /><title>登陆成功</title></head><body><h2>恭喜你登陆成功</h2><font color="#FFFFFF">flag3{Y0u_G0t_F1ag3} ----> /FileUpload</font></body></html>" > /usr/share/html/success.html \
&& echo "<html><head><meta charset="utf-8" /><title>用户登录</title><style>form{width: 30vw;height: 30vh;min-height: 300px;margin: 10vh auto;border: 1px solid;border-radius: 4px;}form .username,.password{display: block;float: right;}div {width: 300px;height: 80px;margin: 30px auto 0;}input label {float: left;display: inline-block;}input {height: 30px;}.button {width: 100px;margin: auto;clear: both;display: block;}</style></head><body><form action="/GotYourSQL" method="post"><div><label>username: </label><input class="username" type="text" name="username"></div><div><label>password:</label><input class="password" type="text" name="password"></div><input class="button" type="submit" value="查询"></form></body></html>" > /usr/share/html/sqlIndex.html \
# 写入最后一个 flag
&& echo "flag4{W0w_y0ur_diffcu1t_f1ag4}" > /root/flag4{W0w_y0ur_diffcu1t_f1ag4} \
# 写入 sh 脚本
&& echo -e "#!/bin/bash\n go run flag0.go & \n go run flag1.go & \n nginx\n tail -f /dev/null" > run.sh && chmod 777 run.sh

# 导入依赖
ADD mattn.tar.gz /usr/lib/golang/src/github.com/

# 启动时执行linux命令
CMD ["./run.sh"]

后记

本次实验从客观上说难度比较大,但是如果善用 Google ,还是可以完成本次实验的。

本次实验主要的难度在于开头的漏洞设计,这个需要查询相关资料了解相关漏洞程序编写的方法,以及后期在实现漏洞时的 Linux 命令操作。

在构建 Docker 镜像时,笔者建议采用将不会改变的内容放在 Dockerfile 的前面,这样在 Docker 构建镜像时会对未修改过的镜像层使用缓存,大大节约镜像构建的时间。

另外,笔者愿意为同学们解答我能解答的问题,关于我

引用

本作品采用知识共享署名 4.0 国际许可协议(CC BY-NC-SA 4.0)进行许可,转载时请注明原文链接,图片在使用时请保留全部内容,可适当缩放并在引用处附上图片所在的文章链接。

最后更新于