前尘—数据连接池下的至暗之处

VSole2023-03-30 09:44:17

前言

这是分析Java反序列化系列的第四篇文章,内容的填充度已经过半。此系列的每一篇文章 都会对漏洞产生的原因进行剖析,理解事物的原理往往在攻击时发挥奇效。

C3P0是一个开源的JDBC连接池,它实现了数据源和JNDI绑定,支持JDBC3规范和JDBC2的标准扩展。目前使用它的开源项目有Hibernate、Spring等。

序列化与反序列化

既然是反序列化漏洞必然要提起的就是序列化与反序列化,如果还有读者对这个概念不清楚请参考文章《前尘——与君再忆CC链》,在Java反序列化漏洞中,序列化和反序列化是理解这些漏洞的基本条件。

导入Maven依赖

<dependencies>
        <dependency>
            <groupId>com.mchangegroupId>
            <artifactId>c3p0artifactId>
            <version>0.9.5.5version>
        dependency>
    dependencies>

此依赖为c3p0最新版本依赖,更新于2019年12月

最新版本没有修复此问题

漏洞跟踪

直接进入网上公开的链条类打开就是一顿分析com/mchange/v2/c3p0/impl/PoolBackedDataSourceBase

分析了这么多的漏洞链条,其实道理很简单。将网上纰漏的漏洞类打开直接往下翻往下翻找到readObject()方法对其内容进行跟进就可以,三板斧直接一顿怼。

private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
        short version = ois.readShort();
        switch(version) {
        case 1:
            Object o = ois.readObject();
            if (o instanceof IndirectlySerialized) {
                o = ((IndirectlySerialized)o).getObject();
            }
            this.connectionPoolDataSource = (ConnectionPoolDataSource)o;
            this.dataSourceName = (String)ois.readObject();
            o = ois.readObject();
            if (o instanceof IndirectlySerialized) {
                o = ((IndirectlySerialized)o).getObject();
            }
            this.extensions = (Map)o;
            this.factoryClassLocation = (String)ois.readObject();
            this.identityToken = (String)ois.readObject();
            this.numHelperThreads = ois.readInt();
            this.pcs = new PropertyChangeSupport(this);
            this.vcs = new VetoableChangeSupport(this);
            return;
        default:
            throw new IOException("Unsupported Serialized Version: " + version);
        }
    }

获取版本,使用switch case关键字做分支处理。这里拿到的version是1,所有走case1.

Object o = ois.readObject();

此语句反序列化出一个referenceSerialized对象,instanceof关键字用来测试一个对象是否为一个类的实例。com.mchange.v2.naming.ReferenceIndirector类中存在内部类ReferenceSerialized实现了IndirectlySerialized接口,所以类型比对通过。

然后调用IndirectlySerialized类的getObject方法,但是ReferenceSerialized实现了IndirectlySerialized接口。所以实际使用多态的方式调用的是ReferenceSerialized的getObject方法

ReferenceSerialized( Reference   reference,
                 Name        name,
                 Name        contextName,
                 Hashtable   env )
    {
        this.reference = reference;
        this.name = name;
        this.contextName = contextName;
        this.env = env;
    }

在ReferenceSerialized构造函数中传入四个值进行赋值

public Object getObject() throws ClassNotFoundException, IOException
{
        try
        {
            Context initialContext;
            if ( env == null )
            initialContext = new InitialContext();
            else
            initialContext = new InitialContext( env );
            Context nameContext = null;
            if ( contextName != null )
            nameContext = (Context) initialContext.lookup( contextName );
            return ReferenceableUtils.referenceToObject方法将( reference, name, nameContext, env ); 
        }
        catch (NamingException e)
        {
            //e.printStackTrace();
            if ( logger.isLoggable( MLevel.WARNING ) )
            logger.log( MLevel.WARNING, "Failed to acquire the Context necessary to lookup an Object.", e );
            throw new InvalidObjectException( "Failed to acquire the Context necessary to lookup an Object: " + e.toString() );
        }
    }

