Apache OFBiz
docker环境 vulhub/ofbiz/CVE-2020-9496/docker-compose.yml at master · vulhub/vulhub · GitHub
一、前言
一个强大的顶级Apache项目,OFBiz是一企业资源规划(ERP)系统,其中包含一个大量库、实体、服务和功能。
J2EE框架编写的
<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/main
这里redirectAll为null直接进入下一个if
这里会进入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
哈后面是一个 equals比较,和原来没replace,寄!
requestUri = new URI(requestUri).normalize().toString();
这段代码的主要目的是确保 requestUri 是一个干净且标准化的 URI,消除任何潜在的路径问题或无效字符。
"/myapp/../resource/./path/" ----》"/myapp/resource/path/"
持续跟进hasBasePermission
是返回true,!true,所以不进入这个if语句
上面一个contains
白名单
allowedPaths : /error:/control:/select:/index.html:/index.jsp:/default.html:/default.jsp:/images
分析一下上面这个while语句,如果包含则返回true,如果不包含则进入while循环 ,总结没用就是不包含上面这几个路径就行了
然后会进入doFilter
语句
就是uri中不包含 .. ;这种特殊符号,并且不包含allowedPaths中的路径
ContextFilter /*
全是一些setAttribute这种的赋值
SameSiteFilter /*
ControlServlet
http://localhost:8080/nowjava/book/show.do 则 webappName=nowjava rname=book
这里获取当前上下文的,把/去掉了
一路session.get set赋值
这里会调用到handler的doRequest
方法中
下面看以下登录校验
Apache Ofbiz RCE (CVE-2020-9496) 漏洞分析
看实现方法最后锁定在了 LoginWorker#checkLogin()
首先看checkLogout方法
,进去了看session中的值,这里返回为null
看一下这个"error".equals(login(request,response))
前面正常操作这里 delegator
获取的值为null直接下面这个赋值后面没用
UtilValidate
就是当getparameter和session中没用username password的时候的一个,提示语(类似账号密码不能为空)
所以说下面这个(unpwErrMsgList.isEmpty()
的值是我们可控的
如果进入if{
一个提示
返回 requirePasswordChange
或者error
这个也是我们可控的,由requirePasswordChange
控制
}
然后返回来看这个,感觉原本是返回error,但我们能让它返回requirePasswordChange
但是这里怎么都要进入这个if(username== null 里面
因为逻辑是下述,所以发生冲突
username password 一个为空,才能进入这个if判断,但是如果有一个为空,有需要进入上述的if判断里面
if (!unpwErrMsgList.isEmpty()) {
request.setAttribute("_ERROR_MESSAGE_LIST_", unpwErrMsgList);
return requirePasswordChange ? "requirePasswordChange" : "error";
}
下面这里,dispatcher和 servletContext的值是不可控,tenantId是可控的
下面如果为空会从request中获得
这里出现了一个问题就是,是从这里获得而来的,而因为没开调试这里 不确定request有没有setattribute,如果没有的话,那么上面就报错返回error了
Delegator delegator = (Delegator) request.getAttribute("delegator");
哈哈哈哈哈哈找了半天这个洞不是这个这个版本 这个版本是过滤器没配置鉴权,直接调用后台然后触发反序列化漏洞。
本作品采用CC BY-NC-ND 4.0进行许可。转载,请注明原作者 Azeril 及本文源链接。