章丘网站建设公司,旅游网站介绍怎么写,html5网站制作工具,建站如何赚钱目录
0x01、前言
0x02、环境搭建
0x03、漏洞原理
0x04、漏洞复现
0x05、漏洞分析
5.1、加密
5.2、解密
0x06、总结 0x01、前言 相信大家总是面试会问到java反序列化#xff0c;或者会问到标志性的漏洞#xff0c;比如shiro反序列化#xff0c;或者weblogic反序列化漏…
目录
0x01、前言
0x02、环境搭建
0x03、漏洞原理
0x04、漏洞复现
0x05、漏洞分析
5.1、加密
5.2、解密
0x06、总结 0x01、前言 相信大家总是面试会问到java反序列化或者会问到标志性的漏洞比如shiro反序列化或者weblogic反序列化漏洞。
那我就这篇文章为大家讲解一下不懂的哥哥直接背一下理解一下就好了。
至于为什么要选择shiro反序列化呢不讲weblogic呢
因为我上次有幸参与金鸡电影节的临时安全负责人具体我就不细说了。当时是内部涉及到shiro反序列化漏洞。
准确的来说是Shiro1.2.4-RememberMe反序列化漏洞。
而它也被称为Shiro 550反序列化漏洞。
细品细品...
0x02、环境搭建 下载地址https://codeload.github.com/apache/shiro/zip/shiro-root-1.2.4
环境Tomcat 8.5.27 idea 2020.2 jdk 1.8 maven 3.6 下载之后之后直接打开并open这个web文件夹即可其他自行百度就行其中还需要导入一些jstl的jar等等
0x03、漏洞原理 shiro默认使用了CookieRememberMeManager其处理cookie的流程是
得到rememberMe的cookie值 -- Base64解码 -- AES解密 -- 反序列化然而AES的密钥是硬编码的就导致了攻击者可以构造恶意数据造成反序列化的RCE漏洞。
payload 构造的顺序则就是相对的反着来
恶意命令--序列化--AES加密--base64编码--发送cookie在整个漏洞利用过程中比较重要的是AES加密的密钥该秘钥默认是默认硬编码的所以如果没有修改默认的密钥就自己可以生成恶意构造的cookie了。
shiro特征 未登陆的情况下请求包的cookie中没有rememberMe字段返回包set-Cookie里也没有deleteMe字段 登陆失败的话不管勾选RememberMe字段没有返回包都会有rememberMedeleteMe字段 不勾选RememberMe字段登陆成功的话返回包set-Cookie会有rememberMedeleteMe字段。但是之后的所有请求中Cookie都不会有rememberMe字段 勾选RememberMe字段登陆成功的话返回包set-Cookie会有rememberMedeleteMe字段还会有rememberMe字段之后的所有请求中Cookie都会有rememberMe字段
0x04、漏洞复现 复现文章https://blog.csdn.net/weixin_43571641/article/details/108182722
0x05、漏洞分析 简单介绍利用 通过在cookie的rememberMe字段中插入恶意payload 触发shiro框架的rememberMe的反序列化功能导致任意代码执行。 shiro 1.2.24中提供了硬编码的AES密钥kPHbIxk5D2deZiIxcaaaA 由于开发人员未修改AES密钥而直接使用Shiro框架导致了该问题
5.1、加密 那既然我们要分析那入口点在哪呢
Shiro≤1.2.4版本默认使用CookieRememberMeManager 而我们看看这边CookieRememberMeManager类继承了AbstractRememberMeManager我们进去看看是什么梗 我们可以看到这边这个类里面有硬编码。
然后它又继承了RememberMeManager接口我们继续进去看看是怎么回事 看名字的话可以知道这些是登陆成功登陆失败退出的一些service既然如此肯定会调用这个登陆成功的接口然后再去实现这个接口。
所以我们直接在这个接口下个断点看看是怎么个流程 这里看到调用了isRememberMe()可以发现这个就是一个判断用户是否选择了RememberMe选项。而我们是勾选了的 所以我们我们条件满足这边判断返回True我们则进入this.rememberIdentity(subject, token, info); subject存储的一些登陆信息如session等等而authcInfo存储的则是用户名 而PrincipalCollection是一个身份集合因为我们可以在Shiro中同时配置多个Realm所以呢身份信息可能就有多个因此其提供了PrincipalCollection用于聚合这些身份信息具体我们不细讲不深入去懂原理。
然后我们再F7继续跟进this.rememberIdentity(subject, principals); 这我们有点懵将身份信息干嘛
我们进入该convertPrincipalsToBytes()方法查看 看到了serialize()方法难道这边开始是进行序列化了还是啥 通过此处我们可以知道是跳了两层到DefaultSerializer类的serialize方法
看到这里就懂了这里先转为byte写入缓冲区
然后进行了一个序列化最后通过toByteArray()方法返回序列化后的Byte数组。 然后返回到原来的地方convertPrincipalsToBytes()内接下来if判断getCipherService()方法不为空则进入条件里面里面。
我们f7进去内部看看 发现又是一个cipherService这是什么我们翻译一下因为大部分开发都会用简称 也就是获取密码服务什么密码服务我们再继续F7跟进发现直接推出了。
那我们就 Ctrl左键 继续进去看。可以发现是new了一个aes加密服务。 那我们点击debugger处回到刚刚那个地方我们就不用继续进入了我们就思考一下这边是要获取到加密服务如果没获取到则不进入。
获取到的话则进入该条件 直接F8下来进入然后我们再手动添加变量监视。
可以发现正如我们所想的获取aes加密服务
然后调用encrypt()方法而懂点英文的都知道这个单词是加密的意思。
那我们初步判断这是个加密方法。
我们f7跟进去看看什么情况。 我们可以知道这个参数是byte[] serialized也就是说此处加密我们刚刚的序列化流的数据。
然后这边this.getCipherService()我们刚刚手动添加变量查看了这边是获取到了aes加密服务然后判断不问空那肯定不为空啊刚刚上面分析过了。然后我们进入条件判断股内部。
ByteSource byteSource cipherService.encrypt(serialized, this.getEncryptionCipherKey());这里调用cipherService.encrypt()方法并且传入序列化数据和getEncryptionCipherKey方法。
加密过程我们就应该不怎么感兴趣了有兴趣的可以自己研究 我们通过getEncryptionCipherKey()名字可以知道是获取key的一个方法。
那我们f7进入看看 哦豁那我们再进一层看一下发现直接就返回了emmmmm….怎么跟别人不一样。
那我们就不追了 第一步有说到硬编码存储在这个地方而构造方法就在这下面可以看到这边设置了key。 我们继续回到原来的地方知道这边是获取加密的key就ok了。
然后这边使用平台的默认字符集将字符串编码为 byte 序列并将结果存储到一个新的 byte 数组中。那我们加密部分就结束了 5.2、解密 由于此处我找不到回溯不到那咋办烦恼最后想到了我们加密的入口~~ 既然自动跳到了这里那么我们就直接在此处下个断点重新开始 随后我们进入这个getRememberedSerializedIdentity()方法看看是什么东西。
此处我们依然还很懵没事 一直f8期间倒是没有什么有意思或者重点的地方 直到我们走到这里这个有一个this.getCookie().readValue(request, response)这是要读取cookice中的数据了这必须跟入了; 这里给进到了这个readvalue()方法中了我们先看看什么情况。
根据名字可以知道是读取值的一个方法。读取什么值请求包的值。
通过getName()方法得到了key为remeberMe。然后把value置空再通过getCookie获取到cookie。
最后判断cookie不为空则进入内部
随后获取到cookie的值值则为序列化内容。然后再 return回序列化内容 随后返回到上一处地方现在remeberMe的值不是delete而是序列化内容所以进入到第二个条件分支。 一直到这一步进行base64解码成为二进制数据给了decoded的byte数组
得到rememberMe的cookie值 -- Base64解码 -- AES解密 -- 反序列化目前只进行了Base64解码那还需要aes解码。我们继续跟进 返回到了上层此处我们知道bytes是二进制数据我们看看条件判断。当bytes数组不为空且长度大于0时进入里面。那我们肯定满足所以我们两步f8加一步F7进入到 convertBytesToPrincipals看看是什么 可以看出我们接下来的步骤要依依实现了。判断key不为空然后进入内部 而从这里开始就是进行aes解密的步骤了我们F7跟进方法查看 这里重新把恶意的bytes数组重新赋值给serialized然后再获取加密服务AES/CBC/PKCS5Padding 同时到达了下一步真真正正的开始解密了其中两个参数第一个是加密的bytes数组第二个是获取到key也就是硬编码我们 就直接进入decrypt()方法中 解密过程的话我不擅长密码学这种看着我头晕涉及到aes啥的加密解密我就会跳过。所以依旧一样跳 此处继续返回到了上一层我们可以看出这个byteSource是aes解密出来的序列化流然后再默认字符集将字符串编码为 byte 序列并将结果存储到一个新的 byte 数组serialized中那接下来我们就差反序列化了
得到rememberMe的cookie值 -- Base64解码 -- AES解密 -- 反序列化我们继续return返回到上一层 顾名思义一看名字就知道是反序列化的方法我们跟进deserialize()方法查看 看到还有一层我们继续F7跟进 形成反序列化漏洞的话没有readObject()怎么可能呢
所以我们看到了最后一道光就这么愉快的结束了。
0x06、总结
其实这个还是得学习学习加密解密的方法才能进行编写poc但是此处只是了解个思路。具体可参考其他文章
https://www.anquanke.com/post/id/225442#h2-7
https://mp.weixin.qq.com/s/ayZKDVnN7zEbKjo5w8uqxQ 没看够~欢迎关注 免费领取安全学习资料包 渗透工具 技术文档、书籍 面试题 帮助你在面试中脱颖而出 视频 基础到进阶 环境搭建、HTMLPHPMySQL基础学习信息收集SQL注入,XSSCSRF暴力破解等等 应急响应笔记 学习路线