freeBuf
主站

分类

云安全 AI安全 开发安全 终端安全 数据安全 Web安全 基础安全 企业安全 关基安全 移动安全 系统安全 其他安全

特色

热点 工具 漏洞 人物志 活动 安全招聘 攻防演练 政策法规

点我创作

试试在FreeBuf发布您的第一篇文章 让安全圈留下您的足迹
我知道了

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

漏洞分析 | Ignite Realtime Openfire路径遍历漏洞(CVE-2023-32315)
网宿安全演武实验室 2023-08-25 15:35:43 366920

漏洞概述

Ignite Realtime Openfire是Ignite Realtime社区的一款采用Java开发且基于XMPP(前称Jabber,即时通讯协议)的跨平台开源实时协作(RTC)服务器,它能够构建高效率的即时通信服务器,并支持上万并发用户数量。

近期,Openfire被曝存在认证绕过漏洞,未经身份认证的远程攻击者可以构造恶意请求访问受限界面,最终上传恶意文件实现远程代码执行。


受影响版本

受影响版本:3.10.0 <= Openfire < 4.6.8,4.7.0 <= Openfire < 4.7.5


漏洞分析

问题关键在于Openfire内置的Jetty Web服务器支持对%u002e这类非标准unicode uri的解析,导致之前的路径穿越漏洞(CVE-2008-6508)再次出现。


这里我们采用打补丁前的最新版本(4.7.4)进行分析,具体链接如下:
https://codeload.github.com/igniterealtime/Openfire/zip/refs/tags/v4.7.4


先从xmppserver/src/main/webapp/WEB-INF/web.xml开始分析,这段配置定义了一个AuthCheck filter,用于排除对部分url的权限检查,包括登录/注销页面、系统设置及其子页面、静态资源文件等:

<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>

接着查看filter,xmppserver/src/main/java/org/jivesoftware/admin/AuthCheckFilter.java

这里的excludes就是AuthCheck filter配置的部分,然后就去调用testURLPassesExclude(),若返回true,则break,也就说明请求路径无需鉴权。

public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
        throws IOException, ServletException
{
    ...
    // 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 (!doExclude) {
        WebManager manager = new WebManager();
        manager.init(request, response, request.getSession(), context);
        boolean haveOneTimeToken = manager.getAuthToken() instanceof AuthToken.OneTimeAuthToken;
        User loggedUser = manager.getUser();
        boolean loggedAdmin = loggedUser == null ? false : adminManager.isUserAdmin(loggedUser.getUsername(), true);
        if (!haveOneTimeToken && !loggedAdmin && !authUserFromRequest(request)) {
            response.sendRedirect(getRedirectURL(request, loginPage, null));
            return;
        }
    }
    chain.doFilter(req, res);
}

显然,testURLPassesExclude()起到了关键作用。

public static boolean testURLPassesExclude(String url, String exclude) {
    ......
    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;
            }
        }
    }
    ......
}

可以先尝试历史payload理清代码逻辑:
payload1:/setup/setup-/../../log.js
payload2:/setup/setup-/%2e%2e/%2e%2e/log.jsp


因为匹配到excludes存在的setup/setup-*,进入url检测,这里已经对”..”以及”%2e”进行了过滤,所以普通的路径遍历特征都会被拦截,但新版本中的Jetty Web服务器支持对%u002e这类非标准unicode uri的解析,也就又给攻击者提供了一种利用方式。


还是以4.7.4为例,我们来分析一下其解码逻辑:

<jetty.version>9.4.43.v20210629</jetty.version>


首先看org.eclipse.jetty.http.HttpURI#parse() ,这是Jetty中用于解析HTTP请求URI的方法。它的作用是将HTTP请求URI字符串解析为一个包含多个属性的Java对象,以便Jetty可以根据这些属性来处理HTTP请求,我们需要关注的是URI的路径部分是如何处理的:

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");
}

这里给出了两个判断条件,第一,如果URI的路径部分既没有进行编码,也没有包含点或双点符号,则说明路径是正确的,可以直接使用;第二,如果URI的路径部分不为空,则需要对它进行解码和规范化操作,着重关注第二个条件,代码先使用了URIUtil.decodePath()方法对_path进行解码,得到解码后的路径字符串。然后,又使用URIUtil.canonicalPath()方法对解码后的路径字符串进行规范化,得到规范化后的路径字符串。最后,如果规范化后的路径字符串为null,则抛出IllegalArgumentException异常。


跟进org.eclipse.jetty.util.URIUtil#decodePath(),进一步分析%uxxxx的解码流程:

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;
        ......
    }
}

主要的解码逻辑写在了for循环里,它会遍历整个路径字符串,并对编码字符进行解码。其中,builder用于存储解码后的路径字符串,如果遇到%,会检查builder是否为null,如果是的话,就说明还没有解码过任何字符,需要先将%前面的字符拷贝到builder中,这样做的目的是保证解码后的uri路径完整。然后,再根据后面的字符决定unicode/ascii解码,得到解码后的路径字符串,最后由org.eclipse.jetty.util.URIUtil#canonicalPath()进行规范处理。


以绕过的payload为例,处理流程如下:

/setup/setup-/%u002e%u002e/%u002e%u002e/log.jsp

-> /setup/setup-/../../log.jsp

-> /log.jsp


此外,CVE-2021-34429的绕过逻辑也与之类似

https://github.com/eclipse/jetty.project/security/advisories/GHSA-vjv5-gp2w-65vm


漏洞复现

通过以上分析,攻击者仅需向受害站点发送满足漏洞触发条件的unicode uri再拼接Openfire管理后台敏感路径,即可进行权限绕过。

最常见的利用方式当然是新建账户进而接管后台:

接着修改开源插件,https://github.com/igniterealtime/openfire-fastpath-plugin

添加恶意代码并打包为jar后上传,即可实现getshell。


# 网络安全 # web安全 # 漏洞分析
本文为 网宿安全演武实验室 独立观点,未经授权禁止转载。
如需授权、对文章有疑问或需删除稿件,请联系 FreeBuf 客服小蜜蜂(微信:freebee1024)
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
网宿安全演武实验室 LV.5
网宿科技-网宿安全演武实验室官方账号
  • 41 文章数
  • 80 关注者
大模型安全警报:你的AI客服正在泄露客户银行卡号
2025-03-27
信息安全风险管理简述(下):如何进行风险评估
2025-03-11
信息安全风险管理简述(上)
2025-03-11
文章目录