前言
Apache OFBiz是一个电子商务平台,用于构建大中型企业级、跨平台、跨数据库、跨应用服务器的多层、分布式电子商务类应用系统。是美国阿帕奇(Apache)基金会的一套企业资源计划(ERP)系统。该系统提供了一整套基于Java的Web应用程序组件和工具。
影响版本
Apache Ofbiz <= 18.12.14
环境搭建
从github上拉取源码:https://github.com/apache/ofbiz-framework/releases/tag/release18.12.14
使用命令创建测试数据:gradlew cleanAll loadAll
将项目导入到IDEA,执行build后会在build/libs下生成一个ofbiz.jar
添加JAR Application,设置JAR的路径后启动就可以开始debug
漏洞分析
网上公开的POC如下:
POST /webtools/control/forgotPassword/././ProgramExport HTTP/1.1
Host: your-ip user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:126.0) Gecko/20100101 Firefox/126.0
Content-Type: application/x-www-form-urlencoded
groovyProgram=\u0074\u0068\u0072\u006f\u0077\u0020\u006e\u0065\u0077\u0020\u0045\u0078\u0063\u0065\u0070\u0074\u0069\u006f\u006e\u0028\u0027\u0069\u0064\u0027\u002e\u0065\u0078\u0065\u0063\u0075\u0074\u0065\u0028\u0029\u002e\u0074\u0065\u0078\u0074\u0029\u003b
该漏洞源于org.apache.ofbiz.webapp.control.ControlFilter类对路径(请求URL中的特殊字符(如 ;、%2e)限制不当导致攻击者能够绕过后台功能点的过滤器验证,并通过/webtools/control/ProgramExport接口的编程导出功能执行任意Groovy代码获取系统权限。
权限绕过
直接访问路径需要认证
在ProgramExport.groovy中打断点,调用栈如下
随便找个地方下断点后直接访问需要登录的路径:https://127.0.0.1:8443/webtools/control/ProgramExport
String viewName = (UtilValidate.isNotEmpty(overrideViewUri) && (eventReturn == null || "success".equals(eventReturn))) ? overrideViewUri : nextRequestResponse.value;
renderView(viewName, requestMap.securityExternalView, request, response, saveName);
发现eventReturn变成了error,根据上面的代码逻辑viewName变login,如果没有被过滤的情况应该会是想要访问的页面名称。因此在renderView中,本次请求中需要渲染的视图会重新跳转到登录页面。
往前找,是在哪里识别请求路径的
这里requestMap.securityAuth为true时进入条件,为eventReturn赋值为error,而checkLoginReturnString是调用this.runEvent()的结果,这里面应该就是用户的身份认证的逻辑。最后会进入到checkLogin判断是否是登录状态,此处会返回error。
换成可以绕过登录的路径:https://127.0.0.1:8443/webtools/control/forgotPassword/././ProgramExport
这时的requestMap.securityAuth = false 不会进入if检查登录状态,继续往前,看是哪里设置的这个参数。
定位到这里生成的RequestMap
对象 。
不过具体判断访问的uri是否需要授权是在resolveURI()中,但是我没有找到context是在哪里获取到的。
可以看到ctx中包含了forgotPassword。因此,当访问接口为forgotPassword时,是不需要验证的。
后台RCE
这里可以执行Groovy代码
修补情况
https://issues.apache.org/jira/browse/OFBIZ-13092
删除了这段代码以防止..绕过。
但根据上面的绕过分析,似乎直接访问直接访问/webtools/control/forgotPassword/ProgramExport也是可以绕过验证的。