安全研究
安全漏洞
BitchX Send_CTCP()远程内存破坏漏洞
发布日期:2003-03-14
更新日期:2003-03-20
受影响系统:
BitchX IRC Client 1.0c19描述:
BUGTRAQ ID: 7097
BitchX是一款流行的IRC客户端,可使用在多种操作系统平台下,包括Linux和Windows。
BitchX中的Send_CTCP()函数缺少正确的边界缓冲区检查,远程攻击者利用这个漏洞提交恶意服务器端数据,导致BitchX崩溃。
BitchX包含如下代码:
---
#define IRCD_BUFFER_SIZE 512
#define BIG_BUFFER_SIZE IRCD_BUFFER_SIZE*4
extern void send_ctcp (int type, char *to, int datatag, char *format, ...)
{
char putbuf [BIG_BUFFER_SIZE + 1],
*putbuf2;
int len;
len = IRCD_BUFFER_SIZE - (12 + strlen(to));
putbuf2 = alloca(len);
...
snprintf(putbuf2, len, "%c%s %s%c",
CTCP_DELIM_CHAR,
ctcp_cmd[datatag].name, putbuf,
CTCP_DELIM_CHAR);
...
putbuf2[len - 2] = CTCP_DELIM_CHAR;
putbuf2[len - 1] = 0;
---
其中调用的alloca()函数没有进行任何边界检查,攻击者提交恶意服务器段数据可以破坏堆栈内容,精心构建应答数据给BitchX可能以用户进程权限在系统上执行任意指令。
<*来源:Timo Sirainen (tss@iki.fi)
链接:http://marc.theaimsgroup.com/?l=bugtraq&m=104766521328322&w=2
*>
建议:
临时解决方法:
如果您不能立刻安装补丁或者升级,NSFOCUS建议您采取以下措施以降低威胁:
* Timo Sirainen <tss@iki.fi>提供如下第三方补丁:
diff -ru BitchX-old/source/banlist.c BitchX/source/banlist.c
--- BitchX-old/source/banlist.c 2002-02-28 06:22:46.000000000 +0200
+++ BitchX/source/banlist.c 2003-03-13 20:09:01.000000000 +0200
@@ -277,30 +277,30 @@
case 7:
if (ip)
{
- sprintf(banstr, "*!*@%s", cluster(ip));
+ snprintf(banstr, sizeof(banstr), "*!*@%s", cluster(ip));
break;
}
case 2: /* Better */
- sprintf(banstr, "*!*%s@%s", t1, cluster(host));
+ snprintf(banstr, sizeof(banstr), "*!*%s@%s", t1, cluster(host));
break;
case 3: /* Host */
- sprintf(banstr, "*!*@%s", host);
+ snprintf(banstr, sizeof(banstr), "*!*@%s", host);
break;
case 4: /* Domain */
- sprintf(banstr, "*!*@*%s", strrchr(host, '.'));
+ snprintf(banstr, sizeof(banstr), "*!*@*%s", strrchr(host, '.'));
break;
case 5: /* User */
- sprintf(banstr, "*!%s@%s", t, cluster(host));
+ snprintf(banstr, sizeof(banstr), "*!%s@%s", t, cluster(host));
break;
case 6: /* Screw */
malloc_sprintf(&tmpstr, "*!*%s@%s", t1, host);
- strcpy(banstr, screw(tmpstr));
+ strmcpy(banstr, screw(tmpstr), sizeof(banstr)-1);
new_free(&tmpstr);
break;
case 1: /* Normal */
default:
{
- sprintf(banstr, "%s!*%s@%s", nick, t1, host);
+ snprintf(banstr, sizeof(banstr), "%s!*%s@%s", nick, t1, host);
break;
}
}
diff -ru BitchX-old/source/ctcp.c BitchX/source/ctcp.c
--- BitchX-old/source/ctcp.c 2002-02-28 06:22:47.000000000 +0200
+++ BitchX/source/ctcp.c 2003-03-13 19:59:35.000000000 +0200
@@ -1482,6 +1482,7 @@
*putbuf2;
int len;
len = IRCD_BUFFER_SIZE - (12 + strlen(to));
+ if (len <= 2) return;
putbuf2 = alloca(len);
if (format)
diff -ru BitchX-old/source/misc.c BitchX/source/misc.c
--- BitchX-old/source/misc.c 2002-03-24 11:31:07.000000000 +0200
+++ BitchX/source/misc.c 2003-03-13 20:02:13.000000000 +0200
@@ -3121,19 +3121,19 @@
{
if (*hostname == '~')
hostname++;
- strcpy(result, hostname);
+ strmcpy(result, hostname, sizeof(result)-1);
*strchr(result, '@') = '\0';
if (strlen(result) > 9)
{
result[8] = '*';
result[9] = '\0';
}
- strcat(result, "@");
+ strmcat(result, "@", sizeof(result)-1);
if (!(hostname = strchr(hostname, '@')))
return NULL;
hostname++;
}
- strcpy(host, hostname);
+ strmcpy(host, hostname, sizeof(host)-1);
if (*host && isdigit(*(host + strlen(host) - 1)))
{
@@ -3154,8 +3154,8 @@
for (i = 0; i < count; i++)
tmp = strchr(tmp, '.') + 1;
*tmp = '\0';
- strcat(result, host);
- strcat(result, "*");
+ strmcat(result, host, sizeof(result)-1);
+ strmcat(result, "*", sizeof(result)-1);
}
else
{
@@ -3177,10 +3177,10 @@
else
return (char *) NULL;
}
- strcat(result, "*");
+ strmcat(result, "*", sizeof(result)-1);
if (my_stricmp(host, temphost))
- strcat(result, ".");
- strcat(result, host);
+ strmcat(result, ".", sizeof(result)-1);
+ strmcat(result, host, sizeof(result)-1);
}
return result;
}
diff -ru BitchX-old/source/names.c BitchX/source/names.c
--- BitchX-old/source/names.c 2002-03-25 22:47:30.000000000 +0200
+++ BitchX/source/names.c 2003-03-13 20:10:26.000000000 +0200
@@ -572,7 +572,7 @@
*nmodes = 0;
*nargs = 0;
- for (; *modes; modes++)
+ for (; *modes && strlen(nmodes) < sizeof(nmodes)-2; modes++)
{
isbanned = isopped = isvoiced = 0;
switch (*modes)
@@ -742,7 +742,7 @@
/* modes which can be done multiple times are added here */
- for (tucm = ucm; tucm; tucm = tucm->next)
+ for (tucm = ucm; tucm && strlen(nmodes) < sizeof(nmodes)-2; tucm = tucm->next)
{
if (tucm->o_ed)
{
diff -ru BitchX-old/source/notice.c BitchX/source/notice.c
--- BitchX-old/source/notice.c 2002-02-28 06:22:50.000000000 +0200
+++ BitchX/source/notice.c 2003-03-13 20:07:39.000000000 +0200
@@ -422,10 +422,10 @@
{
char *q = strchr(line, ':');
char *port = empty_string;
- int conn = !strncmp(line+7, "connect", 7) ? 1 : 0;
+ int conn = strlen(line) > 7 && !strncmp(line+7, "connect", 7) ? 1 : 0;
int dalnet = 0, ircnet = 0;
- if (*(line+18) == ':')
+ if (strlen(line) > 18 && *(line+18) == ':')
q = NULL;
else
dalnet = (q == NULL);
@@ -462,7 +462,7 @@
else sscanf(p, "%s was %s from %s", for_, fr, temp);
q = p;
- sprintf(q, "%s@%s", fr, temp);
+ snprintf(q, strlen(q)+1, "%s@%s", fr, temp);
if (!conn)
{
port = strstr(temp2, "reason:");
diff -ru BitchX-old/source/server.c BitchX/source/server.c
--- BitchX-old/source/server.c 2002-03-25 07:21:24.000000000 +0200
+++ BitchX/source/server.c 2003-03-13 20:10:00.000000000 +0200
@@ -474,11 +474,11 @@
}
else
#endif
- junk = dgets(bufptr, des, 1, BIG_BUFFER_SIZE, server_list[i].ssl_fd);
+ junk = dgets(bufptr, des, 1, BIG_BUFFER_SIZE/2, server_list[i].ssl_fd);
}
else
#endif
- junk = dgets(bufptr, des, 1, BIG_BUFFER_SIZE, NULL);
+ junk = dgets(bufptr, des, 1, BIG_BUFFER_SIZE/2, NULL);
}
switch (junk)
{
@@ -1741,7 +1741,7 @@
default:
if (FD_ISSET(des, &rd))
{
- if (!dgets(buffer, des, 0, BIG_BUFFER_SIZE, NULL))
+ if (!dgets(buffer, des, 0, BIG_BUFFER_SIZE/2, NULL))
flushing = 0;
}
break;
@@ -1751,7 +1751,7 @@
FD_ZERO(&rd);
FD_SET(des, &rd);
if (new_select(&rd, NULL, &timeout) > 0)
- dgets(buffer, des, 1, BIG_BUFFER_SIZE, NULL);
+ dgets(buffer, des, 1, BIG_BUFFER_SIZE/2, NULL);
}
厂商补丁:
BitchX
------
目前厂商还没有提供补丁或者升级程序,我们建议使用此软件的用户随时关注厂商的主页以获取最新版本:
http://www.bitchx.org/
浏览次数:3099
严重程度:0(网友投票)
绿盟科技给您安全的保障