1. 拿到敏感文件
打开环境会看到一个弹窗,提示请登录,然后会跳转到登录界面

没有找到注册按钮,随便输入用户密码密码登录后会有提示弹窗:网站建设中!

看到弹窗就觉得这里登录并不是关键,应该有其他的利用点,于是拿
dirsearch扫描一下后台文件

**<font style="color:#FA8C16;">/admin</font>**|**<font style="color:#FA8C16;">/admin/</font>**|**<font style="color:#FA8C16;">/admin/?/login</font>**|**<font style="color:#FA8C16;">/admin/index.ph</font>**

四个页面都提示 **please continue**
**<font style="color:#FA8C16;">/admin/admin.php</font>**

弹窗显示 **you need to log in** , 然后跳转到 login.php 页面
**<font style="color:#FA8C16;">/image</font>**

**/images** 会跳转到 **/images/**并返回 403 , 没有任何利用点 .
**<font style="color:#FA8C16;">robots.txt</font>**

发现了两个敏感文件 **hint.php** 和 **Hack.php** , 分别查看他们 .
**<font style="color:#FA8C16;">hint.php</font>**

给了个提示 , **/etc/nginx/sites-enabled/site.conf** 文件的配置可能有问题 . 该文件应该是 Nginx 的站点核心配置文件之一 .
**<font style="color:#FA8C16;">Hack.php</font>**
访问该文件得到一个空白页面 , 猜测该文件没有直接输出任何语句 .
1.1 可利用的点
**<font style="color:#FA8C16;">/admin/admin.php</font>**页面
该页面需要登录后才能访问,但是我们没有账号密码,也没有拿到注册界面,所以账号密码登录是不太现实的,同意爆破密码也不太可能,现在最理想的情况是在该站点某个地方泄露了Cookie,我们可以凭借这个Cookie以某个用户身份登录
**<font style="color:#FA8C16;">/etc/nginx/sites-enabled/site.conf</font>**文件
这个文件是题目中给出的提示,肯定有用。但是现在没有地方去读取这个文件,最常用的文件漏洞有”文件包含”与”任意文件下载(读取)”,但是先要找到这个利用点,
**<font style="color:#FA8C16;">Hack.php</font>**页面
这是不知道这个页面是干啥用的,不过看着名字肯定有利用点。
整理思路后 , 拿 **BurpSuite** 代理走一遍刚才的流程 .
2. 本地文件包含读取Nginx配置文件
BurpSuite发现一个奇怪的Cookie
在访问的该站点的每一个页面时,都会带有isLogin的Cookie,这没有任何问题,但是isLogin字段的值确实被定义为”0”。

想到Cookie是用来识别用户,维持用户登录状态的,这里”0”可能代表布尔值,因此手动将它改为”isLogin=1“

然后再访问 /admin/admin.php , 发现我们成功登录到了站点后台 .

2.1 本地文件包含漏洞拿到/etc/nginx/sites-enabled/site.conf
后台看起来有很多选项卡,其实大部分都是假的,即使有几个选项存在页面跳转,也都是指向index.php,没有什么问题。
真正的利用点在于”管理中心”选项卡,在访问它时会有如下这个HTTP请求

- 注意这个参数 :
**file=index?ext=php**,file参数值是文件名 ,ext参数值是文件扩展名 . 那么这里是否存在LFI( 本地文件包含漏洞 ) , 可以包含其他文件呢 ?
2.1.1 ./测试
Payload : **file=./index&ext=php**

提示 **please continue** .
2.1.2 ../测试
Payload : **file=../index&ext=php**

