首页 > 编程语言 >Java反序列化:CommonsCollections3调试分析

Java反序列化:CommonsCollections3调试分析

时间:2023-09-12 21:44:21浏览次数:44  
标签:map 序列化 Java InstantiateTransformer new return null public CommonsCollections3

基础知识

1. Java 反射

1.1 getConstructor

getConstructor 是Java反射API中的一个方法,用于获取类的公共构造方法的引用。构造方法是一种特殊的方法,用于创建类的实例(对象),并且通常在对象创建时进行初始化。

getConstructor的函数原型:

public Constructor<?> getConstructor(Class<?>... parameterTypes) throws NoSuchMethodException, SecurityException
  • parameterTypes:一个可变参数,用于指定要获取的构造方法的参数类型列表。
  • NoSuchMethodException:如果没有找到匹配指定参数类型的公共构造方法,则会抛出此异常。
  • SecurityException:如果存在安全管理器且其 checkMemberAccess 方法拒绝访问构造方法,则会抛出此异常。

1.2 newInstance

newInstance是Java反射API中的一个方法,用于创建类的实例并返回该实例的引用。

newInstance的函数原型:

public T newInstance() throws InstantiationException, IllegalAccessException
  • T表示要创建的类型

2. InstantiateTransformer

InstantiateTransformer 是Apache Commons Collections库中的一个类,用于创建对象的转换器。具体来说,它用于通过类名实例化一个新对象,并将其作为转换结果返回。

看看源码:

public class InstantiateTransformer<T> implements Transformer<Class<? extends T>, T>, Serializable {
    private static final long serialVersionUID = 3786388740793356347L;
    private static final Transformer NO_ARG_INSTANCE = new InstantiateTransformer();
    private final Class<?>[] iParamTypes;
    private final Object[] iArgs;

    public static <T> Transformer<Class<? extends T>, T> instantiateTransformer() {
        return NO_ARG_INSTANCE;
    }

    public static <T> Transformer<Class<? extends T>, T> instantiateTransformer(Class<?>[] paramTypes, Object[] args) {
        if (paramTypes == null && args != null || paramTypes != null && args == null || paramTypes != null && args != null && paramTypes.length != args.length) {
            throw new IllegalArgumentException("Parameter types must match the arguments");
        } else {
            return paramTypes != null && paramTypes.length != 0 ? new InstantiateTransformer(paramTypes, args) : new InstantiateTransformer();
        }
    }

    private InstantiateTransformer() {
        this.iParamTypes = null;
        this.iArgs = null;
    }

    public InstantiateTransformer(Class<?>[] paramTypes, Object[] args) {
        this.iParamTypes = paramTypes != null ? (Class[])paramTypes.clone() : null;
        this.iArgs = args != null ? (Object[])args.clone() : null;
    }

    public T transform(Class<? extends T> input) {			
        try {
            if (input == null) {
                throw new FunctorException("InstantiateTransformer: Input object was not an instanceof Class, it was a null object");
            } else {
                Constructor<? extends T> con = input.getConstructor(this.iParamTypes);	// 获取公开构造器
                return con.newInstance(this.iArgs);				// 创建对象实例
            }
        } catch (NoSuchMethodException var3) {
            throw new FunctorException("InstantiateTransformer: The constructor must exist and be public ");
        } catch (InstantiationException var4) {
            throw new FunctorException("InstantiateTransformer: InstantiationException", var4);
        } catch (IllegalAccessException var5) {
            throw new FunctorException("InstantiateTransformer: Constructor must be public", var5);
        } catch (InvocationTargetException var6) {
            throw new FunctorException("InstantiateTransformer: Constructor threw an exception", var6);
        }
    }
}

3. TrAXFilter

在其构造方法中具有

public class TrAXFilter extends XMLFilterImpl {
    private Templates              _templates;
    private TransformerImpl        _transformer;
    private TransformerHandlerImpl _transformerHandler;
    private boolean _useServicesMechanism = true;

    public TrAXFilter(Templates templates)  throws
        TransformerConfigurationException
    {
        _templates = templates;
        _transformer = (TransformerImpl) templates.newTransformer();
        _transformerHandler = new TransformerHandlerImpl(_transformer);
        _useServicesMechanism = _transformer.useServicesMechnism();
    }

