1. 拿到敏感文件

打开环境会看到一个弹窗,提示请登录,然后会跳转到登录界面

Web_php_wrong_nginx_config WriteUp - 图1

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

Web_php_wrong_nginx_config WriteUp - 图2

看到弹窗就觉得这里登录并不是关键,应该有其他的利用点,于是拿

dirsearch扫描一下后台文件

Web_php_wrong_nginx_config WriteUp - 图3

  • **<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>**

Web_php_wrong_nginx_config WriteUp - 图4

四个页面都提示 **please continue**

  • **<font style="color:#FA8C16;">/admin/admin.php</font>**

Web_php_wrong_nginx_config WriteUp - 图5

弹窗显示 **you need to log in** , 然后跳转到 login.php 页面

  • **<font style="color:#FA8C16;">/image</font>**

Web_php_wrong_nginx_config WriteUp - 图6

**/images** 会跳转到 **/images/**并返回 403 , 没有任何利用点 .

  • **<font style="color:#FA8C16;">robots.txt</font>**

Web_php_wrong_nginx_config WriteUp - 图7

发现了两个敏感文件 **hint.php****Hack.php** , 分别查看他们 .

  • **<font style="color:#FA8C16;">hint.php</font>**

Web_php_wrong_nginx_config WriteUp - 图8

给了个提示 , **/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

在访问的该站点的每一个页面时,都会带有isLoginCookie,这没有任何问题,但是isLogin字段的值确实被定义为”0”。

Web_php_wrong_nginx_config WriteUp - 图9

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

Web_php_wrong_nginx_config WriteUp - 图10

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

Web_php_wrong_nginx_config WriteUp - 图11

2.1 本地文件包含漏洞拿到/etc/nginx/sites-enabled/site.conf

后台看起来有很多选项卡,其实大部分都是假的,即使有几个选项存在页面跳转,也都是指向index.php,没有什么问题。

真正的利用点在于”管理中心”选项卡,在访问它时会有如下这个HTTP请求

Web_php_wrong_nginx_config WriteUp - 图12

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

2.1.1 ./测试

Payload : **file=./index&ext=php**

Web_php_wrong_nginx_config WriteUp - 图13

提示 **please continue** .

2.1.2 ../测试

Payload : **file=../index&ext=php**

Web_php_wrong_nginx_config WriteUp - 图14

响应结果与 ./ 完全相同 , 看起来 **../** 并没有被解析处理 , 或者说是被过滤掉了 .

2.1.3 ….//测试

既然 **../** 可能被过滤了 , 那么就重叠写为 **....//** . 这样即使 **../** 被过滤删除 , 剩下的内容也还是 **../**

Payload : **file=....//index&ext=php**

Web_php_wrong_nginx_config WriteUp - 图15

页面内容出现了变化 , 不再出现 please continue , 这里可能因为过滤检测后 ../index.php 文件不存在 , 而导致站点自动跳转到 ./index.php 主页 .**

因此重写法绕过 **../** 过滤可能是成功的 , 我们继续测试 .

2.1.4 去除ext参数值测试

如果 HTTP 请求中 ext=php 是必须存在且无法更改的 , 那么这里的利用会非常困难 . 因为我们的目标是 /etc/nginx/sites-enabled/site.conf , 而不是 PHP 文件 .

Payload : **file=index&ext=**

Web_php_wrong_nginx_config WriteUp - 图16

没有出现 please continue , 因此这里看到的页面可能是因为当前目录下 index 文件不存在而强制跳转到的 index.php .

2.1.5 去除ext参数值,并在file参数中添加文件扩展名测试

那么如何验证上述 **没有出现 please continue 字符串是因为站点没有找到文件而做的强制跳转** 这个猜想是正确的呢 ?

我们不在 ext 参数字段中添加任何值 , 而是在 file 参数中添加文件扩展名 , 如果出现了 please continue 则表示读取到了文件 .

Payload : **file=index.php&ext=**

Web_php_wrong_nginx_config WriteUp - 图17

出现了 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=**

Web_php_wrong_nginx_config WriteUp - 图18

成功读取到 **/etc/nginx/sites-enabled/site.conf** 配置文件

3. 目录遍历漏洞拿到WebShell

利用上面的本地文件包含漏洞,我们可以读取到所有一直文件名的文件,但是对于那些我们不知道的文件,就没有办法去读取,必须拿到其他的利用点。

