# About WebSec

## 致谢

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

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

## 开始

{% hint style="danger" %}
在开始文章之前，请确认自己的网络是可以访问 [Google](https://www.google.com)、[Wiki](https://zh.wikipedia.org/zh/Wiki) 等非常规网站。

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

{% hint style="danger" %}
本文章只用于分享知识、探讨问题，***笔者不保证所有内容的正确性***，请用辩证的眼光阅读本文章。
{% endhint %}

{% hint style="danger" %}
为了避免给初学者造成**误导**，请注意：

**在一个 Docker 容器中运行多个服务的行为是错误的！**
{% endhint %}

### 准备阶段

#### 课设目标

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

#### 本机环境

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

不建议在 MacOS 下使用 Docker ，因为您可能会遇到无法扫描目标容器的情况，[具体原因](/blog/about-docker.md#wei-shen-me-zai-mac-xia-wu-fa-lian-jie-docker-rong-qi)。

#### 知识储备

* 有关 [Docker 的基本命令](https://www.runoob.com/docker/docker-command-manual.html)以及 [Dockerfile 的编写](/blog/about-docker.md#dockerfile)
* 本靶场使用 Nginx 作为 Web 服务中间件，所以需要了解[Nginx 配置文件的编写](https://zhuanlan.zhihu.com/p/31202053)
* CTF 常用的[隐写手段](https://en.wikipedia.org/wiki/Steganography)、[Base64编码方式](https://zh.wikipedia.org/wiki/Base64)、[JsFuck](https://zh.wikipedia.org/zh-hans/JSFuck)、[SQL注入](https://en.wikipedia.org/wiki/SQL_injection)相关知识

#### 漏洞设计

关于漏洞设计可以 Google 关键词 [writeup](https://www.google.com/search?q=writeup\&sxsrf=ALeKk01v3nrxzMDsUMp_xB52Yxg7qIDtdA:1590072789730\&source=lnt\&tbs=lr:lang_1zh-CN%7Clang_1zh-TW\&lr=lang_zh-CN%7Clang_zh-TW\&sa=X\&ved=2ahUKEwij1rHemsXpAhWuFjQIHYPyC_0QpwV6BAgMEBo\&biw=1478\&bih=702) ，参考别人的漏洞设计。

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

1. 大端口明文信息 flag0 + base64 下一步的提示。
2. 网站 robot.txt 模拟爬虫协议信息泄漏明文 flag1 + 下一步提示。
3. 网页白色字体隐写 + JsFuck flag2 +下一步提示。
4. Golang + Sqlite3 实现的 SQL 注入绕过登录鉴权获得 flag3 +下一步提示。
5. 一个简单的任意目录读漏洞，可以从提示信息中得到在 /root 下的最后一个 flag4 。

### 编写阶段

#### [Dockerfile](/blog/about-websec.md#fu-lu)

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

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

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

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

本镜像数据库选用了 Sqlite3 而不是 MySQL 或者 MariaDB ，因为[在 Docker 容器中执行 Systemctl 指令会被禁止](/blog/about-docker.md#zai-docker-zhong-wei-shen-me-wu-fa-tiao-yong-systemctl)。

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

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

### 部署阶段

{% hint style="warning" %}
此部分不同机器操作差异较大，请按照步骤指引进行，不需要获得和屏幕一样的运行效果。
{% endhint %}

进入编写好 Dockerfile 根目录下。

![进入根目录](/files/-MAOd3ScQsI1P-9wMatY)

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

![构建镜像](/files/-MAOd3SfA9HPEKLG113x)

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

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

![运行容器](/files/-MAOd3SgxDM02DvgAyNg)

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

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

### 渗透阶段

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

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

![nmap 扫描](/files/-MAOd3ShE9o4HwhfOtKS)

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

![netcat 拉取](/files/-MAOd3Si0aXS1P3Lg0Lf)

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

![base64 在线解码](/files/-MAOd3Sj1UBQ5sfT1eZ-)

获得提示 /robot.txt 。

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

![robot 内容](/files/-MAOd3SkpcEKMINuyaX0)

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

![index 页面](/files/-MAOd3Slhekdbu-TpYIM)

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

![提示 js 方法](/files/-MAOd3SmdzHlrAbfrMkA)

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

![js 方法](/files/-MAOd3SnvT0KgeesJduj)

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

![jsfuck](/files/-MAOd3SomRm5SHGzi-6l)

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

![获得 flag2](/files/-MAOd3SpRbn3cVrjaMSf)

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

![SQL 注入页面](/files/-MAOd3SqE7KURl3GrZa5)

测试。

![正常执行](/files/-MAOd3SrOy-53Vffq3h8)

![正常执行结果](/files/-MAOd3Ssrhb2aDVSyq9Q)

构造 SQL 注入语句。

![构造注入](/files/-MAOd3Ste9W0ZFkv7xQ5)

![注入成功](/files/-MAOd3SuTKviwuCgkSWJ)

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

![获得提示](/files/-MAOd3SvotTBKTzL9024)

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

![获得 flag4](/files/-MAOd3SwSBD5FF6m5bXB)

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

## 附录

{% hint style="info" %}
为保证课程设计的**多样性**，此处只放上相关的 Dockerfile 文件，而根目录下的其他文件都被省略，故**无法直接 build 镜像**。
{% endhint %}

```
#  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 构建镜像时会对未修改过的镜像层使用缓存，大大节约镜像构建的时间。

另外，笔者愿意为同学们解答我能解答的问题，[关于我](/blog/master.md#yin-yan)。

## 引用

* [Base64 在线解码](https://www.base64decode.org/)

## [许可协议](/blog/license.md)

{% hint style="info" %}
本作品采用[知识共享署名 4.0 国际许可协议(CC BY-NC-SA 4.0)](https://creativecommons.org/licenses/by-nc-sa/4.0/)进行许可，转载时请注明原文链接，图片在使用时请保留全部内容，可适当缩放并在引用处附上图片所在的文章链接。
{% endhint %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://3ric.gitbook.io/blog/about-websec.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
