CVE-2022-22954

代码分析

http://file.xipudata.com/?dir=/2_software/Vmware/Horizon8 下载好ova,使用vmware安装搭建,导入时添加下域名。 根据官方提供的临时修复脚本可以知道漏洞存在于 /opt/vmware/horizon/workspace/webapps/catalog-portal/WEB-INF/lib/endusercatalog-ui-1.0-SNAPSHOT-classes.jar 修复脚本中还提到了这个文件 查看该文件后发现存在eval,这是java freemarker的写法,用来把字符串当作ftl代码,所以我们只需要控制errorObj即可实现代码执行 所以我们知道漏洞来源于customError,我们需要找到可以到达customError的路由,并且可以控制errorObj 在UiErrorController.class中可以找到handleGenericError,可以传递errorObj,最后return到customError

    private String handleGenericError(final HttpServletRequest request, final HttpServletResponse response, final Map<String, Object> model, final boolean isAWJade, final boolean garnetAndAbove, final String excpClass, final int errorCode, final String errorMessage) {
        final String localizedMessageHeader = this.messages.getLocalizedErrorMessage("errorPage.errorHeading", request.getLocale(), (Object[])null);
        final String localizedMessage = this.messages.getLocalizedErrorMessage(this.getLocalizedMessageKey(excpClass), request.getLocale(), (Object[])null);
        if (errorCode != -1) {
            response.setStatus(errorCode);
        }
        model.put("errorObj", errorMessage);
        model.put("messageHeader", localizedMessageHeader);
        model.put("genericErrorMsg", localizedMessage);
        model.put("contextPath", request.getContextPath());
        if (isAWJade) {
            WebUtils.markCookiesForDeletion(request, response, new String[] { "USER_CATALOG_CONTEXT" });
            WebUtils.markCookiesForDeletionWithPath(request, response, "/catalog-portal", new String[] { "EUC_XSRF_TOKEN" });
            model.put("logoutPath", retrieveServerInitiatedLogoutPath(garnetAndAbove).getName());
        }
        else {
            final StringBuilder logoutUrl = new StringBuilder(request.getContextPath()).append("/ui").append("/logout");
            String queryStr = request.getQueryString();
            if (StringUtils.isNotBlank((CharSequence)queryStr)) {
                queryStr = UrlUtils.encodeQuery(UrlUtils.decode(queryStr));
                logoutUrl.append('?').append(queryStr);
            }
            model.put("logoutPath", logoutUrl.toString());
        }
        return "customError";
    }

所以我们继续往上找到getErrorPagehandleUnauthorizedError,调用了handleGenericError