openfire是一个即时通讯服务器,也称之为即时通讯平台。它是基于XMPP协议的,大家所熟悉的通讯软件QQ、MSN和Gtalk等等,其中Gtalk就是基于XMPP协议的实现。
在即时通讯中往往因为需要保存一些状态或者数据所以不能采用点对点通讯,而是需要搭建服务器来转发。来源:`https://blog.csdn.net/qin34/article/details/41316231`
通俗的讲openfire是一个即时通讯服务器,也叫即时通讯平台
3.10.0 <= Openfire < 4.6.8
4.7.0 <= Openfire < 4.7.5
这个漏洞的原理有点像多年前出现的CVE-2008-6508目录穿越漏洞
在设置为maven项目之后,先从源头配置找起
<filter> <filter-name>AuthCheck</filter-name> <filter-class>org.jivesoftware.admin.AuthCheckFilter</filter-class> <init-param> <param-name>excludes</param-name> <param-value> login.jsp,index.jsp?logout=true,setup/index.jsp,setup/setup-*,.gif,.png,error-serverdown.jsp,loginToken.jsp </param-value> </init-param> </filter>
该处定义了一个名为AuthCheck
的filter
,用于对部分url免除鉴权
然后全局搜索AuthCheckFilter
去寻找定义文件
定位代码
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest)req; HttpServletResponse response = (HttpServletResponse)res; // Do not allow framing; OF-997 response.setHeader("X-Frame-Options", JiveGlobals.getProperty("adminConsole.frame-options", "SAMEORIGIN")); // Reset the defaultLoginPage variable String loginPage = defaultLoginPage; if (loginPage == null) { loginPage = request.getContextPath() + (AuthFactory.isOneTimeAccessTokenEnabled() ? "/loginToken.jsp" : "/login.jsp" ); } // Get the page we're on: String url = request.getRequestURI().substring(1); if (url.startsWith("plugins/")) { url = url.substring("plugins/".length()); } // See if it's contained in the exclude list. If so, skip filter execution boolean doExclude = false; for (String exclude : excludes) { if (testURLPassesExclude(url, exclude)) { doExclude = true; break; } }
定义代码里面可以看出
if (testURLPassesExclude(url, exclude)) { doExclude = true; break; }
当doExclude = true
则无需鉴权
继续跟进testURLPassesExclude
方法
public static boolean testURLPassesExclude(String url, String exclude) { // If the exclude rule includes a "?" character, the url must exactly match the exclude rule. // If the exclude rule does not contain the "?" character, we chop off everything starting at the first "?" // in the URL and then the resulting url must exactly match the exclude rule. If the exclude ends with a "*" // character then the URL is allowed if it exactly matches everything before the * and there are no ".." // characters after the "*". All data in the URL before if (exclude.endsWith("*")) { if (url.startsWith(exclude.substring(0, exclude.length()-1))) { // Now make sure that there are no ".." characters in the rest of the URL. if (!url.contains("..") && !url.toLowerCase().contains("%2e")) { return true; } } } else if (exclude.contains("?")) { if (url.equals(exclude)) { return true; } } else { int paramIndex = url.indexOf("?"); if (paramIndex != -1) { url = url.substring(0, paramIndex); } if (url.equals(exclude)) { return true; } } return false; }
代码中 if (!url.contains("..") && !url.toLowerCase().contains("%2e")) {
可以发现对部分字符做了过滤
但是其内置的web服务器支持对%u002e
非标准unicode编码的解析
具体代码如下所示
if (!encodedPath && !dot) { if (_param == null) _decodedPath = _path; else _decodedPath = _path.substring(0, _path.length() - _param.length() - 1); } else if (_path != null) { // The RFC requires this to be canonical before decoding, but this can leave dot segments and dot dot segments // which are not canonicalized and could be used in an attempt to bypass security checks. String decodedNonCanonical = URIUtil.decodePath(_path); _decodedPath = URIUtil.canonicalPath(decodedNonCanonical); if (_decodedPath == null) throw new IllegalArgumentException("Bad URI"); } for (int i = offset; i < end; i++) { char c = path.charAt(i); switch (c) { case '%': if (builder == null) { builder = new Utf8StringBuilder(path.length()); builder.append(path, offset, i - offset); } if ((i + 2) < end) { char u = path.charAt(i + 1); if (u == 'u') { // 解码%uxxxx形式的Unicode字符 builder.append((char)(0xffff & TypeUtil.parseInt(path, i + 2, 4, 16))); i += 5; } else { // 解码%xx形式的ASCII字符 builder.append((byte)(0xff & (TypeUtil.convertHexDigit(u) * 16 + TypeUtil.convertHexDigit(path.charAt(i + 2))))); i += 2; } } else { throw new IllegalArgumentException("Bad URI % encoding"); } break;
首先利用docker拉取漏洞版本镜像
然后开启漏洞环境
然后确定一下
部署完毕
cd CVE-2023-32315-Openfire-Bypass/scan_all
go run main.go -u http://openfire.com:9090
然后就直接出来了,操作不难