帆软 FineReport/FineBI channel反序列化漏洞分析

文章详细介绍了FineReport和FineBI软件存在的反序列化漏洞,该漏洞可能导致任意代码执行。作者通过环境搭建、漏洞复现和分析,揭示了漏洞触发的关键步骤,包括GZIP压缩、Java反序列化过程,并指出ysoserial生成的payload不适用于此漏洞,而采用P牛提供的CB链可以成功触发漏洞。最后,文章提到了攻击流量的特征,即gzip压缩后的Java反序列化数据流。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

事件背景

热点漏洞

漏洞说明

1. 漏洞原理:FineReport/FineBI channel接口能接受序列化数据并对其进行反序列化。配合帆软内置CB链会导致任意代码执行。

2. 组件描述:FineReport是一款企业级报表设计和数据分析工具,它提供了丰富多样的组件,用于创建和展示数据报表。

FineBI 是一款企业级的商业智能 (BI) 平台,提供了丰富的功能和组件,用于数据分析、报表生成和数据可视化等任务

3. 影响版本: 2022-08-12 之前的 FineReport10.0/11.0、FineBI5.1 系列均受影响

漏洞复现

环境搭建:https://fine-build.oss-cn-shanghai.aliyuncs.com/finebi/5.1.5/stable_test/backup/2021-02-26/exe/spider/linux_unix_FineBI5_1-CN.sh

安装在虚拟机环境中,需要给虚拟机至少6G内存才能安装终端输入./linux_unix_FineBI5_1-CN.sh即可安装,安装后,直接运行程序,在环境的bin目录中输入命令

tail -F output.log

可以看到环境的URL,访问并登录后如下

向idea的jar库导入FineBI中web中的库,最后跑下脚本即可
EXP已隐藏,仅分享漏洞分析思路

服务器开启端口监听并执行Java代码

最后反弹shell成功,说明恶意执行成功

漏洞分析

访问漏洞接口/webroot/decision/remote/design/channel发现

对环境文件的接口搜索一下发现

看到一个类com.fr.decision.extension.report.api.remote.RemoteDesignResource.onMessage,在idea全局搜搜索查看可以发现

这里就是channel的入口了,步入WorkContext.handleMessage()中

继续跟进messageListener.handleMessage()

看到this.deserializeInvocation(var1, var2),看着想序列化的方法,继续跟进

这里跟进看SerializerHelper.deserialize()

这里的var1是上面传的GZipSerializerWrapper.wrap(InvocationSerializer.getDefault()),跟进看

这里返回的是GZipSerializerWrapper()对象,同时this.serializer为InvocationSerializer对象再回到前面

var0被包装,送入到var1中的deserialize中,前面提到传入返回的对象为GZipSerializerWrapper()因此找到GZipSerializerWrapper.deserialize步入

这里对传入的包再次进行包装最后送入this.serializer.deserialize(var2),前面提到this.serializer对象在构造函数里被赋值了,为InvocationSerializer,最后再步入InvocationSerializer.deserialize

出现了,有两个readObject(),Java反序列化的触发点,总结

请求体传入的字节 	byte[] var0
包装1:			ByteArrayInputStream var1 = new ByteArrayInputStream(var0);
包装2:			GZIPInputStream var2 = new GZIPInputStream(var1)
包装3:			CustomObjectInputStream var3 = new CustomObjectInputStream(var2)

反序列化:		   (Map)var3.readObject()

因此我们需要做的就是构造与几个包装刚好相反的触发链,根据web的包来看,发现其中自带CB1的链子

因此构造CB1链攻击,但是经过尝试,发现ysoserial生成的payload无法达到攻击目的且报了CB1的错

import com.fr.serialization.JDKSerializer;

import java.io.*;
import java.util.Base64;
import java.util.Map;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;

public class Test {
    public static void main(String[] args) {
        try {
            String base64String = getBase64();
            byte[] bytes = Base64.getDecoder().decode(base64String);

            // 使用Java反序列化漏洞利用工具生成一个包含恶意代码的序列化对象,并将其序列化成字节数组
            byte[] maliciousBytes = bytes;

            // 构造一个GZIP格式的字节数组,将恶意字节数组存储在GZIP数据块中
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            GZIPOutputStream gzipOutputStream = new GZIPOutputStream(baos);
            gzipOutputStream.write(maliciousBytes);
            gzipOutputStream.finish();
            byte[] gzipBytes = baos.toByteArray();

            // 将GZIP格式的字节数组封装成一个输入流对象,并作为var0参数传入Env函数中
            InputStream var0 = new ByteArrayInputStream(gzipBytes);
            Env(var0);

        }catch (Exception e){e.printStackTrace();}


    }

    private static void Env(InputStream var0) throws IOException, ClassNotFoundException {
        GZIPInputStream var2 = new GZIPInputStream(var0);
        JDKSerializer.CustomObjectInputStream var3 = new JDKSerializer.CustomObjectInputStream(var2);
        Map map = (Map) var3.readObject();
    }

    private static String getBase64() {
        return "";
    }
}

当将yso的包替换后则成功,最后得出结论应该是yso CB1的链子无法应用于该系统,可能是版本不匹配,不过P牛文章中提到的链子可以

CommonsBeanutils与无commons-collections的Shiro反序列化利用 | 离别歌

可以弹calc,说明P牛的链子可以触发该环境自带jar包的CB1,因此利用了P牛的链子构造出复现中的EXP。

最后攻击的流量为被gzip压缩后带有Java反序列化特征的流。

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

errorr0

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值