CVE-2023-20864 VMware Aria Operations for Logs 未授权反序列化漏洞分析

admin 2023年6月7日01:40:53评论141 views字数 6807阅读22分41秒阅读模式

01




漏洞背景




2023-04-20 VMware 官方发布安全更新 VMSA-2023-0007,其中漏洞 CVE-2023-20864 评分9.8, 是一个未授权反序列化漏洞,影响版本 8.10.2, 官方给出的修复方式是更新到 8.12 版本。

官方文档说明

  • https://kb.vmware.com/s/article/91831
  • https://www.vmware.com/security/advisories/VMSA-2023-0007.html

02




补丁分析




由于是未授权反序列化漏洞,所以从反序列化特征寻找漏洞补丁位置。

如下图,可以看到明显的反序列化修复逻辑。

新增 SerializationUtil, 使用 ValidatingObjectInputStream 方式来进行反序列化过滤,只允许反序列化传入的requestClass 类CVE-2023-20864 VMware Aria Operations for Logs 未授权反序列化漏洞分析

找到 SerializationUtil 的调用,在api-play-service 包中 InternalClusterController 类,分别对于三个请求处理方法 applyMembership , setTokenapproveMembership 进行了修正CVE-2023-20864 VMware Aria Operations for Logs 未授权反序列化漏洞分析

设置允许的反序列化白名单。

ApplyMembershipResult result = provider.applyMembership((ApplyMembershipRequest)SerializationUtil.deserializeSecure(ApplyMembershipRequest.class, is)); 
var5 = ok(SerializationUtils.serialize(result));

SetTokenResult result = provider.setToken((SetTokenRequest)SerializationUtil.deserializeSecure(SetTokenRequest.class, is));
 var5 = ok(SerializationUtils.serialize(result));

SetConfigResult result = provider.approveMembership((SetConfigRequest)SerializationUtil.deserializeSecure(SetConfigRequest.class, is)); 
var5 = ok(SerializationUtils.serialize(result));

03




服务组件说明




vRealize LogInsight 并不是单一的web服务架构,系统中包含了多个服务,其中修复的反序列化处理进程由 LogInsightDaemon 发起,而web进程由tomcat 进行处理

LogInsightDaemon

LogInsightDaemon 进程如下