    public Transformer getTransformer() {
        return _transformer;
    }

    private void createParent() throws SAXException {
        XMLReader parent = null;
        try {
            SAXParserFactory pfactory = SAXParserFactory.newInstance();
            pfactory.setNamespaceAware(true);

            if (_transformer.isSecureProcessing()) {
                try {
                    pfactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
                }
                catch (SAXException e) {}
            }

            SAXParser saxparser = pfactory.newSAXParser();
            parent = saxparser.getXMLReader();
        }
        catch (ParserConfigurationException e) {
            throw new SAXException(e);
        }
        catch (FactoryConfigurationError e) {
            throw new SAXException(e.toString());
        }

        if (parent == null) {
            parent = XMLReaderFactory.createXMLReader();
        }

        // make this XMLReader the parent of this filter
        setParent(parent);
    }

    public void parse (InputSource input) throws SAXException, IOException
    {
        XMLReader managedReader = null;

        try {
            if (getParent() == null) {
                try {
                    managedReader = XMLReaderManager.getInstance(_useServicesMechanism)
                                                    .getXMLReader();
                    setParent(managedReader);
                } catch (SAXException  e) {
                    throw new SAXException(e.toString());
                }
            }

            // call parse on the parent
            getParent().parse(input);
        } finally {
            if (managedReader != null) {
                XMLReaderManager.getInstance(_useServicesMechanism).releaseXMLReader(managedReader);
            }
        }
    }

    public void parse (String systemId) throws SAXException, IOException
    {
        parse(new InputSource(systemId));
    }

    public void setContentHandler (ContentHandler handler)
    {
        _transformerHandler.setResult(new SAXResult(handler));
        if (getParent() == null) {
                try {
                    createParent();
                }
                catch (SAXException  e) {
                   return;
                }
        }
        getParent().setContentHandler(_transformerHandler);
    }

    public void setErrorListener (ErrorListener handler) { }
}

4. TemplatesImpl动态加载字节码

  • Templates接口

  • TemplatesImpl动态加载字节码过程

/*
	TemplatesImpl.newTransformer()
		TemplatesImpl.getTransletInstance()					
			TemplatesImpl.defineTransletClasses()			
				ClassLoader.defineClass()		=> 加载字节码
*/

5.AbstractMapDecorator类

这个类是java.util.Map接口的装饰器(Decorator),它允许你通过包装另一个Map实现来添加额外的功能或修改Map的行为,而无需修改原始Map实现的代码。

public abstract class AbstractMapDecorator implements Map {
    protected transient Map map;

    protected AbstractMapDecorator() {
    }

    public AbstractMapDecorator(Map map) {
        if (map == null) {
            throw new IllegalArgumentException("Map must not be null");
        } else {
            this.map = map;
        }
    }

    protected Map getMap() {
        return this.map;
    }

    public void clear() {
        this.map.clear();
    }

    public boolean containsKey(Object key) {
        return this.map.containsKey(key);
    }

    public boolean containsValue(Object value) {
        return this.map.containsValue(value);
    }

    public Set entrySet() {
        return this.map.entrySet();
    }

    public Object get(Object key) {
        return this.map.get(key);
    }

    public boolean isEmpty() {
        return this.map.isEmpty();
    }

    public Set keySet() {
        return this.map.keySet();
    }

    public Object put(Object key, Object value) {
        return this.map.put(key, value);
    }

    public void putAll(Map mapToCopy) {
        this.map.putAll(mapToCopy);
    }

    public Object remove(Object key) {
        return this.map.remove(key);
    }

    public int size() {
        return this.map.size();
    }

    public Collection values() {
        return this.map.values();
    }

    public boolean equals(Object object) {
        return object == this ? true : this.map.equals(object);
    }

    public int hashCode() {
        return this.map.hashCode();
    }

    public String toString() {
        return this.map.toString();
    }
}

调试分析

基本过程和CC1链一致,主要是将最后的恶意代码触发由InvokerTransformer改装成InstantiateTransformer,然后利用TrAXFilter来调用TemplatesImpl来加载Java字节码

Gadget Chain

