首页 -> 安全研究
安全研究
安全漏洞
IAXClient多个截短IAX帧内存破坏漏洞
发布日期:2006-06-06
更新日期:2006-06-10
受影响系统:
IAXClient IAXClient不受影响系统:
LoudHush LoudHush 1.3.6
Kiax Kiax 0.8.5
IaxComm IaxComm 1.0
asterisKGuru IDEFISK Softphone 1.35
LoudHush LoudHush 1.3.7描述:
Kiax Kiax 0.8.51
IaxComm IaxComm 1.2
BUGTRAQ ID: 18307
IAXClient是用于实现IAX2 VoIP协议的开放源码函数库。
IAXClient对IAX消息的处理上存在内存破坏漏洞,远程攻击者可能利用此漏洞在服务器上执行任意指令。
IAX消息被称为帧。iaxclient/lib/libiax2/src/iax2.h文件中定义了两个帧类型,分别是IAX完整帧(full frame)和IAX小型帧(mini-frame)。
/* Full frames are always delivered reliably */
struct ast_iax2_full_hdr {
unsigned short scallno; /* Source call number -- high bit must be 1 */
unsigned short dcallno; /* Destination call number -- high bit is 1 if
retransmission */
unsigned int ts; /* 32-bit timestamp in milliseconds (from 1st
transmission) */
unsigned char oseqno; /* Packet number (outgoing) */
unsigned char iseqno; /* Packet number (next incoming expected) */
char type; /* Frame type */
unsigned char csub; /* Compressed subclass */
unsigned char iedata[0];
} __PACKED;
/* Mini header is used only for voice frames -- delivered unreliably */
struct ast_iax2_mini_hdr {
unsigned short callno; /* Source call number -- high bit must be 0, rest
must be non-zero */
unsigned short ts; /* 16-bit Timestamp (high 16 bits from last
ast_iax2_full_hdr) */
/* Frametype implicitly VOICE_FRAME */
/* subclass implicit from last ast_iax2_full_hdr */
unsigned char data[0];
} __PACKED;
解析通过网络接收的IAX报文是由iaxclient/lib/libiax2/src/iax.c中实现的iax_net_process()函数完成的。以下截取自该文件的revision 536:
struct iax_event *iax_net_process(unsigned char *buf, int len, struct
sockaddr_in *sin)
{
struct ast_iax2_full_hdr *fh = (struct ast_iax2_full_hdr *)buf;
struct ast_iax2_mini_hdr *mh = (struct ast_iax2_mini_hdr *)buf;
struct iax_session *session;
if (ntohs(fh->scallno) & IAX_FLAG_FULL) {
/* Full size header */
[A] if (len < sizeof(struct ast_iax2_full_hdr)) {
DEBU(G "Short header received from %s\n", inet_ntoa(sin->sin_addr));
IAXERROR "Short header received from %s\n", inet_ntoa(sin->sin_addr));
}
/* We have a full header, process appropriately */
session = iax_find_session(sin, ntohs(fh->scallno) & ~IAX_FLAG_FULL,
ntohs(fh->dcallno) & ~IAX_FLAG_RETRANS, 1);
if (!session)
session = iax_txcnt_session(fh, len-sizeof(struct ast_iax2_full_hdr),
sin, ntohs(fh->scallno) & ~IAX_FLAG_FULL, ntohs(fh->dcallno) &
~IAX_FLAG_RETRANS);
if (session)
return iax_header_to_event(session, fh, len - sizeof(struct
ast_iax2_full_hdr), sin);
DEBU(G "No session?\n");
return NULL;
} else {
[B] if (len < sizeof(struct ast_iax2_mini_hdr)) {
DEBU(G "Short header received from %s\n", inet_ntoa(sin->sin_addr));
IAXERROR "Short header received from %s\n", inet_ntoa(sin->sin_addr));
}
/* Miniature, voice frame */
session = iax_find_session(sin, ntohs(fh->scallno), 0, 0);
if (session)
return iax_miniheader_to_event(session, mh, len - sizeof(struct
ast_iax2_mini_hdr));
DEBU(G "No session?\n");
return NULL;
}
}
len参数是从同一文件中实现的iax_net_read()函数接收到的,其值设置为recvfrom(2)函数调用的返回值,也就是从网络读取的字节数。buf参数是指向栈中分配的固定大小缓冲区的指针,数据从iax_net_read()函数读取。
函数在[A]和[B]执行了长度检查以确保所接收到的报文不是截短了的full-frame或mini-frame,但在输出错误消息后仍可能出现过小的报文,这就导致了两个可利用的漏洞。
IAX2截短full-frame漏洞
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
在[A]的情况下full-frame报文是由以下执行流处理的:
iax_net_read()
iax_net_process()
iax_find_session()
iax_txcnt_session()
iax_header_to_event()
同一文件中也实现了iax_txcnt_session:
static struct iax_session *iax_txcnt_session(struct ast_iax2_full_hdr
*fh, int datalen,
struct sockaddr_in *sin, short callno, short dcallno)
{
int subclass = uncompress_subclass(fh->csub);
unsigned char buf[ 65536 ]; /* allocated on stack with same size as
iax_net_read() */
struct iax_ies ies;
struct iax_session *cur;
if ((fh->type != AST_FRAME_IAX) || (subclass != IAX_COMMAND_TXCNT) ||
(!datalen)) {
return NULL; /* special handling for TXCNT only */
}
[C] memcpy(buf, fh->iedata, datalen); /* prepare local buf for
iax_parse_ies() */
if (iax_parse_ies(&ies, buf, datalen)) {
return NULL; /* Unable to parse IE's */
}
...
datalen参数接收iax_net_process()传送的值,其计算方法为datalen = len-sizeof(struct ast_iax2_full_hdr)。如果full frame报文是从网络读取的话,该值就可能小于0。
然后在[C]使用了负值datalen的memcpy就会在栈中固定大小的缓冲区buf触发溢出。攻击者可以通过创建11字节长的UDP报文触发这个漏洞,执行任意代码。
由于使用了负数长度参数的malloc(2)、memset(2)和memcpy(2)组合,iax_header_to_event()函数也存在类似问题,在这种情况下是堆溢出。
IAX2截短mini-frame漏洞
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
类似的,在[B]的情况下,mini-frame报文是由以下执行流处理的:
iax_net_read()
iax_net_process()
iax_find_session()
iax_miniheader_to_event()
以下节选自同一文件的iax_miniheader_to_event()函数:
static struct iax_event *iax_miniheader_to_event(struct iax_session
*session,
struct ast_iax2_mini_hdr *mh,
int datalen)
{
struct iax_event *e;
unsigned int ts;
int updatehistory = 1;
e = (struct iax_event *)malloc(sizeof(struct iax_event) + datalen);
if (e) {
if (session->voiceformat > 0) {
e->etype = IAX_EVENT_VOICE;
e->session = session;
e->subclass = session->voiceformat;
e->datalen = datalen;
if (datalen) {
#ifdef EXTREME_DEBUG
DEBU(G "%d bytes of voice\n", datalen);
#endif
[D] memcpy(e->data, mh->data, datalen);
}
ts = (session->last_ts & 0xFFFF0000) | ntohs(mh->ts);
return schedule_delivery(e, ts, updatehistory);
如果datalen参数值小于0的话,[D]的memcpy就会触发堆分配的数据溢出。3字节的UDP报文(比mini-frame报文短1个字节)可以触发这个溢出,导致执行任意代码。
<*来源:Damian Saura
Alejandro Lozanoff
Eduardo Koch
Norberto Kueffner
Steve K
Ivan Arce
链接:http://marc.theaimsgroup.com/?l=bugtraq&m=114989398527826&w=2#0
*>
建议:
临时解决方法:
如果您不能立刻安装补丁或者升级,NSFOCUS建议您采取以下措施以降低威胁:
* 在边界阻断到4569/UDP端口的入站报文。
厂商补丁:
LoudHush
--------
目前厂商已经发布了升级补丁以修复这个安全问题,请到厂商的主页下载:
http://www.loudhush.ro/opencms/export/sites/default/loudhush/LoudHush1.3.7.dmg.zip
浏览次数:3160
严重程度:0(网友投票)
绿盟科技给您安全的保障