对影响VirtualBox和FreeBSD的Libalias越界访问漏洞的分析
2020-08-24 12:00:48 Author: www.4hou.com(查看原文) 阅读量:325 收藏

2020年2月,我们收到了一份提交文件,详细介绍了Oracle VirtualBox中的一个漏洞,该漏洞可能导致libalias数据包别名库中的越界访问。研究人员Vishnu Dev TJ向我们报告了此问题,并在打补丁时最终将其分配编号为CVE-2020-7454。在分析提交内容时,我发现该漏洞也存在于FreeBSD中。这篇文章分析了CVE-2020-7454在VirtualBox和FreeBSD上的影响,并说明为什么维护第三方或共享代码是一项艰巨的任务。

对于不熟悉的人,libalias是一个用于对IP数据包进行别名和去别名的库。它还用于网络地址转换(NAT)。凭借其NAT功能,可以理解为什么VirtualBox会将其用于各种功能。但是,libalias源自FreeBSD。VirtualBox维护它自己的库分支。不幸的是,此漏洞在各个版本之间都存在。它导致FreeBSD内核和用户模式下的出界(OOB)访问。该漏洞已在VirtualBox 6.1.6和FreeBSD-SA-20:12中修复。

0x01 Oracle VirtualBox

以下分析基于VirtualBox 6.1.4。该漏洞的根本原因在于AliasHandleUdpNbtNS()函数,该函数负责解析UDP端口137上的NetBIOS名称服务数据包。下面以简化形式显示了相关部分。

AliasHandleUdpNbtNS(...) 
    { 
        /* ... snip ... */

        /* Calculate data length of UDP packet */ 
        uh = (struct udphdr *)ip_next(pip); 
        nsh = (NbtNSHeader *)udp_next(uh); 
        p = (u_char *) (nsh + 1); 
        pmax = (char *)uh + ntohs(uh->uh_ulen); /* ancount) != 0) { 
            p = AliasHandleResource( 
                ntohs(nsh->ancount), 
                (NBTNsResource *) p, 
                pmax, 
                &nbtarg 
                ); 
        } 
        /* ... snip ... */
    } 
AliasHandleResource(..., char *pmax, ...) 
    { 
        /* ... snip ... */
            switch (ntohs(q->type)) { 
            case RR_TYPE_NB: 
                q = (NBTNsResource *) AliasHandleResourceNB( 
                    q, 
                    pmax, 
                    nbtarg 
                    ); 
                break; 
        /* ... snip ... */ 
    }

上面的代码片段中的(1)uh_ulen是UDP头长度字段,该字段是从不受信任的guest OS发送的。可能的最大值是0xFFFF。通过使用较大的uh_ulen值,攻击者可以生成过大的pmax 值.。接下来,如果UDP数据包包含应答记录,并且其类型指定为NetBIOS General Service,则执行将到达AliasHandleResourceNB()函数

AliasHandleResourceNB(..., char *pmax, ...) 
{ 
    /* ... snip ... */
    while (nb != NULL && bcount != 0) { 
        if ((char *)(nb + 1) > pmax) { /* oldaddr, &nb->addr, sizeof(struct in_addr))) { /* addr = nbtarg->newaddr; /* <--- (4) */
        } 
        /* ... snip ... */
        nb = (NBTNsRNB *) ((u_char *) nb + SizeOfNsRNB); 
    } 
}

在上面的代码片段的(2)处,while循环尝试在数据包中查找旧地址,并将其替换为新地址,直到pmax。由于pmax该值较大,因此将在(3)处发生越界读取。此外,如果找到旧地址,它也可能在(4)处写OOB。

guest OS上的攻击者可以构造无效的UDP标头长度来触发主机OS上的OOB访问。UDP端口137在VirtualBox的默认配置中处于打开状态。为了解决此漏洞,Oracle 在上面的代码片段1中添加了对(1)所示UDP标头长度的验证。

0x02 FreeBSD 12.1

如上所述,libalias库源自FreeBSD。在分析Oracle VirtualBox中的提交时,我发现此漏洞在ipfw用于NAT 时也会影响FreeBSD 。所述ipfw分组过滤器包含完成NAT的两种不同的方法:一个在内核空间和一个在用户空间。两种实现都使用libalias提供的相同函数。这意味着可以natd根据NAT配置在内核或用户态程序()中触发该漏洞。

这是触发内核中的漏洞所需的FreeBSD 12.1 Release的相关配置:

/boot/loader.conf 
 alias_nbt_load="YES" 
/etc/rc.conf 
 gateway_enable="YES" 
 firewall_enable="YES" 
 firewall_nat_enable="YES" 
 firewall_nat_interface="em0" 
 firewall_type="OPEN"

OOB访问发生在中alias_nbt.ko,这是已加载的内核模块。

如果NAT配置基于用户域,则OOB访问libalias_nbt.so将在natd进程的上下文中发生。两种情况都可以在不进行身份验证的情况下远程触发。

在分析过程中,我发现了另一个惊喜。FreeBSD中的libalias库包含CuSeeMe协议处理中同一漏洞的另一个变体,该协议默认情况下侦听UDP端口7648。

AliasHandleCUSeeMeIn(...) 
{ 
    /* ... snip ... */
    end = (char *)ud + ntohs(ud->uh_ulen); /* <--- untrusted UDP header length */
    if ((char *)oc data_type) == 101) 
        /* Find and change our address */ 
        for (i = 0; (char *)(ci + 1) <= end && i < oc->client_count; i++, ci++) 
        if (ci->address == (u_int32_t) alias_addr.s_addr) { /* address = (u_int32_t) original_addr.s_addr; /* <--- OOBW */
            break; 
        } 
    } 
}

但是,该漏洞在VirtualBox中不存在,这意味着FreeBSD 的补丁与VirtualBox的补丁不同。在UdpAliasIn()和UdpAliasOut()函数中都添加了一个验证,这是处理UDP数据包的适当级别。它可以有效地修补任何包含此类漏洞的协议。

0x03 分析总结

此研究表明,维护第三方或共享代码是一项艰巨的任务。即使对源代码进行了修补或更新,也必须对上游产品进行这些更改。甚至当你是在与第三方同步,共享代码漏洞具有双倍的影响,因为它影响其他的产品,Oracle VirtualBox在用户和安全研究人员中越来越受欢迎。

本文翻译自:https://www.zerodayinitiative.com/blog/2020/6/29/cve-2020-7454-killing-two-systems-with-one-bug-in-libalias如若转载,请注明原文地址:


文章来源: https://www.4hou.com/posts/53EK
如有侵权请联系:admin#unsafe.sh