跳转至

CVE-2023-21839(Weblogic JNDI注入漏洞)

漏洞描述

由于Weblogic IIOP/T3协议存在缺陷,当IIOP/T3协议开启时,允许未经身份验证的攻击者通过IIOP/T3协议网络访问攻击存在安全风险的WebLogic Server,漏洞利用成功WebLogic Server可能被攻击者接管执行任意命令导致服务器沦陷或者造成严重的敏感数据泄露。

影响版本

  • Weblogic 12.2.1.3.0
  • Weblogic 12.2.1.4.0
  • Weblogic 14.1.1.0.0

环境配置

  • Vulhub项目
  • Docker-compose启动

漏洞复现

漏洞存在验证

可以从console页面看到版本号为12.2.1.3.0,符合漏洞利用条件

MSF复现

Text Only
search cve:2023-21839

其他复现方式可以参考:https://www.freebuf.com/vuls/364212.html

漏洞原理

T3协议

T3协议是一种Weblogic RMI 调用时的通信协议, 对于JAVA RMI(Remote Method Invocation) 来说,基础的通信协议是JRMP,但是Weblogic中的T3协议就是一种优化方案。

T3协议的特点:

  1. 服务端可以持续追踪监控客户端是否存活(心跳机制),通常心跳的间隔为60秒,服务端在超过240秒未收到心跳即判定与客户端的连接丢失。
  2. 通过建立一次连接可以将全部数据包传输完成,优化了数据包大小和网络消耗

参考文章:

Java安全之初探weblogic T3协议漏洞

Weblogic CVE之旅之T3协议浅学习

IIOP协议

**GIOP**是一种CORBA规范定义的协议,用于在分布式对象之间进行通信和交互,定义了对象请求、响应、异常、命名等基本的通信模式和协议规范。简单来说,GIOP就是一个抽象的协议标准,定义了通信模式和协议规范等信息,并不是具体实现的协议。

**IIOP**是一种实现了GIOP协议的TCP/IP协议栈,它使得CORBA对象能够通过Internet进行分布式通信和交互。简单来说,IIOP协议是在TCP/IP层面上实现的GIOP协议。

**RMI-IIOP**是一种Java远程方法调用协议的实现方式,它在IIOP协议之上扩展了Java RMI协议,使得Java对象可以通过IIOP协议进行分布式通信和交互。简单来说,RMI-IIOP协议就是在IIOP协议的基础上集合了RMI的远程调用Java对象的功能。(本文会将Weblogic部分RMI-IIOP作为IIOP协议来看待)

在文章《 Weblogic IIOP 协议NAT 网络绕过》中提到 “T3 协议本质上 RMI 中传输数据使用的协议, RMI-IIOP 是可以兼容 RMI 和 IIOP 的,所以在 Weblogic 中只要可以通过 T3 序列化恶意代码的都可以通过 IIOP 协议进行序列化”。对于启用了IIOP和T3协议的Weblogic而言,序列化数据协议传输的过程中是没有本质上区别的,同时在Weblogic通信过程中可能会出现NET网络问题。因此,为了解决Java序列化跨语言问题以及IIOP的网络问题,我选择了IIOP协议作为此次Weblogic序列化协议研究的重点。

参考文章:

Weblogic序列化漏洞与IIOP协议

Java中的IDAP协议

LDAP(Lightweight Directory Access Protocol) LDAP代表轻型目录访问协议(Lightweight Directory Access Protocol)。顾名思义,它是用于访问目录服务的轻量级协议,特别是基于X.500协议的目录服务。LDAP运行于TCP/IP连接上或其他面向传输服务的连接上。LDAP是IETF标准跟踪协议,并且在“Lightweight Directory Access Protocol (LDAP) Technical Specification Road Map”RFC4510中进行了指定。

目录是专门为**搜索**和**浏览**而设计的专用**数据库**,支持基本的查找和更新功能。

