影响版本

Apache OFBiz < 17.12.07

环境搭建

这里使用Apache OFBiz 17.12.06jdk8u202搭建环境,配置如下

1.png

然后编译即可

2.png

编译完成后会生成一个build目录

3.png

然后配置JAR Application

4.png

这里的jre版本是OFBiz运行版本,上面的8u202Gradle编译时用的版本

漏洞分析

diff如下

5.png

可以看到这里新增了黑名单DEFAULT_DENYLIST,内容为rmi<,猜测可能是处理数据时出现的安全问题。和CVE-2021-26295一样,在framework\webapp\src\main\java\org\apache\ofbiz\webapp\event\SOAPEventHandler.java#invoke开始

6.png

跟进SoapSerializer#deserialize

7.png

跟进XmlSerializer#deserialize

8.png

跟进Xmlserializer#deserializeSingle

9.png

这里面判断了是否为某种标签然后做出特定处理,最后return deserializeCustom(element);

跟进Xmlserializer#deserializeCustom

10.png

这里将序列化数据先进行十六进制解码,再调用UtilObject#getObject

11.png

跟进UtilObject#getObjectException

12.png

这里wois使用了SafeObjectInputStream类

13.png

这里定义了反序列化时的黑白名单,黑名单为不能是java.rmi.server,白名单为

14.png

在修复版本中添加了黑名单<,从这里的匹配机制可以看出如果使用了<那么就会绕过黑白名单的处理,看一下后续是怎么解析的。跟进ObjectType#loadClass
15.png

可以看到这里取出了<之前的值

所以我们使用org.apache.commons.beanutils.BeanComparator<xxx即可绕过,但是到loadClass得先经过白名单,所以使用org.apache.commons.beanutils.BeanComparator<java.xxx即可。

当然在jdk会对类名进行判断,ObjectStreamClass#initNonProxy

16.png

跟进ObjectStreamClass#classNamesEqual

17.png

这里只截取了最后一个.后面的值,所以我们用org.apache.commons.beanutils.BeanComparator<java.BeanComparator即可绕过。

那我们应该怎么修改序列化数据中的类名呢,这里使用SerializationDumper来dump出序列化数据结构然后修改。

首先利用yso生成CommonsBeanutils1的payload,以十六进制输出

18.png

然后利用SerializationDumper输出序列化数据结构

java -jar SerializationDumper-v1.13.jar 十六进制

把这几处不满足白名单的都按照上面的绕过方法改一改

19.png

最后将其重新编译回去,得到序列化的二进制流

java -jar SerializationDumper-v1.13.jar -b res.txt rebuild.bin

将其十六进制编码后即为POC

漏洞复现

20.png