Ofbiz未授权漏洞

Posted by Azeril on August 13, 2024

Apache OFBiz

docker环境 vulhub/ofbiz/CVE-2020-9496/docker-compose.yml at master · vulhub/vulhub · GitHub

一、前言

一个强大的顶级Apache项目OFBiz是一企业资源规划(ERP)系统其中包含一个大量库实体服务和功能

J2EE框架编写的

image-20240813205911379

   <request-map uri="NewSalesInvoice">
        <security https="true" auth="true"/>   //https  auth=true说明开启鉴权
        <response name="success" type="view" value="NewSalesInvoice"/>  //映射的视图名字
    </request-map>

applications

ControlFilter过滤器 /*

allowedPaths : /error:/control:/select:/index.html:/index.jsp:/default.html:/default.jsp:/images

redirectPath:/control/main

这里forceRedirectAll的值在web.xml中是没找到的

/control/mainimage-20240814154238331

这里redirectAll为null直接进入下一个if

image-20240814164108006

这里会进入if,这里requestURL后面是replace把;和.替换为空,这里.可以双写绕过

request.getRequestURL() http://localhost:8080/jqueryLearn/resources/request.jsp 
request.getRequestURI() /jqueryLearn/resources/request.jsp
request.getContextPath()/jqueryLearn 
request.getServletPath()/resources/request.jsp 

image-20240814170817811

哈后面是一个 equals比较,和原来没replace,寄!

requestUri = new URI(requestUri).normalize().toString();
这段代码的主要目的是确保 requestUri 是一个干净且标准化的 URI,消除任何潜在的路径问题或无效字符。
"/myapp/../resource/./path/" ----》"/myapp/resource/path/"

image-20240814165541401

持续跟进hasBasePermission是返回true,!true,所以不进入这个if语句

image-20240814172643988

上面一个contains 白名单

allowedPaths : /error:/control:/select:/index.html:/index.jsp:/default.html:/default.jsp:/images

分析一下上面这个while语句,如果包含则返回true,如果不包含则进入while循环 ,总结没用就是不包含上面这几个路径就行了

image-20240814175342011

然后会进入doFilter语句

就是uri中不包含  .. ;这种特殊符号并且不包含allowedPaths中的路径

ContextFilter /*

全是一些setAttribute这种的赋值

image-20240814180921770

SameSiteFilter /*

ControlServlet

image-20240814210415997

http://localhost:8080/nowjava/book/show.do 则 webappName=nowjava rname=book

image-20240814205826599

这里获取当前上下文的,把/去掉了

一路session.get set赋值

image-20240814211308491

这里会调用到handler的doRequest方法中

下面看以下登录校验

Apache Ofbiz RCE (CVE-2020-9496) 漏洞分析

image-20240815191258108

看实现方法最后锁定在了 LoginWorker#checkLogin()

image-20240815193114507

首先看checkLogout方法,进去了看session中的值,这里返回为null image-20240815194216539

看一下这个"error".equals(login(request,response))

image-20240815194556341

前面正常操作这里 delegator获取的值为null直接下面这个赋值后面没用

image-20240815200811153

UtilValidate就是当getparameter和session中没用username password的时候的一个,提示语(类似账号密码不能为空)

所以说下面这个(unpwErrMsgList.isEmpty()的值是我们可控的 如果进入if{

一个提示 返回 requirePasswordChange或者error这个也是我们可控的,由requirePasswordChange控制

}

image-20240815201519898

然后返回来看这个,感觉原本是返回error,但我们能让它返回requirePasswordChange

但是这里怎么都要进入这个if(username== null 里面

因为逻辑是下述,所以发生冲突

username password 一个为空才能进入这个if判断但是如果有一个为空有需要进入上述的if判断里面

if (!unpwErrMsgList.isEmpty()) {
            request.setAttribute("_ERROR_MESSAGE_LIST_", unpwErrMsgList);
            return  requirePasswordChange ? "requirePasswordChange" : "error";
        }

image-20240815205511882

下面这里,dispatcher和 servletContext的值是不可控,tenantId是可控的

下面如果为空会从request中获得

image-20240815205936485

这里出现了一个问题就是,是从这里获得而来的,而因为没开调试这里 不确定request有没有setattribute,如果没有的话,那么上面就报错返回error了

        Delegator delegator = (Delegator) request.getAttribute("delegator");

哈哈哈哈哈哈找了半天这个洞不是这个这个版本 这个版本是过滤器没配置鉴权,直接调用后台然后触发反序列化漏洞。


Creative Commons License
本作品采用CC BY-NC-ND 4.0进行许可。转载,请注明原作者 Azeril 及本文源链接。