首页 -> 安全研究

安全研究

安全漏洞
Null HTTPd远程堆缓冲区溢出漏洞

发布日期:2002-09-23
更新日期:2002-09-28

受影响系统:
NullLogic Null httpd 0.5
    - RedHat Linux 7.3
不受影响系统:
NullLogic Null httpd 0.5.1
描述:
BUGTRAQ  ID: 5774
CVE(CAN) ID: CVE-2002-1496

Null HTTPd是一款小型多线程的WEB服务程序,可使用在Linux和Windows操作系统下。

Null HTTPd在处理Content-Length为负值的请求时存在问题,远程攻击者可以利用这个漏洞进行基于堆的缓冲区溢出,以Web进程在系统上执行任意指令。

当攻击者提供值为负的Conteng-Length请求时,可导致出现远程可利用基于堆的缓冲区溢出,有问题代码如下:

    typedef struct {
            // 进入数据
            ...
        // 外出数据
            ...
        /* 这个int定义为有符号值,可以包含负数 */
        int  out_ContentLength;
        ...
    } CONNDATA;

    typedef struct {
            ...
        char *PostData;
        ...
    } CONNECTION;


    int read_header(int sid)
    {
            char line[2048];
        ...
        sgets(line, sizeof(line)-1, conn[sid].socket);
        ...
         if (strncasecmp(line, "Content-Length: ", 16)==0)
                        conn[sid].dat->in_ContentLength=atoi((char *)&line+16);
        ...
        if (strcmp(conn[sid].dat->in_RequestMethod, "POST")==0) {
            if (conn[sid].dat->in_ContentLength<MAX_POSTSIZE) {
                ReadPOSTData(sid);
            }
            ...
        }
        ...
    }


    void ReadPOSTData(int sid) {
            char *pPostData;
        ...
        /* 这里出现了边界检查不充分 */
        conn[sid].PostData=calloc(conn[sid].dat->in_ContentLength+1024, sizeof(char));
        ...
        pPostData=conn[sid].PostData;
        ...
        /* 这里出现了缓冲区溢出 */
        recv(conn[sid].socket, pPostData, 1024, 0);
        ...
    }

可以看到,攻击者可以修改可分配缓冲区大小值并包含在POST数据中发送到Null HTTPd服务程序,数据里面包含一个正值和一个负值,意味我们把缓冲区大小改变为<negative value> + 1024,从而引起缓冲区溢出。