/* Gadget Chaain*/
ObjectInputStream.readObject()
	AnnotationInvocationHandler.readObject()
    	LazyMap.readObject()
    		Map(Proxy).entrySet()
    			LazyMap.get()
    				InstantiateTransformer.transform()
    					TrAXFilter.TrAXFilter()
    						TemplatesImpl.newTransformer()
    							TemplatesImpl.getTransletInstance()

调试过程

  • 看调用栈,几乎就是CC1那条路,不赘述了吧

image-20230912211645657

标签:map,序列化,Java,InstantiateTransformer,new,return,null,public,CommonsCollections3
From: https://www.cnblogs.com/icfh/p/17697898.html

相关文章

  • Error:java: 错误: 不支持发行版本 5(17)
    调试IDEA时出现如下错误, 参考:https://blog.csdn.net/xiao_yi_xiao/article/details/119142118 出现原因:本地配置jdk和idea默认的jdk不匹配JDK环境13 Module对应5 ......
  • Java 接收参数的7种方式
    1.直接在Controller方法参数上配置参数名@RequestMapping("/method01")publicStringmethod01(Stringname,Integerage,Doublemon){Useruser=newUser();user.setName(name);user.setAge(age);user.setMoney(mon);r......
  • 深入理解 @PostConstruct 注解及其在 Java 开发中的应用
    深入理解@PostConstruct注解及其在Java开发中的应用本文将深入探讨Java中的@PostConstruct注解,介绍其作用、使用方法和常见应用场景。我们将详细解释注解的生命周期和执行顺序,以及如何正确使用@PostConstruct注解来进行初始化操作。通过本文的学习,读者将对@PostConstru......
  • Java入门
    java入手注释pvsmJava入口点程序逻辑中枢sout输出//单行注释/**/多行注释/**回车文档注释标识符注意事项标识符不能含关键字标识符需大小写字母开头或$与_开头标识符后可接大小写字母与$_和数字的任意组合标识符大小写敏感八大基本数据类型整数类型字节......
  • Java入门
    java入手注释pvsmJava入口点程序逻辑中枢sout输出//单行注释/**/多行注释/**回车文档注释标识符注意事项标识符不能含关键字标识符需大小写字母开头或$与_开头标识符后可接大小写字母与$_和数字的任意组合标识符大小写敏感八大基本数据类型整数类型字节......
  • JavaScript深拷贝的具体实现方法解析
    什么是深拷贝?深拷贝是指创建一个新对象或数组,使其与原始对象或数组具有相同的值,但是两者是完全独立的,互不影响。深拷贝不仅复制了对象或数组本身,还递归复制了其所有嵌套的对象和数组,确保所有层级的数据都是独立的。实现深拷贝的方法在JavaScript中,实现深拷贝的方法有很多种,下面将介......
  • 无涯教程-JavaScript - TBILLPRICE函数
    描述TBILLPRICE函数返回面值$100的国库券的价格。语法TBILLPRICE(settlement,maturity,discount)争论Argument描述Required/OptionalSettlement国库券的结算日期。证券结算日期是发行国库券给买方的发行日期之后的日期。RequiredMaturity国库券的到期日。......
  • 初始JavaScript
    typora-copy-images-to:media基本语法JavaScript的历史: 在95年以前,就有很多上网的用户了,当时的带宽只有28.8kb/s,用户要进行表单的验证时,点击提交按钮,直接就将数据发送到服务器了,受限于带宽的关系,浏览器和服务器的通信很慢,大概一次通信需要30s的时间。 这样,问题就出现了,我们平常......
  • 无涯教程-JavaScript - SYD函数
    描述SYD函数返回指定期间资产的年折旧数字。语法SYD(cost,salvage,life,per)争论Argument描述Required/OptionalCostTheinitialcostoftheasset.RequiredSalvageThevalueattheendofthedepreciation(sometimescalledthesalvagevalueoftheass......
  • 怒赞了,阿里P8面试官推荐的Java高并发核心编程文档
    文章很长,且持续更新,建议收藏起来,慢慢读!疯狂创客圈总目录博客园版为您奉上珍贵的学习资源:免费赠送:《尼恩Java面试宝典》持续更新+史上最全+面试必备2000页+面试必备+大厂必备+涨薪必备免费赠送:《尼恩技术圣经+高并发系列PDF》,帮你实现技术自由,完成职业升级,薪......