首页 -> 安全研究
安全研究
安全漏洞
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("<");
+ } else if (buffer[offset]=='>') {
+ prints(">");
+ } else if (buffer[offset]=='&') {
+ prints("&");
+ } else if (buffer[offset]=='"') {
+ prints(""");
+ } 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
浏览次数:3721
严重程度:0(网友投票)
绿盟科技给您安全的保障