VirtualBox NAT DHCP / BOOTP服务器漏洞
字数 1354 2025-08-27 12:33:37

VirtualBox NAT DHCP/BOOTP服务器漏洞分析

漏洞概述

本文详细分析VirtualBox NAT网络模式中DHCP/BOOTP服务器存在的两个高危漏洞:CVE-2016-5610(堆溢出漏洞)和CVE-2016-5611(越界读取漏洞)。这两个漏洞存在于VirtualBox 5.0.28和5.1.8之前的版本中,可导致虚拟机逃逸攻击。

0x001 技术背景

VirtualBox在NAT模式下会为每个虚拟机启用一个DHCP服务器,该服务器为guest虚拟机分配IP地址。默认配置下:

  • Guest虚拟机IP地址范围:10.0.2.15
  • 伪造的DHCP服务器IP:10.0.2.2
  • DHCP服务器监听UDP端口68
# Guest虚拟机中查看网络配置
renorobert@ubuntuguest:~$ ifconfig enp0s3
enp0s3    Link encap:Ethernet  HWaddr 08:00:27:b8:b7:4c  
          inet addr:10.0.2.15  Bcast:10.0.2.255  Mask:255.255.255.0
          inet6 addr: fe80::a00:27ff:feb8:b74c/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:119 errors:0 dropped:0 overruns:0 frame:0
          TX packets:94 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:11737 (11.7 KB)  TX bytes:12157 (12.1 KB)

0x002 漏洞分析

1. DHCP数据包结构

漏洞存在于src/Vbox/Devices/Network/slirp/bootp.c文件中,DHCP数据包定义如下:

#define DHCP_OPT_LEN            312

/* RFC 2131 */
struct bootp_t {
    struct ip      ip;                          /**< header: IP header */
    struct udphdr  udp;                         /**< header: UDP header */
    uint8_t        bp_op;                       /**< opcode (BOOTP_REQUEST, BOOTP_REPLY) */
    uint8_t        bp_htype;                    /**< hardware type */
    uint8_t        bp_hlen;                     /**< hardware address length */
    uint8_t        bp_hops;                     /**< hop count */
    uint32_t       bp_xid;                      /**< transaction ID */
    uint16_t       bp_secs;                     /**< numnber of seconds */
    uint16_t       bp_flags;                    /**< flags (DHCP_FLAGS_B) */
    struct in_addr bp_ciaddr;                   /**< client IP address */
    struct in_addr bp_yiaddr;                   /**< your IP address */
    struct in_addr bp_siaddr;                   /**< server IP address */
    struct in_addr bp_giaddr;                   /**< gateway IP address */
    uint8_t        bp_hwaddr[16];               /** client hardware address */
    uint8_t        bp_sname[64];                /** server host name */
    uint8_t        bp_file[128];                /** boot filename */
    uint8_t        bp_vend[DHCP_OPT_LEN];       /**< vendor specific info */
};

2. BOOTP客户端管理

DHCP服务器维护一个BOOTPClient结构数组来跟踪所有分配的IP地址:

/** Entry in the table of known DHCP clients. */
typedef struct {
    uint32_t xid;
    bool allocated;
    uint8_t macaddr[6];
    struct in_addr addr;
    int number;
} BOOTPClient;

/** Number of DHCP clients supported by NAT. */
#define NB_ADDR     16

int bootp_dhcp_init(PNATState pData) {
    pData->pbootp_clients = RTMemAllocZ(sizeof(BOOTPClient) * NB_ADDR);
    if (!pData->pbootp_clients)
        return VERR_NO_MEMORY;
    return VINF_SUCCESS;
}

0x003 CVE-2016-5611 - 越界读取漏洞

漏洞位置

dhcp_find_option()函数中存在越界读取漏洞:

