Apache OFBiz CVE-2021-29200 简要分析
2021-05-10 18:25:27 Author: xz.aliyun.com(查看原文) 阅读量:131 收藏

本文作者:r00t4dm@Cloud-Penetrating Arrow Lab & Longofo@知道创宇404实验室

OFBiz PMC针对CVE-2021-26295漏洞修复的commit如下:

@Override
    protected Class<?> resolveClass(ObjectStreamClass classDesc) throws IOException, ClassNotFoundException {
        String className = classDesc.getName();
        // BlackList exploits; eg: don't allow RMI here
        if (className.contains("java.rmi.server")) {
            Debug.logWarning("***Incompatible class***: "
                    + classDesc.getName()
                    + ". java.rmi.server classes are not allowed for security reason",
                    "SafeObjectInputStream");
            return null;
        }
        if (!whitelistPattern.matcher(className).find()) {
            // DiskFileItem, FileItemHeadersImpl are not serializable.
            if (className.contains("org.apache.commons.fileupload")) {
                return null;
            }
            Debug.logWarning("***Incompatible class***: "

我提交给OFBiz社区的利用方式是RemoteObjectInvocationHandler作为JRMPClient,这个补丁代码也刚好解决了RemoteObjectInvocationHandler作为JRMPClient的利用方式,并分配了CVE-2021-26295。

令我感兴趣的是当检测到敏感对象时它并不是抛出异常,而是返回null,我询问了PMC并得到这样的答复

That's purely syntactic (proof it works as is). I used null for a reason and I have to check what it entails to replace null by an exception. Else I'd be happy to replace it

这种返回null的修复方式本身是没有问题的,只是检测边界需要扩大,如果检测边界不变那必须抛出异常。
所以这个补丁的代码是存在问题的,通过使用java.下的代码可以绕过白名单。

private static final String[]DEFAULT_WHITELIST_PATTERN= {
        "byte\\[\\]", "foo", "SerializationInjector",
        "\\[Z", "\\[B", "\\[S", "\\[I", "\\[J", "\\[F", "\\[D", "\\[C",
        "java..*", "sun.util.calendar..*", "org.apache.ofbiz..*",
        "org.codehaus.groovy.runtime.GStringImpl", "groovy.lang.GString"};

接着需要找一个符合白名单并且是远程对象的类,通过使用LiveRef打开通道,值得注意的是sun.rmi.server.UnicastRef是连接的抽象或者封装,所以这里可以直接使用sun.rmi.server.UnicastRef即可。

我第二次交给OFBiz社区的利用对象是javax.management.remote.rmi.RMIConnectionImpl_Stub,因为javax.management.remote.rmi.RMIConnectionImpl_Stub符合白名单正则表达式,又由于反序列化的递归性质,父类反序列化为空不影响子类反序列化流程,所以使用javax.management.remote.rmi.RMIConnectionImpl_Stub可以绕过这个补丁。

后续我针对这个问题给官方提供的补丁代码是

if (className.contains("java.rmi.server")) {
            Debug.logWarning("***Incompatible class***: "
                    + classDesc.getName()
                    + ". java.rmi.server classes are not allowed for security reason",
                    "SafeObjectInputStream");
//            return null;
            throw new InvalidObjectException("no safe!!" + className);
        }

并要求OFBiz社区关闭SOAP和HTTPEngine的入口,我想这个Endpoint应该不会有问题了。


文章来源: http://xz.aliyun.com/t/9556
如有侵权请联系:admin#unsafe.sh