/usr/lib/loginsight/application/3rd_party/bin/java ...... -cp /usr/lib/loginsight/application/lib/* ...... com.vmware.loginsight.daemon.LogInsightDaemon --wait=120

启动类为 com.vmware.loginsight.daemon.LogInsightDaemon

观察其逻辑,首先是一个启动进程,其中的重点服务有

  • Cassandra 数据库,监听 9042 端口
  • Thrift 服务 ,VMSA-2023-0001 中多个漏洞服务组件
  • Tomcat 服务,监听 443 和 80端口
  • API 服务,监听9000端口

Api 服务

观察其API 服务,可以看到是一个 *Play* Framework框架, 一种高效的Java和Scala Web应用程序 框架,具备异步非阻塞,无状态等特点

protected synchronized void start(ServiceRegistryClient registry) throws Exception {
        this.registry = registry;
        CollectionAgentsConfig agentCfg = (CollectionAgentsConfig)this.configurationHolder.getConfiguration(CollectionAgentsConfig.class);
        DistributedConfig distribCfg = (DistributedConfig)this.configurationHolder.getConfiguration(DistributedConfig.class);
        LogImporterConfig importerConfig = (LogImporterConfig)this.configurationHolder.getConfiguration(LogImporterConfig.class);
        ApiServerConfig asc = (ApiServerConfig)this.configurationHolder.getConfiguration(ApiServerConfig.class);
        this.setServerConfig(asc);
        DaemonInfo di = distribCfg.getDaemonForCurrentHost();
        this.setAPIToken(di.getToken());
        File root = new File(System.getProperty("user.dir"));
        GuiceApplicationBuilder builder = (GuiceApplicationBuilder)((GuiceApplicationBuilder)((GuiceApplicationBuilder)(new GuiceApplicationBuilder()).in(root)).in(Mode.PROD)).in(APIServiceController.class.getClassLoader());
        if (!SystemUtils.IS_WINDOWS) {
            System.setProperty("pidfile.path""/dev/null");
        }

        this.serverPort = asc.getServerPort();
        this.serverSecurePort = asc.getServerSecurePort();
        builder = (GuiceApplicationBuilder)builder.configure("play.server.http.port", Integer.toString(this.serverPort));
        builder = (GuiceApplicationBuilder)builder.configure("play.server.https.port", Integer.toString(this.serverSecurePort));
        String bindAddress = "0.0.0.0";
        if (!asc.shouldBindAllInterfaces()) {
            bindAddress = di.getHost(asc.getBindAddress());
            builder = (GuiceApplicationBuilder)builder.configure("play.server.http.address", bindAddress);
            builder = (GuiceApplicationBuilder)builder.configure("play.server.https.address", bindAddress);
        }

        System.setProperty("https.keyStore", FileUtils.join(new String[]{"application", FIPS.getInstance().getTomcatKeyStorePath()}));
        builder = (GuiceApplicationBuilder)builder.configure("play.server.https.keyStore.path", FileUtils.join(new String[]{"application", FIPS.getInstance().getTomcatKeyStorePath()}));
        if (FIPS.getInstance().isFIPSModeEnabled()) {
            builder = (GuiceApplicationBuilder)builder.configure("play.server.https.keyStore.algorithm""X.509");
            builder = (GuiceApplicationBuilder)builder.configure("play.server.https.keyStore.type", FIPS.getInstance().getKeyStoreType());
        }

        builder = (GuiceApplicationBuilder)builder.configure("play.server.https.keyStore.password", importerConfig.getSyslogSslKeystorePassword());
        builder = (GuiceApplicationBuilder)builder.configure("http.netty.option.child.keepAlive", Boolean.toString(true));
        builder = (GuiceApplicationBuilder)builder.configure("play.server.netty.eventLoopThreads", Integer.toString(NUM_NETTY_IO_THREADS));
        Application app = builder.build().asScala();
        ServerConfig sc = new ServerConfig(root, Option.apply(this.serverPort), Option.apply(this.serverSecurePort), bindAddress, app.mode(), System.getProperties(), app.configuration());
        this.server = (new NettyServerProvider()).createServer(sc, app);

        try {
            AgentManager.INSTANCE.setConfiguration(agentCfg.getClassMap());
        } catch (ParseError var13) {
            throw new ConfigurationException(var13);
        }

        this.setAgentDefaultConfig(agentCfg.getAgentConfigText());
        registry.registerInstance(RegistryUtils.serviceRegisterRequest(registry, this.server.mainAddress(), ServiceName.API_SERVICE.getInternalName(), ServiceInstanceType.REST));
        this.doPing(di.getHost(asc.getBindAddress()));
        this.cleanupEnabled = asc.getCleanupTmpEnabled();
        this.cleanupExpire = asc.getCleanupTmpExpire();
        this.cleanupInterval = asc.getCleanupTmpInterval();
        this.restartScheduler();
        this.serversStarted.set(true);
    }

重点关注其路由文件 api-play-service jar 包中的 routes 文件

对比8.10 和 8.10.2 ,可以看到路由中新增了三个路径 applyMembership 等,为此次触发接口CVE-2023-20864 VMware Aria Operations for Logs 未授权反序列化漏洞分析

Web 服务

web 服务由tomcat 启动,在 web.xml 部署文件中声明了 stripes Filter ,使用的是 stripes web框架(Stripes 是基于动作的MVC(模型视图控制器)框架)

<display-name>Stripes Filter</display-name>
    <filter-name>StripesFilter</filter-name>
    <filter-class> net.sourceforge.stripes.controller.StripesFilter
    </filter-class>

dynamicMappingfilter 注册了所有的actionBean ,通过uri 寻址 目标actionbean, 进入 net.sourceforge.stripes.controller.DispatcherServlet 处理CVE-2023-20864 VMware Aria Operations for Logs 未授权反序列化漏洞分析

在 LoginInterceptor , SecurityInterceptor 中进行了身份,权限判断。

LoginInterceptor 当请求上下文 user 为空时,且访问对象具备 NotAuthenticated 注解时,会绕过身份判断。CVE-2023-20864 VMware Aria Operations for Logs 未授权反序列化漏洞分析

APIProxyActionBean 是请求转发类,将请求转发到 NetUtils.LOCALHOST, UIConfigManager.getApiServerConfig().getServerPort() , request.getRequestURI()

这里的 ApiServerConfig 的 ServerPort 自然是指 9000 端口CVE-2023-20864 VMware Aria Operations for Logs 未授权反序列化漏洞分析

这样,当请求 web 服务的 api 路由时就会将请求转发给 api server 9000 端口,当请求路径是以下请求时就可以把body带入反序列化处理部分

  • /api/v2/internal/cluster/applyMembership
  • /api/v2/internal/cluster/setToken
  • /api/v2/internal/cluster/approveMembership

04




漏洞复现




使用ysoserial 构建反序列化数据作为body。此处以创建文件作为用例CVE-2023-20864 VMware Aria Operations for Logs 未授权反序列化漏洞分析

05




参考链接




    • https://kb.vmware.com/s/article/91831
    • https://www.vmware.com/security/advisories/VMSA-2023-0007.html
    • https://www.playframework.com/
    • https://github.com/StripesFramework/stripes


06




关于雪诺凛冬实验室




CVE-2023-20864 VMware Aria Operations for Logs 未授权反序列化漏洞分析

原文始发于微信公众号(雪诺凛冬实验室):CVE-2023-20864 VMware Aria Operations for Logs 未授权反序列化漏洞分析

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2023年6月7日01:40:53
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   CVE-2023-20864 VMware Aria Operations for Logs 未授权反序列化漏洞分析https://cn-sec.com/archives/1784636.html

发表评论

匿名网友 填写信息