[UNIX] Asterisk IAX2 Video Frame Buffer Overflow
- From: SecuriTeam <support@xxxxxxxxxxxxxx>
- Date: 15 Jun 2006 11:35:02 +0200
The following security advisory is sent to the securiteam mailing list, and can be found at the SecuriTeam web site: http://www.securiteam.com
- - promotion
The SecuriTeam alerts list - Free, Accurate, Independent.
Get your security news from a reliable source.
http://www.securiteam.com/mailinglist.html
- - - - - - - - -
Asterisk IAX2 Video Frame Buffer Overflow
------------------------------------------------------------------------
SUMMARY
" <http://www.asterisk.org/> Asterisk is a complete PBX in software. It
runs on Linux, BSD and MacOSX and provides all of the features you would
expect from a PBX and more. Asterisk does voice over IP in many protocols,
and can interoperate with almost all standards-based telephony equipment
using relatively inexpensive hardware."
" <http://en.wikipedia.org/wiki/IAX> IAX is the Inter-Asterisk eXchange
protocol used by Asterisk."
Improper handling of the IAX2 protocol allows attackers to execute
arbitrary code using Asterisk.
DETAILS
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:
<http://www.cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2006-2898>
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
ADDITIONAL INFORMATION
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>
http://www.coresecurity.com/common/showdoc.php?idx=547&idxseccion=10
The vendor advisory can be found at: <http://www.asterisk.org/node/95>
http://www.asterisk.org/node/95
========================================
This bulletin is sent to members of the SecuriTeam mailing list.
To unsubscribe from the list, send mail with an empty subject line and body to: list-unsubscribe@xxxxxxxxxxxxxx
In order to subscribe to the mailing list, simply forward this email to: list-subscribe@xxxxxxxxxxxxxx
====================
====================
DISCLAIMER:
The information in this bulletin is provided "AS IS" without warranty of any kind.
In no event shall we be liable for any damages whatsoever including direct, indirect, incidental, consequential, loss of business profits or special damages.
- Prev by Date: [UNIX] KDM Symlink Attack File Permissions Bypass
- Next by Date: [EXPL] PicoZip Long Filename Buffer Overflow (Exploit)
- Previous by thread: [UNIX] KDM Symlink Attack File Permissions Bypass
- Next by thread: [EXPL] PicoZip Long Filename Buffer Overflow (Exploit)
- Index(es):
Relevant Pages
|