响应结果与 ./ 完全相同 , 看起来 **../** 并没有被解析处理 , 或者说是被过滤掉了 .
2.1.3 ….//测试
既然 **../** 可能被过滤了 , 那么就重叠写为 **....//** . 这样即使 **../** 被过滤删除 , 剩下的内容也还是 **../**
Payload : **file=....//index&ext=php**

页面内容出现了变化 , 不再出现 please continue , 这里可能因为过滤检测后 ../index.php 文件不存在 , 而导致站点自动跳转到 ./index.php 主页 .**
因此重写法绕过 **../** 过滤可能是成功的 , 我们继续测试 .
2.1.4 去除ext参数值测试
如果 HTTP 请求中 ext=php 是必须存在且无法更改的 , 那么这里的利用会非常困难 . 因为我们的目标是 /etc/nginx/sites-enabled/site.conf , 而不是 PHP 文件 .
Payload : **file=index&ext=**

没有出现 please continue , 因此这里看到的页面可能是因为当前目录下 index 文件不存在而强制跳转到的 index.php .
2.1.5 去除ext参数值,并在file参数中添加文件扩展名测试
那么如何验证上述 **没有出现 please continue 字符串是因为站点没有找到文件而做的强制跳转** 这个猜想是正确的呢 ?
我们不在 ext 参数字段中添加任何值 , 而是在 file 参数中添加文件扩展名 , 如果出现了 please continue 则表示读取到了文件 .
Payload : **file=index.php&ext=**

出现了 please continue , 说明读取到了当前目录下的 index.php . 而前面 Payload : **file=index&ext=** 因为站点没有读到 index 这个文件 , 直接跳转到 index.php , 因此没有出现 please continue .
这也说明了我上面所有的猜测都是正确的 . 我们可以利用重写 **../** 来绕过站点的过滤删除机制 .
现在我们可以直接读取到 **/etc/nginx/sites-enabled/site.conf**.
Payload : **file=....//....//....//....//etc/nginx/sites-enabled/site.conf&ext=**

成功读取到 **/etc/nginx/sites-enabled/site.conf** 配置文件
3. 目录遍历漏洞拿到WebShell
利用上面的本地文件包含漏洞,我们可以读取到所有一直文件名的文件,但是对于那些我们不知道的文件,就没有办法去读取,必须拿到其他的利用点。
查看 /etc/nginx/sites-enabled/site.conf , 很容易发现其中存在的问题 .