查看 /etc/nginx/sites-enabled/site.conf , 很容易发现其中存在的问题 .

  1. ![](https://cdn.nlark.com/yuque/0/2020/png/573149/1586248677469-b6802bfa-d89c-4cf7-bbd8-9d48ed69ab7e.png)

这段代码给 **/web-img** 目录设置了一个别名 **/images/** , 并且开启了 **autoindex** .

这里给不熟悉Nginx的同学说下,

  1. alias 用于给 localtion 指定的路径设置别名 , 在路径匹配时 , alias 会把 location 后面配置的路径丢弃掉 , 并把当前匹配到的目录指向到 alias 指定的目录 .

注意 ! alias 会丢弃掉 location 的路径 , 因此 alias 后面的路径是从系统根目录开始的 , 然后直接跟指定的路径 . 它和 root 的用法不一样 . 可以参考这个链接 .

**autoindex** 是一个目录浏览功能 , 用于列出当前目录的所有文件及子目录 .

总之 , 这里在 URL 访问 **/web-img** , 就会访问系统根目录下的 **/images/**

而如果在 URL 访问 **/web-img../** , 则相当于访问 **/images/../** , 即访问系统根目录 . 且由于开启了 **autoindex** , 我们可以直接在浏览器里看到根目录下的所有内容 !

Web_php_wrong_nginx_config WriteUp - 图19

这里就是一个目录遍历漏洞 . 我们可以通过它查看系统中的所有文件~

遍历目录 , 在 /var/www 下能找到 hack.php.bak

Web_php_wrong_nginx_config WriteUp - 图20

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

Web_php_wrong_nginx_config WriteUp - 图21

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

Web_php_wrong_nginx_config WriteUp - 图22

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

weevely 生成的后门如下

Web_php_wrong_nginx_config WriteUp - 图23

所以猜测这也一个WebShell,只不过经过了加密混淆,我们需要做的就是分析出该后门的构造思路,并且编写连接脚本,以连接这个WebShell

4. 分析后门代码

hack.php.bak 里代码的思路是很简单的 , 先定义多个变量 , 然后通过 str_replace() 函数进行字符替换并拼接 , 接着通过 create_function() 创建了一个匿名函数 , 最后执行该函数 .

str_replace() 函数替换拼接后的代码就是匿名函数$g的内容 . 因此这里输出$g , 看看该函数到底在做什么 .

Web_php_wrong_nginx_config WriteUp - 图24

还是很乱 , 需要稍微整理下 , 这里增加了一些注释 .

4.1 先是预定义阶段 , 定义了两个字符串和一个 x() 函数 , 后面会用到

Web_php_wrong_nginx_config WriteUp - 图25

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

Web_php_wrong_nginx_config WriteUp - 图26

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

Web_php_wrong_nginx_config WriteUp - 图27

  1. $m[0] : 所有可选语言及其权重系数
  2. $m[1] : 所有可选语言的首字母
  3. $m[2] : 所有可选语言的权重值( 不清楚该怎么说 , 反正你能明白 )

简单的说下这个 Accept-Language ( 参考链接 )

  1. 举个例子 : Accept-Language: zh-cn,zh;q=0.5
  2. 1. Accept-Language表示浏览器所支持的语言类型 .
  3. 2. zh-CN 表示简体中文 , zh 表示中文 , 不同语言之间用逗号分割 .
  4. 3. q 是权重系数 , 范围为 [0,1] . q 值越大 , 请求越倾向于获得其对应语言表示的内容 . 若没有指定 q 值,则默认为1 . 若被赋值为0 , 则用于提醒服务器该语言是浏览器不接受的内容类型 .

然后拼接了前两种可选语言的首字母 , 和预定义的字符串拼接并进行 md5 校验 , 截取等操作 . 然后赋值给 $h$f 两个变量 .

4.3 拼接payload

Web_php_wrong_nginx_config WriteUp - 图28

循环中的 $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

Web_php_wrong_nginx_config WriteUp - 图29

紧跟上面的代码 , 若在 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()** 执行攻击者指定的命令 , 最后将命令执行结果加密编码呈现给攻击者 .

整体的解密流程还是非常清晰的 , 我们知道了后门是如何处理攻击者发送的恶意数据包 . 但现在我们没有连接脚本 , 无法构造出后门能处理的请求 . 因此这里需要逆向整个解密过程 , 以便构造出请求数据包 .

就这样吧 啥时候能力到了再说

https://www.guildhab.top/?p=1474