<*来源:Bert Vanmanshoven (sacrine@zworg.com
  
  链接:http://marc.theaimsgroup.com/?l=bugtraq&m=103279245630482&w=2
*>

建议:
临时解决方法:

如果您不能立刻安装补丁或者升级,NSFOCUS建议您采取以下措施以降低威胁:

* 暂时在边界防火墙设置策略,只允许可信IP访问Null HTTPd。

厂商补丁:

NullLogic
---------
采用如下补丁程序:

diff -Nru nullhttpd-0.5.0/src/format.c nullhttpd-0.5.1-pre/src/format.c
    --- nullhttpd-0.5.0/src/format.c    Sun Feb  3 18:18:22 2002
    +++ nullhttpd-0.5.1-pre/src/format.c    Sun Sep 15 21:55:09 2002
    @@ -153,3 +153,29 @@
         }
         return 0;
     }
    +
    +int printht(const char *format, ...)
    +{
    +    unsigned char buffer[1024];
    +    int offset=0;
    +    va_list ap;
    +
    +    va_start(ap, format);
    +    vsnprintf(buffer, sizeof(buffer)-1, format, ap);
    +    va_end(ap);
    +    while (buffer[offset]) {
    +        if (buffer[offset]=='<') {
    +            prints("&lt;");
    +        } else if (buffer[offset]=='>') {
    +            prints("&gt;");
    +        } else if (buffer[offset]=='&') {
    +            prints("&amp;");
    +        } else if (buffer[offset]=='"') {
    +            prints("&quot;");
    +        } else {
    +            prints("%c", buffer[offset]);
    +        }
    +        offset++;
    +    }
    +    return 0;
    +}
    diff -Nru nullhttpd-0.5.0/src/http.c nullhttpd-0.5.1-pre/src/http.c
    --- nullhttpd-0.5.0/src/http.c    Sun Feb  3 18:18:22 2002
    +++ nullhttpd-0.5.1-pre/src/http.c    Sun Sep 15 21:55:09 2002
    @@ -149,8 +149,15 @@
             while ((line[strlen(line)-1]=='\n')||(line[strlen(line)-1]=='\r')) line[strlen(line)-1]='\0';
             if (strncasecmp(line, "Connection: ", 12)==0)
                 strncpy(conn[sid].dat->in_Connection, (char *)&line+12, sizeof(conn[sid].dat->in_Connection)-1);
    -        if (strncasecmp(line, "Content-Length: ", 16)==0)
    +        if (strncasecmp(line, "Content-Length: ", 16)==0) {
                 conn[sid].dat->in_ContentLength=atoi((char *)&line+16);
    +            if (conn[sid].dat->in_ContentLength<0) {
    +                // Negative Content-Length?  If so, the client is either broken or malicious.
    +                // Thanks to <ilja@idefense.be> for spotting this one.
    +                logerror("ERROR: negative Content-Length of %d provided by client.", conn[sid].dat->in_ContentLength);
    +                conn[sid].dat->in_ContentLength=0;
    +            }
    +        }
             if (strncasecmp(line, "Cookie: ", 8)==0)
                 strncpy(conn[sid].dat->in_Cookie, (char *)&line+8, sizeof(conn[sid].dat->in_Cookie)-1);
             if (strncasecmp(line, "Host: ", 6)==0)
    diff -Nru nullhttpd-0.5.0/src/main.c nullhttpd-0.5.1-pre/src/main.c
    --- nullhttpd-0.5.0/src/main.c    Sun Feb  3 18:18:22 2002
    +++ nullhttpd-0.5.1-pre/src/main.c    Sun Sep 15 21:55:09 2002
    @@ -36,12 +36,17 @@
         logaccess(2, "%s - HTTP Request: %s %s", conn[sid].dat->in_RemoteAddr, conn[sid].dat->in_RequestMethod,
conn[sid].dat->in_RequestURI);
         snprintf(file, sizeof(file)-1, "%s%s", config.server_htdocs_dir, conn[sid].dat->in_RequestURI);
         snprintf(conn[sid].dat->out_ContentType, sizeof(conn[sid].dat->out_ContentType)-1, "text/html");
    -    if (strncmp(conn[sid].dat->in_RequestURI, "/cgi-bin/",    9)==0) cgi_main();
    -    else if (sendfile(sid, file)==0) return;
    -    else if (dirlist(sid)==0) return;
    -    else {
    +    if (strncmp(conn[sid].dat->in_RequestURI, "/cgi-bin/",    9)==0) {
    +        cgi_main();
    +    } else if (sendfile(sid, file)==0) {
    +        return;
    +    } else if (dirlist(sid)==0) {
    +        return;
    +    } else {
             send_header(sid, 0, 200, "OK", "1", "text/html", -1, -1);
    -        prints("<BR><CENTER>The file or function '%s' could not be found.</CENTER>\n", conn[sid].dat->in_RequestURI);
    +        prints("<BR><CENTER>The file or function '");
    +        printht("%s", conn[sid].dat->in_RequestURI);
    +        prints("' could not be found.</CENTER>\n");
             logerror("%s - Incorrect function call '%s'", conn[sid].dat->in_RemoteAddr, conn[sid].dat->in_RequestURI);
         }
         return;
    diff -Nru nullhttpd-0.5.0/src/main.h nullhttpd-0.5.1-pre/src/main.h
    --- nullhttpd-0.5.0/src/main.h    Sun Feb  3 18:18:22 2002
    +++ nullhttpd-0.5.1-pre/src/main.h    Sun Sep 15 21:55:09 2002
    @@ -251,6 +251,7 @@
     char *strcasestr(char *src, char *query);
     char *strcatf(char *dest, const char *format, ...);
     int printhex(const char *format, ...);
    +int printht(const char *format, ...);
     /* http.c functions */
     void printerror(int sid, int status, char* title, char* text);
     char *get_mime_type(char *name);
    diff -Nru nullhttpd-0.5.0/src/server.c nullhttpd-0.5.1-pre/src/server.c
    --- nullhttpd-0.5.0/src/server.c    Sun Feb  3 18:18:22 2002
    +++ nullhttpd-0.5.1-pre/src/server.c    Sun Sep 15 21:55:09 2002
    @@ -377,7 +377,14 @@
         if (strcasecmp("ANY", config.server_hostname)==0) {
             sin.sin_addr.s_addr=htonl(INADDR_ANY);
         } else {
    -        hp=gethostbyname(config.server_hostname);
    +        if ((hp=gethostbyname(config.server_hostname))==NULL) {
    +#ifdef WIN32
    +            MessageBox(0, "DNS Lookup failure.", APPTITLE, MB_ICONERROR);
    +#else
    +            printf("DNS Lookup failure.\r\n");
    +#endif
    +            exit(0);
    +        }
             memmove((char *)&sin.sin_addr, hp->h_addr, hp->h_length);
         }
         sin.sin_port=htons((unsigned short)config.server_port);

升级程序到Null httpd v0.5.1:

NullLogic Upgrade Null httpd 0.5.1
http://prdownloads.sourceforge.net/nullhttpd/nullhttpd-0.5.1.tar.gz

浏览次数:4005
严重程度:0(网友投票)
本安全漏洞由绿盟科技翻译整理,版权所有,未经许可,不得转载
绿盟科技给您安全的保障