这段代码给 **/web-img** 目录设置了一个别名 **/images/** , 并且开启了 **autoindex** .
这里给不熟悉Nginx的同学说下,
alias 用于给 localtion 指定的路径设置别名 , 在路径匹配时 , alias 会把 location 后面配置的路径丢弃掉 , 并把当前匹配到的目录指向到 alias 指定的目录 .
注意 ! alias 会丢弃掉 location 的路径 , 因此 alias 后面的路径是从系统根目录开始的 , 然后直接跟指定的路径 . 它和 root 的用法不一样 . 可以参考这个链接 .
而 **autoindex** 是一个目录浏览功能 , 用于列出当前目录的所有文件及子目录 .
总之 , 这里在 URL 访问 **/web-img** , 就会访问系统根目录下的 **/images/**
而如果在 URL 访问 **/web-img../** , 则相当于访问 **/images/../** , 即访问系统根目录 . 且由于开启了 **autoindex** , 我们可以直接在浏览器里看到根目录下的所有内容 !

这里就是一个目录遍历漏洞 . 我们可以通过它查看系统中的所有文件~
遍历目录 , 在 /var/www 下能找到 hack.php.bak

这是 hack.php 的自动备份文件 . 点击即可下载到本地 .

打开后发现代码很乱 , 不清楚有什么用 .

但是这玩意怎么看怎么像用 weevely 生成的 WebShell 后门 .
weevely 生成的后门如下

所以猜测这也一个WebShell,只不过经过了加密混淆,我们需要做的就是分析出该后门的构造思路,并且编写连接脚本,以连接这个WebShell
4. 分析后门代码
hack.php.bak 里代码的思路是很简单的 , 先定义多个变量 , 然后通过 str_replace() 函数进行字符替换并拼接 , 接着通过 create_function() 创建了一个匿名函数 , 最后执行该函数 .
str_replace() 函数替换拼接后的代码就是匿名函数$g的内容 . 因此这里输出$g , 看看该函数到底在做什么 .

还是很乱 , 需要稍微整理下 , 这里增加了一些注释 .
4.1 先是预定义阶段 , 定义了两个字符串和一个 x() 函数 , 后面会用到

4.2 然后就需要获取攻击者发送的数据了 , 这里攻击代码是通过 Referer 字段传输的

需要注意这个正则函数 preg_match_all() , 该函数从 Accept-Language 取值 , 然后通过正则匹配后输出到 $m 数组中 . 单独拿出来看 , $m 数组的输出内容是如下这样的 .

$m[0] : 所有可选语言及其权重系数$m[1] : 所有可选语言的首字母$m[2] : 所有可选语言的权重值( 不清楚该怎么说 , 反正你能明白 )
简单的说下这个 Accept-Language ( 参考链接 )
举个例子 : Accept-Language: zh-cn,zh;q=0.51. Accept-Language表示浏览器所支持的语言类型 .2. zh-CN 表示简体中文 , zh 表示中文 , 不同语言之间用逗号分割 .3. q 是权重系数 , 范围为 [0,1] . q 值越大 , 请求越倾向于获得其对应语言表示的内容 . 若没有指定 q 值,则默认为1 . 若被赋值为0 , 则用于提醒服务器该语言是浏览器不接受的内容类型 .
然后拼接了前两种可选语言的首字母 , 和预定义的字符串拼接并进行 md5 校验 , 截取等操作 . 然后赋值给 $h 和 $f 两个变量 .
4.3 拼接payload

循环中的 $p .= $q[$m[2][$z]] 会不断从 $q 中提取数据 . 结合之前的代码 , 攻击代码是放在 Referer 中的( 最后会放在 $q 中 ) , 因此这里可以看作是拼接攻击代码 , 组合成 Payload . ‘
然后判断 $h 是否出现在 Payload 的开头 , 若是则设置 $_SESSION['$i'] = "" , 同时删除 Payload 的 $h 部分 .
接着判断 $_SESSION 中那个是否存在 $i 这个键名 , 若是则将 Payload 赋值给 $_SESSION[$i] , 然后查找 $_SESSION[$i]( 也就是 Payload ) 中 $f 第一次出现的位置 .
4.4 解密并执行payload

紧跟上面的代码 , 若在 Payload 中找到了 $f 第一次出现的位置( 也就是说明 $f 存在于 Payload 中 ) , 就会继续执行如下过程 .
- 生成密钥
**$k**, 该值由预定义的两个字符串拼接而成 , 然后打开输出控制缓冲区 . - 截取 Payload 中从开头到
**$f**出现位置的这部分字符串( 由此可以判断**$f**应该是出现在 Payload 的末尾 , 这里删去 $f ) - 利用
**preg_replace()**函数 , 正则替换字符串中的 “**_**“ 和 “**-**“ 为 “**/**“ 和 “**+**“ . - 对替换后的字符串进行
**Base64_decode**解码操作 - 对解码后的字符串进行循环异或运算( 也就是调用
**x()**函数 ) - 对计算后的字符串调用
**gzuncompress()**函数进行解压 . - 通过
**eval()**执行解压后的字符串 . - 返回输出到缓冲区的内容 , 然后清空并关闭输出缓冲区 .
- 对缓冲区输出的内容通过
**gzcompress()**函数压缩 , 再通过**x()**函数循环异或计算 , 最后通过**Base64_encode**编码并输出 .
整个后门代码的思路应该就是如上这样的 , 攻击者通过 **Referer** 传输攻击代码 , 这段攻击代码的格式应该为 **填充字符串 + 加密混淆后的Payload + 填充字符串**
该后门脚本接收到攻击者传送的数据包 , 先按照一定顺序取出攻击代码 , 然后把前后两侧的填充字符串去除 , 拿到 Payload , 然后对 Payload 进行解密反混淆操作 , 接着通过 **eval()** 执行攻击者指定的命令 , 最后将命令执行结果加密编码呈现给攻击者 .
整体的解密流程还是非常清晰的 , 我们知道了后门是如何处理攻击者发送的恶意数据包 . 但现在我们没有连接脚本 , 无法构造出后门能处理的请求 . 因此这里需要逆向整个解密过程 , 以便构造出请求数据包 .
就这样吧 啥时候能力到了再说