如果contextName不为空则使用lookup,进行rmi触发远程调用,但是这里的contextName为空只能向下分析

return中调用了ReferenceableUtils类的referenceToObject方法将构造函数中传入的四个值当作参数传入继续跟进。

reFerenceToObject根据Reference对象来获取工厂类的名字,以及工厂类的地址,接着拿到类加载器,拿到appClassLoader(一般程序中类加载都用这个,它的上面还有jre核心类运行的加载(rt.jar)bootstrap classloader和扩展类加载ext classloader)

接着就判断工厂类地址是否为空,不为空则去远程地址加载工厂类,这里用到了urlclassLoader,然后通过class.forname生成一个class 类型的实例,就加载到了工厂类,即我们的恶意字节码类

总结

个人认为此个序列化漏洞大致了解即可,因为此依赖新的架构项目已经不被广泛使用了,并且maven可以的看到最后一次更新在2019年。

Java反序列化一直是一个老生常谈的问题,理解这些原理性的知识可以更好的帮助我们找到执行链,你我终有一天也会发现理解事物的本质是如此重要。

序列化连接池
本作品采用《CC 协议》,转载必须注明作者和本文链接
C3P0是一个开源的JDBC连接池,它实现了数据源和JNDI绑定,支持JDBC3规范和JDBC2的标准扩展。
Xray捡洞中的高频漏洞
2021-12-28 04:33:22
用 X-Ray 刷洞发现一些出现频率高的漏洞,把漏洞原理和利用方式稍作整理,按照危害排名,低危漏洞可以收集一些信息然后深度利用变高危。
Set第三个参数过期时间单位是秒。然后这个Set中存在的就是网点还没有揽收的件,这时候通过Count就会知道这个网点今天还有多少件没有揽收。如果get,set两次以上,建议用getall,setall。
目前,多数项目会有多数据源的要求,或者是主从部署的要求,所以我们还需要引入mybatis-plus关于多数据源的依赖:。#设置默认的数据源或者数据源组,默认值即为master. true未匹配到指定数据源时抛异常,false使用默认数据源。表名注解,用于标识实体类对应的表。其说明如下,关于这些书写,常规情况基本很少用到,不做多余解释了:@Documented
假设Mysql中canal_test库下有一张表policy_cred,需要统计实时统计policy_status状态为1的mor_rate的的变化趋势,并标注比率的风险预警等级。?本次安装的canal版本为1.1.2,Canal版本最后在1.1.1之后。server端采用MQ模式,MQ选用Kafka。服务器系统为Centos
如果指定了一个类为final,则该类所有的方法都是final的。此举能够使性能平均提高50% 。因为对这些大对象的操作会造成系统大的开销,稍有不慎,将会导致严重的后果。
一般有运行nginx服务器的用户组,nginx进程pid存放路径,日志存放路径,配置文件引入,允许生成worker process数等。#user administrator administrators; #配置用户或者组,默认为nobody nobody。keepalive_requests 120;#单连接请求上限次数。
神器 Nginx 的学习手册
2022-02-23 07:35:52
Nginx 是一个高性能的 HTTP 和反向代理服务器,特点是占用内存少,并发能力强,事实上 Nginx 的并发能力确实在同类型的网页服务器中表现较好。 Nginx 专为性能优化而开发,性能是其最重要的要求,十分注重效率,有报告 Nginx 能支持高达 50000 个并发连接数。 01 Nginx 知识网结构图 Nginx 的知识网结构图如下:
是个抓取网络数据包的库,这么说可能还有点抽象,但是抓包工具大家可能都使用过。场景1:网络流量分析对网络设备流量进行实时采集以及数据包分析。场景2:伪造数据包不少网络安全工具,需要伪造网络数据包,填充上必要的协议字段后发送给对端设备,从而达到一些目的。
VSole
网络安全专家