POSTED BY: Stelios Tsampas / 30.03.2016

Kamailio SEAS module encode_msg heap buffer overflow

CENSUS ID:CENSUS-2016-0009
CVE ID:CVE-2016-2385
Affected Products:Kamailio 4.3.4 (and possibly previous versions)
Class:Heap-based Buffer Overflow (CWE-122)
Remote:Yes
Discovered by:Stelios Tsampas

Kamailio (successor of former OpenSER and SER) is an Open Source SIP Server released under GPL, able to handle thousands of call setups per second. Kamailio can be used to build large platforms for VoIP and realtime communications, presence, WebRTC, Instant messaging and other applications. It can also easily be applied to scaling up SIP-to-PSTN gateways, PBX systems or media servers.

There is a (remotely exploitable) heap overflow vulnerability in Kamailio version 4.3.4 and possibly in previous versions. The vulnerability takes place in the SEAS module, which enables Kamailio to transfer the execution logic control of a SIP message to a given external entity, called the Application Server.

Details

The heap overflow can be triggered if Kamailio is configured to use the SEAS module, more specifically if Kamailio calls the module’s single exported function as_relay_t(). The heap overflow is located in function encode_msg(), file encode_msg.c, line 269:


int encode_msg(struct sip_msg *msg, char *payload,int len)
{
   ...
   /*now we copy the actual message after the headers-meta-section*/
   memcpy(&payload[j],msg->buf,msg->len);
   LM_DBG("msglen = %d,msg starts at %d\n",msg->len,j);
   j=htons(j);
   ...
}

msg is a pointer to a sip_msg structure and it is basically the current SIP packet being processed by Kamailio. msg->buf is a buffer which holds the packet's contents and msg->len is the packet's length. Unsurprisingly, msg->len can take arbitrary values (bound by the packet size) while j takes the value of 180 in most cases.

The destination buffer payload is allocated in encoded_msg()'s caller function, create_as_event_t(), specifically in file seas.c, line 442:


char * create_as_event_t(struct cell *t, struct sip_msg *msg, char processor_id, 
                         int *evt_len, int flags)
{
   ...
  if(!(buffer=shm_malloc(ENCODED_MSG_SIZE))){
     LM_ERR("Out Of Memory !!\n");
     return 0;
  }
  ...
  if(encode_msg(msg,buffer+k,ENCODED_MSG_SIZE-k)<0){
     LM_ERR("Unable to encode msg\n");
     goto error;
  }
  ...
}

Preprocessor constant ENCODE_MSG_SIZE is defined as 3200 and variable k at line 521 holds the value 34. The problem is that the program does not check the packet's length if it is larger than the destination buffer. If a user makes a request with a large enough packet then the buffer will overflow.

Discussion

We were able to trigger the bug remotely using a large UDP packet.

A proof-of-concept packet is provided here that crashes the Kamailio process handling the request. From bash the packet can be sent using the following command:


cat seas-trigger.packet > /dev/udp/KAMAILIO-IP/KAMAILIO-PORT

This bug may potentially provide attackers with remote code execution capabilities.

Recommendation

The security defect has been fixed in version 4.3.5 of Kamailio. Upgrading to the latest stable version is strongly advised.

Disclosure Timeline

Vendor Contact:February 12th, 2016
CVE assignment:February 15th, 2016
Vendor Patch Release:March 3rd, 2016
Public Advisory:March 30th, 2016