|
|
|
|
| |
Credit:
The information has been provided by Corelabs.
The original article can be found at: http://www.coresecurity.com/common/showdoc.php?idx=547&idxseccion=10
The vendor advisory can be found at: http://www.asterisk.org/node/95
|
| |
Vulnerable Systems:
* Asterisk PBX version 1.2.8 and prior
* Asterisk PBX version 1.0.10 and prior
Immune Systems:
* Asterisk version 1.2.9 and above
* Asterisk version 1.0.11 and above
The Inter-Asterisk Exchange (IAX) protocol provides control and transmission of streaming media over IP networks. IAX can be used with any type of streaming media including video and still images but is targeted primarily at the control of VoIP calls.
The IAX protocol relies on a single UDP port for all communications (4569/udp). The protocol uses a 15-bit identification number ("call number") to multiplex several IAX2 streams over the same UDP port.
IAX2 messages are called frames. Several basic frame types are described in the protocol specification draft[1] and defined in the iax2.h header file of the Asterisk source code package.
An IAX2 full frame uses the 12-byte header described below:
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) */
unsigned char type; /* Frame type */
unsigned char csub; /* Compressed subclass */
unsigned char iedata[0];
} __attribute__ ((__packed__));
An IAX2 mini-frame, used on established sessions for voice transition, has a 4-byte header:
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];
} __attribute__ ((__packed__));
Video frames are supported using the following 6-byte packet header:
struct ast_iax2_video_hdr {
unsigned short zeros; /* Zeros field -- must be zero */
unsigned short callno; /* Video call number */
unsigned short ts; /* Timestamp and mark if present */
unsigned char data[0];
} __attribute__ ((__packed__));
Asterisk reads IAX2 packets from the network in the socket_read() function implemented in channels/chan_iax2.c.
The following excerpts are from revision 29849 of the file (included in the Asterisk 1.2.8 package)
static int socket_read(int *id, int fd, short events, void *cbdata)
{
struct sockaddr_in sin;
int res;
int updatehistory=1;
int new = NEW_PREVENT;
unsigned char buf[4096];
void *ptr;
socklen_t len = sizeof(sin);
...
res = recvfrom(fd, buf, sizeof(buf), 0,(struct sockaddr *) &sin,
&len);
if (res < 0) {
if (errno != ECONNREFUSED)
ast_log(LOG_WARNING, "Error: %s\n",
strerror(errno));
handle_error();
return 1;
}
if(test_losspct) { /* simulate random loss condition */
if( (100.0*rand()/(RAND_MAX+1.0)) < test_losspct)
return 1;
}
[A] if (res < sizeof(struct ast_iax2_mini_hdr)) {
ast_log(LOG_WARNING,
"midget packet received (%d of %d min)\n", res,
(int)sizeof(struct ast_iax2_mini_hdr));
return 1;
}
if ((vh->zeros == 0) && (ntohs(vh->callno) & 0x8000)) {
/* This is a video frame, get call number */
fr->callno = find_callno(ntohs(vh->callno) & ~0x8000,
dcallno, &sin, new,1, fd);
[B] minivid = 1;
} else if (meta->zeros == 0) {
....
At [A] a length check is performed to make sure that the number of bytes read from the network is not less than those required for a complete a mini frame header, if that check is passed the packet is further inspected to determine if it belongs to video-enabled session in [B].
Since the required header length of a IAX2 mini-frame is less than the header length of a video frame, Asterisk will not reject truncated video frames of length equal to or greater than 4 bytes (but less than 6-bytes).
Processing of video frames is later done further down the execution flow:
...
} else if (minivid) {
f.frametype = AST_FRAME_VIDEO;
if (iaxs[fr->callno]->videoformat > 0)
f.subclass = iaxs[fr->callno]->videoformat
| (ntohs(vh->ts) & 0x8000 ? 1: 0);
else {
ast_log(LOG_WARNING,
"Received mini frame before first full video frame\n ");
iax2_vnak(fr->callno);
ast_mutex_unlock(&iaxsl[fr->callno]);
return 1;
}
[C] f.datalen = res - sizeof(struct ast_iax2_video_hdr);
if (f.datalen)
f.data = buf + sizeof(struct ast_iax2_video_hdr);
else
f.data = NULL;
...
}
...
[D] iax_frame_wrap(fr, &f)
In [C] the lenght of video payload is calculated subtracting the size of video header (number of bytes required in a video header) from the number of bytes read from the network (return code of the recvfrom() call). Naturally if a truncated video frame was received the result of this subtraction will be a negative number and will end up stored in f.datalen, additionally f.data will end up pointing to memory outside the boundaries of the packet received.
Later at [D] the iax_frame_wrap() function, implemented in iax2-parser.c is called:
void iax_frame_wrap(struct iax_frame *fr, struct ast_frame *f)
{
fr->af.frametype = f->frametype;
fr->af.subclass = f->subclass;
fr->af.mallocd = 0; /* Our frame is static relative to the
container */
fr->af.datalen = f->datalen;
fr->af.samples = f->samples;
fr->af.offset = AST_FRIENDLY_OFFSET;
fr->af.src = f->src;
fr->af.delivery.tv_sec = 0;
fr->af.delivery.tv_usec = 0;
fr->af.data = fr->afdata;
if (fr->af.datalen) {
#if __BYTE_ORDER == __LITTLE_ENDIAN
/* We need to byte-swap slinear samples from network
byte order */
if ((fr->af.frametype == AST_FRAME_VOICE) &&
(fr->af.subclass ==AST_FORMAT_SLINEAR)) {
ast_swapcopy_samples(fr->af.data, f->data,
fr->af.samples);
} else
#endif
[E] memcpy(fr->af.data, f->data, fr->af.datalen);
}
}
The memcpy() at [E] will receive a pointer to memory outside of the packet read from the network as second argument and a negative value as third argument resulting in an exploitable buffer overflow condition that could be used by an attacker to execute arbitrary code on the system running Asterisk.
CVE Information:
CVE-2006-2898
Vendor Status:
The vendor has issued a fix.
Disclosure Timeline:
2006-06-02: Initial notification to vendor
2006-06-02: Vendor response acknowledging notification
2006-06-05: Draft advisory and technical details provided to vendor
2006-06-05: Fixed versions of Asterisk released by vendor
2006-06-06: Asterisk 1.2.9 release announced
|
|
|
|
|