static uint8_t *dhcp_find_option(uint8_t *vend, uint8_t tag) {
    uint8_t *q = vend;
    uint8_t len;
    while(*q != RFC1533_END) {          // expects END tag in an untrusted input
        if (*q == RFC1533_PAD) {
            q++;   // incremented without validation 
            continue;
        }
        if (*q == tag)
            return q;   // returns pointer if tag found
        q++;
        len = *q;    
        q += 1 + len;   // length and pointer not validated
    }
    return NULL;
}

漏洞利用

  1. 攻击者发送特制的DHCPDECLINE数据包,其中bp_vend字段填充RFC1533_PAD
  2. 服务器调用dhcp_find_option()寻找RFC2132_REQ_ADDR选项
  3. 由于缺少边界检查,函数可能返回指向DHCP缓冲区外的指针
  4. 服务器将外部数据当作IP地址处理,导致信息泄露
static void dhcp_decode(PNATState pData, struct bootp_t *bp, const uint8_t *buf, int size) {
    case DHCPDECLINE:
        pu8RawDhcpObject = dhcp_find_option(&bp->bp_vend[0], RFC2132_REQ_ADDR);
        req_ip.s_addr = *(uint32_t *)(pu8RawDhcpObject + 2);
        rc = bootp_cache_lookup_ether_by_ip(pData, req_ip.s_addr, NULL);
        if (RT_FAILURE(rc)) {
            bc->addr.s_addr = req_ip.s_addr;
            slirp_arp_who_has(pData, bc->addr.s_addr);
            LogRel(("NAT: %RTnaipv4 has been already registered\n", req_ip));
        }
        break;
}

泄露效果

通过伪造的ARP请求泄露主机内存数据:

renorobert@guest:~$ sudo tcpdump -vv -i eth0 arp
15:51:34.557995 ARP, Ethernet (len 6), IPv4 (len 4), Request who-has 45.103.99.109 (Broadcast) tell 10.0.2.2, length 46

0x004 CVE-2016-5610 - 堆溢出漏洞

漏洞位置

dhcp_decode_request()函数中缺少对bp_hlen字段的验证:

static int dhcp_decode_request(PNATState pData, struct bootp_t *bp, struct mbuf *m) {
    switch (dhcp_stat) {
        case RENEWING:
            Assert((bp->bp_hlen == ETH_ALEN));
            memcpy(bc->macaddr, bp->bp_hwaddr, bp->bp_hlen);
            bc->addr.s_addr = bp->bp_ciaddr.s_addr;
            break;

        case INIT_REBOOT:
            Assert((bp->bp_hlen == ETH_ALEN));
            memcpy(bc->macaddr, bp->bp_hwaddr, bp->bp_hlen);
            bc->addr.s_addr = ui32;
            break;
    }
}

漏洞利用

  1. bp_hlen是1字节字段,最大可设置为255
  2. 断言语句Assert在release版本中不编译
  3. 攻击者可发送特制的DHCPREQUEST数据包,控制bp_hlenbp_hwaddr
  4. 当复制bp_hwaddrBOOTPClient结构的macaddr字段时,导致堆缓冲区溢出

利用步骤

  1. 发送14个合法的DHCPREQUEST数据包填充pbootp_clients数组
  2. 发送第15个特制的DHCPREQUEST数据包,设置bp_hlen为较大值触发溢出
  3. 溢出会覆盖相邻的uma_zone结构,控制函数指针
struct uma_zone {
    uint32_t magic;
    PNATState pData;
    RTCRITSECT csZone;
    const char *name;
    size_t size;
    ctor_t pfCtor;    // 可被覆盖的函数指针
    dtor_t pfDtor;    // 可被覆盖的函数指针
    zinit_t pfInit;   // 可被覆盖的函数指针
    zfini_t pfFini;   // 可被覆盖的函数指针
    uma_alloc_t pfAlloc; // 可被覆盖的函数指针
    uma_free_t pfFree;   // 可被覆盖的函数指针
    // ... 其他字段
};

崩溃现场

