Apache OFBiz未授权命令执行浅析(CVE-2023-51467)

Apache OFBiz未授权命令执行浅析(CVE-2023-51467)

未修复的权限绕过

还是之前那个遗留的问题,首先是权限绕过,首先还是做一个简单的回顾
关于登录的校验在org.apache.ofbiz.webapp.control.LoginWorker#checkLogin做处理来判断用户是否登录,可以看到这里的判断逻辑非常简单,跳过前两个判断,在后面只需要login返回的不是error,则为认证成功image

再来看看login的判断,在这里如果unPwErrMsglist不为null则可以直接返回requirePasswordChangeimage

因此知道这个其实你就可以去后台点一点就知道哪里能RCE了,但是我比较好奇OFBiz的路由处理,为什么最后能调用到ProgramExport.groovy

路由处理以及解惑

在web.xml当中可以看到仅有一个Servlet处理,继续跟入org.apache.ofbiz.webapp.control.ControlServletimage

doGET为例,忽略一些无关的逻辑,最终都是通过handler.doRequest做请求的处理

在这里我们先看看handler的获取处理,首先在servlet的初始化过程就进行了初始化操作

1
2
3
4
5
6
7
8
9
10
11
12
@Override
public void init() throws ServletException {
ServletContext ctx = getServletContext();
if (Debug.infoOn()) {
String path = ctx.getContextPath();
String webappName = path.isEmpty() ? path : path.substring(1);
Debug.logInfo("Loading webapp [" + webappName + "], located at " + ctx.getRealPath("/"), module);
}

// Initialize the request handler.
RequestHandler.getRequestHandler(ctx);
}

可以看到代码虽然不少,但其实就是从/WEB-INF/controller.xml下获取了路由的配置,并根据配置文件初始化了两个工厂类ViewFactory/EventFactory

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
public static RequestHandler getRequestHandler(ServletContext servletContext) {
RequestHandler rh = (RequestHandler) servletContext.getAttribute("_REQUEST_HANDLER_");
if (rh == null) {
rh = new RequestHandler(servletContext);
servletContext.setAttribute("_REQUEST_HANDLER_", rh);
}
return rh;
}

private RequestHandler(ServletContext context) {
// init the ControllerConfig, but don't save it anywhere, just load it into the cache
this.controllerConfigURL = ConfigXMLReader.getControllerConfigURL(context);
try {
ConfigXMLReader.getControllerConfig(this.controllerConfigURL);
} catch (WebAppConfigurationException e) {
// FIXME: controller.xml errors should throw an exception.
Debug.logError(e, "Exception thrown while parsing controller.xml file: ", module);
}
this.viewFactory = new ViewFactory(context, this.controllerConfigURL);
this.eventFactory = new EventFactory(context, this.controllerConfigURL);

this.trackServerHit = !"false".equalsIgnoreCase(context.getInitParameter("track-serverhit"));
this.trackVisit = !"false".equalsIgnoreCase(context.getInitParameter("track-visit"));

hostHeadersAllowed = UtilMisc.getHostHeadersAllowed();

}

public static ControllerConfig getControllerConfig(WebappInfo webAppInfo) throws WebAppConfigurationException, MalformedURLException {
Assert.notNull("webAppInfo", webAppInfo);
String filePath = webAppInfo.getLocation().concat(controllerXmlFileName);
File configFile = new File(filePath);
return getControllerConfig(configFile.toURI().toURL());
}

public static ControllerConfig getControllerConfig(URL url) throws WebAppConfigurationException {
ControllerConfig controllerConfig = controllerCache.get(url);
if (controllerConfig == null) {
controllerConfig = controllerCache.putIfAbsentAndGet(url, new ControllerConfig(url));
}
return controllerConfig;
}

image

image接下来我们继续看org.apache.ofbiz.webapp.control.RequestHandler#doRequest,首先根据请求路径获取对应处理的RequestMapimage

image

接着首先是一些预处理,感兴趣的可以自己看看

image

继续往下,之后在正式处理前会走到我们熟悉的登录校验由于第一部分已经简单做了分析,这里就不再重复

image

之后根据返回结果选择对应的response,上面也提到过requestMap与uri有关,同样response这部分与uri以及type有关

1
2
3
4
5
<request-map uri="ProgramExport">
<security https="true" auth="true"/>
<response name="success" type="view" value="ProgramExport"/>
<response name="error" type="view" value="ProgramExport"/>
</request-map>

image

接下来可以看到这里根据nextRequestResponse.type的种类执行,和我们请求的路径在xml中对应的配置有关,在这里由于我们是view因此走入else执行后置处理器

image

最终执行视图渲染的处理,之后的处理感兴趣就自己跟跟

image

而我们后台漏洞的利用点ProgramExport,对应视图如下

1
<view-map name="ProgramExport" type="screen" page="component://webtools/widget/EntityScreens.xml#ProgramExport"/>

因此也不难理解为什么通过路由最终能调用ProgramExport.groovy的处理了

image

利用时值得注意的点

在直接利用时你会发现在某些版本下无法打成功,其实是因为这里做了一些简单的检查

image

这里有一些禁止使用的token

image

可以看到这个配置来源于配置文件

image

image

看到拦截的内容简直抽象,不知道从哪里抄来的…不多吐槽,绕过也很简单,黑名单里的限制并不多很容易通过代码层面bypass,当然也可以用unicode编码更直白

image

Ps:当然还有另一个CVE是关于SSRF以及任意配置读取的利用点也可以自己翻翻后台功能,这里不多做分析了

参考链接

Apache OFBiz漏洞 CVE-2023-49070 的前世今生