CVE:CVE-2007-5365
CNNVD:CNNVD-200710-201
OpenBSD是一款开放源代码Unix类操作系统。
OpenBSD系统的DHCP协议实现上存在缓冲区溢出漏洞，远程攻击者可能利用此漏洞控制服务器。
OpenBSD的options.c文件中的cons_options()函数没有正确地处理DHCP请求。如果远程攻击者所发送的DHCP请求中指定最大消息大小小于最小IP MTU(278)的话，就会在OpenBSD中导致dhcpd(8)覆盖栈缓冲区，执行任意指令。
漏洞存在于负责处理从客户端所接收到的DHCP选项的函数中。在src/usr.sbin/dhcpd/options.c文件中：
 int
 cons_options(struct packet *inpacket, struct dhcp_packet *outpacket,
     int mms, struct tree_cache **options,
     int overload, /* Overload flags that may be set. */
     int terminate, int bootpp, u_int8_t *prl, int prl_len)
 {
         unsigned char priority_list[300];
         int priority_len;
         unsigned char buffer[4096];        /* Really big buffer... */
         int main_buffer_size;
         int mainbufix, bufix;
         int option_size;
         int length;
dhcp.h中定义了DHCP_FIXED_LEN：
         if (!mms &&
             inpacket &&
             inpacket->options[DHO_DHCP_MAX_MESSAGE_SIZE].data &&
             (inpacket->options[DHO_DHCP_MAX_MESSAGE_SIZE].len >=
             sizeof(u_int16_t)))
                 mms = getUShort(
                     inpacket->options[DHO_DHCP_MAX_MESSAGE_SIZE].data);
         if (mms)
                 main_buffer_size = mms - DHCP_FIXED_LEN;
         else if (bootpp)
                 main_buffer_size = 64;
         else
                 main_buffer_size = 576 - DHCP_FIXED_LEN;
         if (main_buffer_size > sizeof(buffer))
                 main_buffer_size = sizeof(buffer);
main_buffer_size是有符型，可被攻击者控制。只要main_buffer_size是比较小的正整数(<= 4096)，执行流就会正常进行：
        /* Copy the options into the big buffer... */
         option_size = store_options(
             buffer,
             (main_buffer_size - 7 + ((overload & 1) ? DHCP_FILE_LEN : 0)+
                 ((overload & 2) ? DHCP_SNAME_LEN : 0)),
             options, priority_list, priority_len, main_buffer_size,
             (main_buffer_size + ((overload & 1) ? DHCP_FILE_LEN : 0)),
             terminate);
         /* Put the cookie up front... */
         memcpy(outpacket->options, DHCP_OPTIONS_COOKIE, 4);
         mainbufix = 4;
这里如果main_buffer_size为比较小的正值的话(<= 7)，就会导致store_options迅速退出，执行流会继续。具体来讲，只要客户端报文中的Maximum Segment Size值(mms)满足(DHCP_FIXED_LEN < mms < DHCP_FIXED_LEN+4)这个条件，main_buffer_size就会为小于4的正数。
         if (option_size <= main_buffer_size - mainbufix) {
                 memcpy(&outpacket->options[mainbufix],
                     buffer, option_size);
                 mainbufix += option_size;
                 if (mainbufix < main_buffer_size)
                         outpacket->options[mainbufix++] = DHO_END;
                 length = DHCP_FIXED_NON_UDP + mainbufix;
         } else {
                 outpacket->options[mainbufix++] = DHO_DHCP_OPTION_OVERLOAD;
                 outpacket->options[mainbufix++] = 1;
                 if (option_size >
                     main_buffer_size - mainbufix + DHCP_FILE_LEN)
                         outpacket->options[mainbufix++] = 3;
                 else
                         outpacket->options[mainbufix++] = 1;
                 memcpy(&outpacket->options[mainbufix],
                     buffer, main_buffer_size - mainbufix);
用负数的第三个参数触发memcpy(3)调用就会导致覆盖大部分的进程内存。
solution:Upgrade debian debian_linux to a higher version than 3.1,4.0,and avoid the version 3.1,4.0; Upgrade openbsd openbsd to a higher version than 4.0,4.1,4.2,and avoid the version 4.0,4.1,4.2; Upgrade redhat enterprise_linux to a higher version than 2.1,and avoid the version 2.1; Upgrade redhat linux_advanced_workstation to a higher version than 2.1,and avoid the version 2.1; Upgrade sun opensolaris to a higher version than snv_01,snv_02,snv_03,snv_04,snv_05,snv_06,snv_07,snv_08,snv_09,snv_10,snv_11,snv_12,snv_13,snv_14,snv_15,snv_16,snv_17,snv_18,snv_19,snv_20,snv_21,snv_22,snv_23,snv_24,snv_25,snv_26,snv_27,snv_28,snv_29,snv_30,snv_31,snv_32,snv_33,snv_34,snv_35,snv_36,snv_37,snv_38,snv_39,snv_40,snv_41,snv_42,snv_43,snv_44,snv_45,snv_46,snv_47,snv_48,snv_49,snv_50,snv_51,snv_52,snv_53,snv_54,snv_55,snv_56,snv_57,snv_58,snv_59,snv_60,snv_61,snv_62,snv_63,snv_64,snv_65,snv_66,snv_67,snv_68,snv_69,snv_70,snv_71,snv_72,snv_73,snv_74,snv_75,snv_76,snv_77,snv_78,snv_79,snv_80,snv_81,snv_82,snv_83,snv_84,snv_85,snv_86,snv_87,snv_88,snv_89,snv_90,snv_91,snv_92,snv_93,snv_94,snv_95,snv_96,snv_97,snv_98,snv_99,snv_100,snv_101,snv_102,and avoid the version snv_01,snv_02,snv_03,snv_04,snv_05,snv_06,snv_07,snv_08,snv_09,snv_10,snv_11,snv_12,snv_13,snv_14,snv_15,snv_16,snv_17,snv_18,snv_19,snv_20,snv_21,snv_22,snv_23,snv_24,snv_25,snv_26,snv_27,snv_28,snv_29,snv_30,snv_31,snv_32,snv_33,snv_34,snv_35,snv_36,snv_37,snv_38,snv_39,snv_40,snv_41,snv_42,snv_43,snv_44,snv_45,snv_46,snv_47,snv_48,snv_49,snv_50,snv_51,snv_52,snv_53,snv_54,snv_55,snv_56,snv_57,snv_58,snv_59,snv_60,snv_61,snv_62,snv_63,snv_64,snv_65,snv_66,snv_67,snv_68,snv_69,snv_70,snv_71,snv_72,snv_73,snv_74,snv_75,snv_76,snv_77,snv_78,snv_79,snv_80,snv_81,snv_82,snv_83,snv_84,snv_85,snv_86,snv_87,snv_88,snv_89,snv_90,snv_91,snv_92,snv_93,snv_94,snv_95,snv_96,snv_97,snv_98,snv_99,snv_100,snv_101,snv_102; Upgrade sun solaris to a higher version than 8.0,9.0,10.0,and avoid the version 8.0,9.0,10.0; Upgrade ubuntu ubuntu_linux to a higher version than 6.06:_nil_,6.10,7.04,7.10,and avoid the version 6.06:_nil_,6.10,7.04,7.10