提供目录服务的方式有很多。不同的方法允许将不同类型的信息存储在目录中,对如何引用,查询和更新该信息,如何防止未经授权的访问等提出不同的要求(这些由LDAP定义)。一些目录服务是本地的,提供本地服务;一些目录服务是全球性的,向更广泛的环境(例如,整个Internet)提供服务。全局服务通常是分布式的,这意味着它们包含的数据分布在许多机器上,所有这些机器协作以提供目录服务。通常,全局服务定义统一的名称空间,无论在何处访问,都可以提供相同的数据视图。

Java连接LDAP服务端

现在可以从Java程序访问LDAP。 向您展示如何执行此操作的最佳方法是通过示例程序。 该程序将执行以下任务:

  • 创建一个新的LDAP对象
  • 查看LDAP对象
  • 将新属性添加到LDAP对象
  • 修改LDAP对象上的属性
  • 删除LDAP对象上的属性
  • 删除LDAP对象
Java
java复制代码package test;

import java.util.Properties;
import javax.naming.Context;
import javax.naming.NamingException;
import javax.naming.directory.*;

public class LDAPTest {

    public void run() {
        try {
            DirContext context = getContext();
            String name = "employeeNumber=00001,ou=system";
            createLDAPObject(context, name);
            createAttribute(context, name, "displayName", "JOBS");
            viewAttribute(context, name, "displayName");
            updateAttribute(context, name, "displayName", "STEVE");
            viewAttribute(context, name, "displayName");
            removeAttribute(context, name, "displayName");
            removeLDAPObject(context, name);
        } catch (NamingException e) {
            e.printStackTrace();
        }
    }

    private void removeLDAPObject(DirContext context, String name) throws NamingException {
        context.destroySubcontext(name);
    }

    private void createLDAPObject(DirContext context, String name) throws NamingException {
        Attributes attributes = new BasicAttributes();

        Attribute attribute = new BasicAttribute("objectClass");
        attribute.add("inetOrgPerson");
        attributes.put(attribute);

        Attribute sn = new BasicAttribute("sn");
        sn.add("Steve");
        attributes.put(sn);

        Attribute cn = new BasicAttribute("cn");
        cn.add("Jobs");
        attributes.put(cn);

        attributes.put("telephoneNumber", "123456");
        context.createSubcontext(name, attributes);
    }

    private void removeAttribute(DirContext context, String name, String attrName) throws NamingException {
        Attribute attribute = new BasicAttribute(attrName);
        ModificationItem[] item = new ModificationItem[1];
        item[0] = new ModificationItem(DirContext.REMOVE_ATTRIBUTE, attribute);
        context.modifyAttributes(name, item);
    }

    private void createAttribute(DirContext context, String name, String attrName, Object attrValue) throws NamingException {
        Attribute attribute = new BasicAttribute(attrName, attrValue);
        ModificationItem[] item = new ModificationItem[1];
        item[0] = new ModificationItem(DirContext.ADD_ATTRIBUTE, attribute);
        context.modifyAttributes(name, item);
    }

    private void updateAttribute(DirContext context, String name, String attrName, Object attrValue) throws NamingException {
        Attribute attribute = new BasicAttribute(attrName, attrValue);
        ModificationItem[] item = new ModificationItem[1];
        item[0] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE, attribute);
        context.modifyAttributes(name, item);
    }

    private void viewAttribute(DirContext context, String name, String attrName) throws NamingException {
        Attributes attrs = context.getAttributes(name);
        System.out.println(attrName + ":" + attrs.get(attrName).get());
    }

    private DirContext getContext() throws NamingException {
        Properties properties = new Properties();
        properties.put(Context.INITIAL_CONTEXT_FACTORY,
                "com.sun.jndi.ldap.LdapCtxFactory");
        properties.put(Context.PROVIDER_URL, "ldap://localhost:10389");

        return new InitialDirContext(properties);
    }

    public static void main(String[] args) {
        new LDAPTest().run();
    }
}

参考文章:

https://juejin.cn/post/7159130019691200543#heading-7

漏洞分析

参考文章:

CVE-2023-21839分析

修复建议

  • 升级Weblogic版本或安装补丁
  • 禁用T3和IIOP协议

请参考以下链接尽快修复:

https://www.oracle.com/security-alerts/cpujan2023.html


参考文章:

https://www.secrss.com/articles/51214