Thread 11 "EMT" received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7fd20e4af700 (LWP 27148)]
0x00007fd1df22308e in ?? () from /usr/lib/virtualbox/VBoxDD.so
=> 0x7fd1df22308e: call   QWORD PTR [rbx+0x70]

0x005 漏洞修复

Oracle在2016年10月的重要补丁更新中修复了这两个漏洞:

  1. dhcp_find_option()中添加边界检查
  2. dhcp_decode_request()中严格验证bp_hlen字段

0x006 总结

这两个漏洞展示了VirtualBox NAT网络实现中的严重安全问题:

  1. CVE-2016-5611:由于缺乏输入验证导致的越界读取,可泄露主机内存信息
  2. CVE-2016-5610:堆溢出漏洞结合特定内存布局可实现代码执行

建议用户升级到VirtualBox 5.0.28或5.1.8及以上版本以修复这些漏洞。

VirtualBox NAT DHCP/BOOTP服务器漏洞分析 漏洞概述 本文详细分析VirtualBox NAT网络模式中DHCP/BOOTP服务器存在的两个高危漏洞:CVE-2016-5610(堆溢出漏洞)和CVE-2016-5611(越界读取漏洞)。这两个漏洞存在于VirtualBox 5.0.28和5.1.8之前的版本中,可导致虚拟机逃逸攻击。 0x001 技术背景 VirtualBox在NAT模式下会为每个虚拟机启用一个DHCP服务器,该服务器为guest虚拟机分配IP地址。默认配置下: Guest虚拟机IP地址范围:10.0.2.15 伪造的DHCP服务器IP:10.0.2.2 DHCP服务器监听UDP端口68 0x002 漏洞分析 1. DHCP数据包结构 漏洞存在于 src/Vbox/Devices/Network/slirp/bootp.c 文件中,DHCP数据包定义如下: 2. BOOTP客户端管理 DHCP服务器维护一个 BOOTPClient 结构数组来跟踪所有分配的IP地址: 0x003 CVE-2016-5611 - 越界读取漏洞 漏洞位置 dhcp_find_option() 函数中存在越界读取漏洞: 漏洞利用 攻击者发送特制的 DHCPDECLINE 数据包,其中 bp_vend 字段填充 RFC1533_PAD 服务器调用 dhcp_find_option() 寻找 RFC2132_REQ_ADDR 选项 由于缺少边界检查,函数可能返回指向DHCP缓冲区外的指针 服务器将外部数据当作IP地址处理,导致信息泄露 泄露效果 通过伪造的ARP请求泄露主机内存数据: 0x004 CVE-2016-5610 - 堆溢出漏洞 漏洞位置 dhcp_decode_request() 函数中缺少对 bp_hlen 字段的验证: 漏洞利用 bp_hlen 是1字节字段,最大可设置为255 断言语句 Assert 在release版本中不编译 攻击者可发送特制的 DHCPREQUEST 数据包,控制 bp_hlen 和 bp_hwaddr 当复制 bp_hwaddr 到 BOOTPClient 结构的 macaddr 字段时,导致堆缓冲区溢出 利用步骤 发送14个合法的 DHCPREQUEST 数据包填充 pbootp_clients 数组 发送第15个特制的 DHCPREQUEST 数据包,设置 bp_hlen 为较大值触发溢出 溢出会覆盖相邻的 uma_zone 结构,控制函数指针 崩溃现场 0x005 漏洞修复 Oracle在2016年10月的重要补丁更新中修复了这两个漏洞: 在 dhcp_find_option() 中添加边界检查 在 dhcp_decode_request() 中严格验证 bp_hlen 字段 0x006 总结 这两个漏洞展示了VirtualBox NAT网络实现中的严重安全问题: CVE-2016-5611 :由于缺乏输入验证导致的越界读取,可泄露主机内存信息 CVE-2016-5610 :堆溢出漏洞结合特定内存布局可实现代码执行 建议用户升级到VirtualBox 5.0.28或5.1.8及以上版本以修复这些漏洞。