Dear Sirs,
 
I find a SIP torture plugin from a web site, and copy all *.nasl to the
plugin forder.
When I restart nessusd, some error information will be displayed.
Does any one ever use this packet? 
Please tell me how to modify this nasl.
 
Thx. & B.R

Attachment: sip_torture_test_app1_insuf.nasl
Description: Binary data

# Main Script for SIP Torture Tests
#
# (C) 2006 Ingo Grebe
# $Revision: 1.0 $

include( "misc_func.inc" );

debug_level = 1;
debug = 1;

##############################################################################################
### --- Initialize global vars                                                  
           ###
##############################################################################################
myaddr_ = this_host();
dstaddr_ = get_host_ip();
returnport_ = rand() % 65535;
returnport2_ = rand() % 65535;
sip_port_ = get_kb_item( "sip_port" );
if( !sip_port_ ) sip_port_ = 5060;

authentication_ = TRUE;
sip_reg_name1_ = "";
sip_reg_uri1_ = "";
sip_reg_contact1_ = "";
sip_reg_name2_ = "";
sip_reg_uri2_ = "";
sip_reg_contact2_ = "";
replyudp_ = "";
replytcp_ = "";
##############################################################################################


if( debug )
  display( "\nSIP Torture Test @ ", dstaddr_, " on port ", sip_port_,
           "\n===================================================\n\n" );

### --- Is port SIP_PORT_ open?
testsoc = open_sock_tcp( sip_port_ );
if( testsoc == 0 )
{
  display( "Port ", sip_port_, " not open. Script stopped.\n" );
  exit( 0 );
}


##############################################################################################
### --- Read the SIP registration variables out of the KB. The values           
           ###
### --- were set by the script "sip_torture_test_settings.nasl".                
           ###
##############################################################################################
function read_sip_registration_vars()
{
  sip_reg_name1_ = get_kb_item( "sip_reg_name1" );
  sip_reg_uri1_ = get_kb_item( "sip_reg_uri1" );
  sip_reg_name2_ = get_kb_item( "sip_reg_name2" );
  sip_reg_uri2_ = get_kb_item( "sip_reg_uri2" );

  if( !sip_reg_name1_ && !sip_reg_uri1_ )
  {
    display( "No registration vars for User1. Script stopped.\n" );
    exit( 0 );
  }
  else
  {
    ### --- If no RETURNPORT for User1 exist in KB, it gets add.
    if( get_kb_item("sip_reg_returnport1") == "" )
      set_kb_item( name: "sip_reg_returnport1", value: returnport_ );
    else
      returnport_ = get_kb_item( "sip_reg_returnport1" );

    ### --- Read the SIP Contact String out of the KB. If the port differs
    ### --- from the RETURNPORT for User1, it gets rebuild.
    sip_reg_contact1_ = get_kb_item( "sip_reg_contact1" );
    if( returnport_ >!< sip_reg_contact1_ )
    {
      sip_reg_contact1_ = string( substr( sip_reg_uri1_, 0, 
stridx(sip_reg_uri1_, '@') ),
                                  myaddr_, ':', returnport_ );
      set_kb_item( name: "sip_reg_contact1", value: sip_reg_contact1_ );
    }
  }

  ### --- Same procedure for User 2.
  if( !sip_reg_name2_ && !sip_reg_uri2_ )
    display( "No registration vars for User2. Register only User1.\n" );
  else
  {
    ### --- If no RETURNPORT for User2 exist in KB, it gets add.
    if( get_kb_item("sip_reg_returnport2") == "" )
      set_kb_item( name: "sip_reg_returnport2", value: returnport2_ );
    else
      returnport2_ = get_kb_item( "sip_reg_returnport2" );

    ### --- Read the SIP Contact String out of the KB. If the port differs
    ### --- from the RETURNPORT for User2, it gets rebuild.
    sip_reg_contact2_ = get_kb_item( "sip_reg_contact2" );
    if( returnport2_ >!< sip_reg_contact2_ )
    {
      sip_reg_contact2_ = string( substr( sip_reg_uri2_, 0, 
stridx(sip_reg_uri2_, '@') ),
                                  myaddr_, ':', returnport2_ );
      set_kb_item( name: "sip_reg_contact2", value: sip_reg_contact2_ );
    }
  }

  if( debug )
    display( "SIP Registration vars\n---------------------\n",
             "Display Name [User1]: ", sip_reg_name1_, "\t\tDisplay Name 
[User2]: ", sip_reg_name2_, 
             "\nSIP Uri [User1]: ", sip_reg_uri1_, "\tSIP Uri [User2]: ", 
sip_reg_uri2_,
             "\nContact [User1]: ", sip_reg_contact1_, "\tContact [User2]: ", 
sip_reg_contact2_,
             "\nReturnport [User1]: ", returnport_, "\t\t\tReturnport [User2]: 
", returnport2_, "\n\n" );
}
########################################################################################################



########################################################################################################
### --- Send a string with the specified protocol ("udp" or "tcp") over the 
specified srcport.       ###
### --- When "udp", then the function builds an udp-packet, when "tcp" it opens 
the tcp-socket.      ###
### --- Note: "tcp" works only for port SIP_PORT_; "udp" works for all. So if 
"tcp" is used          ###
### --- RETURNPORT should be set to SIP_PORT_.                                  
                     ###
### --- After sending, it waits for an reply and stores the reply in REPLYUDP_ 
or REPLYTCP_.         ###
########################################################################################################
function send_string( string, protocol, srcport )
{
  if( !(protocol == "udp") && !(protocol == "tcp") )
  {
    display( "send_string: wrong protocol (must be 'udp' or 'tcp').\n" );
    exit( 0 );
  }

  if( protocol == "udp" )
  {
    if( !srcport )
    {
      if( debug )
        display( "Empty SRCPORT. Set SRCPORT = RETURNPORT_.\n" );
      srcport = returnport_;
    }

    ### --- build ip-packet
    ippkt = forge_ip_packet( ip_hl: 5,
                             ip_v: 4,
                             ip_tos: 0,
                             ip_len: 20,
                             ip_off: 0,
                             ip_ttl: 128,
                             ip_p: IPPROTO_UDP,
                             ip_src: myaddr_ );

    ### --- build udp-packet with specified SRCPORT and specified SIP message 
(string).
    udppacket = forge_udp_packet( ip: ippkt,
                                  uh_sport: srcport,
                                  uh_dport: sip_port_,
                                  uh_ulen: 8 + strlen(string),
                                  data: string );

    ### --- Filter all udp-packets from DSTADDR with destination ports 
RETURNPORT_ or RETURNPORT2_.
    filter = string( "udp and src ", dstaddr_, " and (dst port ", returnport_, 
" or dst port ", returnport2_, ")" );

    ### --- Finally send the udp-packet and wait for reply.
    replyudp_ = send_packet( udppacket, pcap_active:TRUE, pcap_filter:filter, 
pcap_timeout:10 );

    ### --- Compare the Call-Id elements of send and receive data. If differs, 
drop packet and get next.
    ### --- Counter i prevents endless loop.
    i = 0;
    while( (i++ < 5) &&
           !compareCallid(senddata: string, recvdata: replyudp_) )
      replyudp_ = pcap_next();

    ### --- Check the reply for authentication request.
    if( ("sip/2.0 407" >< tolower(replyudp_)) || ("sip/2.0 401" >< 
tolower(replyudp_)) )
    {
      if( debug )
        display( "\n(UDP) Data send, but authentication required. Send 
authentication digest now.\n" );

      if( !authentication_ )
      {
        if( debug )
          display( "(UDP) Authentication stopped cause 
AUTHENTICATION_=FALSE.\n\n" );
      }
      else
      {
        ### --- Build authentication response for the authentication request.
        string = digestAuthenticationData( senddata: string,
                                           recvdata: get_udp_element(udp: 
replyudp_, element: "data") );

        ### --- Build udp-packet with new authentication response (string).
        udppacket = forge_udp_packet( ip: ippkt,
                                      uh_sport: srcport,
                                      uh_dport: sip_port_,
                                      uh_ulen: 8 + strlen(string),
                                      data: string );

        ### --- Finally send the udp-packet with the authentication header 
field and wait for reply.
        replyudp_ = send_packet( udppacket, pcap_active:TRUE, 
pcap_filter:filter, pcap_timeout:10 );

        ### --- Compare the Call-Id elements of send and receive data. If 
differs, drop packet and get next.
        ### --- Counter i prevents endless loop.
        i = 0;
        while( (i++ < 5) &&
               !compareCallid(senddata: string, recvdata: replyudp_) )
          replyudp_ = pcap_next();

        ### --- Check if authentication accepted or not accepted.
        if( debug )
          if( ("sip/2.0 407" >< tolower(replyudp_)) || ("sip/2.0 401" >< 
tolower(replyudp_)) )
            display( "(UDP) Authentication not accepted.\n\n" );
          else 
            display( "(UDP) Authentication accepted.\n\n" );
      }
    }
  }

  if( protocol == "tcp" )
  {
    if( !srcport )
      srcport = sip_port_;

    ### --- This script supports only tcp-socket SIP_PORT_.
    if( srcport != sip_port_ )
      display( "SRCPORT should be manualy set to ", sip_port_, " when tcp is 
used. But it is ",
               srcport, ". Is it right?\n" );

    sendsoc = open_sock_tcp( sip_port_ );

    if( !sendsoc )
    {
      display( "send_string: TCP Port ", sip_port_, " is closed.\n" );
      return 0;
    }
    else
    {
      ### --- Send the message and wait for reply.
      send( socket: sendsoc, data: string );
      replytcp_ = recv( socket: sendsoc, length: 1024, timeout: 10 );

      ### --- Compare the Call-Id elements of send and receive data. If 
differs, drop packet and get next.
      ### --- Counter i prevents endless loop.
      i = 0;
      while( (i++ < 5) && !compareCallid(senddata: string, recvdata: replytcp_) 
)
        replytcp_ = pcap_next();

      if( ("sip/2.0 407" >< tolower(replytcp_)) || ("sip/2.0 401" >< 
tolower(replytcp_)) )
      {
        if( debug )
          display( "\n(TCP) Data send, but authentication required. Send 
authentication digest now.\n" );

        if( !authentication_ )
        {
          if( debug )
            display( "(TCP) Authentication stopped cause 
AUTHENTICATION_=FALSE.\n\n" );
        }
        else
        {
          ### --- Build authentication response for the authentication request.
          string = digestAuthenticationData( senddata: string, recvdata: 
replytcp_ );

          ### --- Finally send the udp-packet with the authentication header 
field and wait for reply.
          send( socket: sendsoc, data: string );
          replytcp_ = recv( socket: sendsoc, length: 1024, timeout: 10 );

          ### --- Compare the Call-Id elements of send and receive data. If 
differs, drop packet and get next.
          ### --- Counter i prevents endless loop.
          i = 0;
          while( (i++ < 5) && !compareCallid(senddata: string, recvdata: 
replytcp_) )
            replytcp_ = pcap_next();

          ### --- Check if authentication accepted or not accepted.
          if( ("sip/2.0 407" >< tolower(replytcp_)) || ("sip/2.0 401" >< 
tolower(replytcp_)) )
            display( "(TCP) Authentication not accepted.\n\n" );
          else 
            display( "(TCP) Authentication accepted.\n\n" );
        }
      }
    }

    close( sendsoc );
  }

  if( debug )
    display( "send string (length: ", strlen(string), ") per ", protocol,
             "\n--------------------------------------------\n",
             "--- ", myaddr_, ":", srcport, " -> ", dstaddr_, ":", sip_port_,
             "\n--------------------------------------------\n", string );
}
##############################################################################################


##############################################################################################
### --- Returns the reply message, which is received in the function 
SEND_STRING().        ###
### --- protocol is "udp" or "tcp"                                              
           ###
##############################################################################################
function recv_data( protocol )
{
  if( !(protocol == "udp") && !(protocol == "tcp") )
  {
    display( "recv_data: wrong protocol (must be 'udp' or 'tcp').\n" );
    exit( 0 );
  }

  if( protocol == "udp" )
  {
    if( replyudp_ == "" ) data = "";
    else
    {
      data = get_udp_element( udp: replyudp_, element: "data" );

      ### --- Read out source and destination port of the udp-packet.
      ### --- Needed for debug string.
      sport = get_udp_element( udp: replyudp_, element: "uh_sport" );
      dport = get_udp_element( udp: replyudp_, element: "uh_dport" );
    }
  }
  else
  {
    ### --- Values when "tcp" is used.
    sport = sip_port_;
    dport = sip_port_;
    data = replytcp_;
  }

  if( data )
  {
    if( debug )
      display( "return ", protocol ," data",
               "\n--------------------------------------------\n",
               "--- ", myaddr_, ":", dport, " <- ", dstaddr_, ":", sport,
               "\n--------------------------------------------\n", data );
    return data;
  }
  else
  {
    if( debug )
      display( "[no return ", protocol ," data]\n\n" );

    return "";
  }
}
######################################################################################################



######################################################################################################
### --- Receive the next udp-packet. It's needed when the SIP Server sends two 
messages.           ###
### --- The PCAP-Filter is set in a way, that this function receives packets 
for both returnports. ###
### --- Note: Receive nextdata works and exists only for udp and not for tcp.   
                   ###
######################################################################################################
function recv_nextdata_udp()
{
  nextreply = pcap_next();
  if( nextreply )
    nextdata = get_udp_element( udp: nextreply, element: "data" );

  if( debug )
    display( "return nextdata\n---------------\n", nextdata, "\n" );

  return nextdata;
}
######################################################################################################



######################################################################################################
### --- Build the security_note for the port SIP_PORT_ and the protocol "udp" 
or "tcp".            ###
######################################################################################################
function plugin_output( message, protocol, sipresponse )
{
  ### --- Is port SIP_PORT_ still open?
  testsoc = open_sock_tcp( sip_port_ );
  if( testsoc == 0 )
  {
    message = string( "\nPort ", sip_port_, " isn't still open.\n", message );
    display( "Port ", sip_port_, " isn't still open.\n" );
  }

  ### --- If MESSAGE is empty, then the sip torture tests couldn't handle the 
sip element's response.
  if( sipresponse == "" )
    sipresponse = string( "[no response]\n" );

  if( message == "" )
    message = "FAILED? Can't handle the SIP element's response. The response 
is:" + '\n' + sipresponse;

  if( debug )
    display( "Plugin output [", protocol ,"]\n-------------------\n", message, 
"\n\n" );

  security_note( port: sip_port_, protocol: protocol, data: desc["english"] + 
'\n\nPlugin output :\n'
                 + message + '\n\n' );
  register_service( port: sip_port_, ipproto: protocol, proto: "sip" );
}
######################################################################################################


######################################################################################################
### --- This function compares the Call-Id elements of SENDDATA and RECVDATA.   
                   ###
######################################################################################################
function compareCallid( senddata, recvdata )
{
  ### --- If nothing to compare, return TRUE.
  if( !senddata || !recvdata || ("sip/2.0" >!< tolower(recvdata)) )
    return TRUE;

  lines = split( senddata, keep: 0 );

  ### --- read the METHOD out of the sended data
  firstline = split( lines[0], sep: ' ', keep: 0 );
  method = chomp(firstline[0]);

  ### --- If nothing to compare, return TRUE.
  if( method >!< recvdata )
    return TRUE;

  ### --- reads out the Call-Id element of SENDDATA
  foreach line ( lines )
  {
    if( "call-id" >!< tolower(line) )
      continue;

    break;
  }

  line = ereg_replace( string: line, pattern: ' ', replace: '' );

  callidline = split( line, sep: ':', keep: 0 );

  if( callidline[1] >< recvdata )
    return TRUE;
  else
  {
    if( debug )
      display( "Call-Id elements of SENDDATA and RECVDATA don't compare.\n",
               "--------------------------------------------------------\n",
               "call-id of senddata:\n", callidline[1], "\nrecvdata:\n", 
recvdata,
               "\n--------------------------------------------------------\n" );
    return FALSE;
  }
}


######################################################################################################
### --- This function builds a new SIP message with an authentication header 
field.                ###
### --- It needs the SIP servers SIP message with the authenticate header 
field. And it needs the  ###
### --- sended packet before the server responded. This function follows RFC 
2617.                 ###
######################################################################################################
function digestAuthenticationData( senddata, recvdata )
{
  ### --- Initialize all the vars needed for building authentication header.
  realm = "";
  nonce = "";
  opaque = "";
  method = "";
  uri = "";

  ### --- Reads the authentication USERNAME and PASSWORD out of the KB.
  user = get_kb_item( "sip_auth_user" );
  pwd = get_kb_item( "sip_auth_pwd" );
  if( (user == "") || (pwd == "") )
    display( "No username and/or no password for SIP Server Authentication. ",
             "Authentication may fail!.\n\n" );

  ### --- look for the WWW-Authenticate or Proxy-Authenticate element in 
RECVDATA
  lines = split( recvdata );
  proxyauthenticate = FALSE;
  wwwauthenticate = FALSE;

  ### --- reads out the authenticate element
  ### --- if authenticate element is found then it is in LINE 
  foreach line ( lines )
  {
    if( "WWW-Authenticate" >< line ) wwwauthenticate = TRUE;
    else
      if( "Proxy-Authenticate" >< line ) proxyauthenticate = TRUE;
      else continue;

    break;
  }

  if( !wwwauthenticate && !proxyauthenticate )
  {
    display( "No Authenticate element found.\n" );
    exit( 0 );
  }

  if( "digest" >!< tolower(line) )
  {
    display( "Only Digest Authentication supported.\n" );
    exit( 0 );
  }

  if( "algorithm=" >< tolower(line) )
    if( ("md5" >!< tolower(line)) || ("md5-sess" >< tolower(line)) )
    {
      display( "Only MD5 algorithm supported.\n" );
      exit( 0 );
    }

  ### --- read the METHOD and the URI out of the sended data
  senddataLines = split( senddata, keep: 1 ); 
  firstline = split( senddataLines[0], sep: ' ', keep: 0 );
  method = firstline[0];
  uri = firstline[1];

  ######################################################################
  ### --- read the needed vals out of the Authenticate element ---   ###
  ######################################################################
  if( "realm" >< tolower(line) )
  {
    idx = stridx( line, "realm=" ) + 7;
    realm = substr( line, idx, stridx(line, '"', idx)-1 );
  }
  else
  {
    display( "Authentication error: No REALM parameter.\n" );
    exit( 0 );
  }

  if( "nonce" >< tolower(line) )
  {
    idx = stridx( line, "nonce=" ) + 7;
    nonce = substr( line, idx, stridx(line, '"', idx)-1 );
  }
  else
  {
    display( "Authentication error: No NONCE parameter.\n" );
    exit( 0 );
  }

  if( "opaque" >< tolower(line) )
  {
    idx = stridx( line, "opaque=" ) + 8;
    opaque = substr( line, idx, stridx(line, '"', idx)-1 );

    ### --- Quotes the OPAQUE parameter, because it should be returned by the 
client
    ### --- unchanged in the Authorization header of subsequent requests 
    opaque = string( ',opaque="', opaque, '"' );
  }

  if( "qop" >< tolower(line) )
  {
    idx = stridx( line, "qop=" ) + 8;
    qop = substr( line, idx, stridx(line, '"', idx)-1 );

    ### --- Quotes the QOP parameter for authentication header, because if a 
client receives
    ### --- a "qop" parameter in a challenge header field, it MUST send the 
"qop" parameter in
    ### --- any resulting authorization header field.
    qop = string( ',qop="', qop, '"' );
  }

  if( "uri" >< tolower(line) )
  {
    idx = stridx( line, "uri=" ) + 5;
    uri = substr( line, idx, stridx(line, '"', idx)-1 );
  }
  else
    if( "domain" >< tolower(line) )
    {
      idx = stridx( line, "domain=" ) + 5;
      uri = substr( line, idx, stridx(line, '"', idx)-1 );
    }

  if( uri == "" )
  {
    display( 'No URI parameter found.\n' );
    exit( 0 );
  }
  ### --- all needed vals readed out of the Authenticate element --- ###
  ######################################################################

  ### --- calculate the hashes of A1 and A2 as described in RFC 2617
  a1 = string( user, ':', realm, ':', pwd );
  a2 = string( toupper(method), ':', uri );
  ha1 = hexstr(MD5(a1));
  ha2 = hexstr(MD5(a2));

  ### --- calculate the RESPONSE as described in RFC 2617
  kd = string( ha1 , ':', nonce, ':', ha2 );
  response = hexstr(MD5(kd));

  if( "auth" >< tolower(qop) )
    if( debug )
      display( 'QOP is "auth" or "auth-int". The definition of RESPONSE differs 
from the one is made.',
               'The correct definition is described in RFC 2617 and is not 
supported in this script.' );

  ### --- set TRUE only for intensive debuging
  if( FALSE )
    display( "realm:|", realm, "|\n",
             "nonce:|", nonce, "|\n",
             opaque, "\n", qop, "\n",
             "uri:|", uri, "|\n",
             "pwd:|", pwd, "|\n",
             "user:|", user, "|\n",
             "method:|", method, "|\n",
             "response:|", response, "|\n" );

  if( proxyauthenticate )
    authorization = string( 'Proxy-Authorization: Digest username="', user, 
'",' , qop,
                            'realm="', realm, '",uri="', uri, 
'",algorithm=MD5,opaque="",' ,
                            'nonce="', nonce, '",response="', response, '"\r\n' 
);

  if( wwwauthenticate )
    authorization = string( 'WWW-Authorization: Digest username="', user, '",' 
, qop,
                            'realm="', realm, '",uri="', uri, 
'",algorithm=MD5,opaque="",' ,
                            'nonce="', nonce, '",response="', response, '"\r\n' 
);

  newdata = "";

  ### --- Inserts authorization digest before Via header field and increment 
the number behind "CSeq:".
  foreach line ( senddataLines )
  {
    if( "cseq" >< tolower(line) )
    {
      parts = split( line, sep: ' ', keep: 0 );
      parts[1]++;
      line = string( parts[0], " ", parts[1], " ", parts[2] );
    }

    if( "via" >< tolower(line) )
      newdata += authorization;

    newdata += line;
  }

  ### --- set TRUE only for intensive debuging
  if( FALSE )
    display( "\nnew data with authentication header 
field\n------------------------------------------\n",
             newdata );

  return newdata;
}
_______________________________________________
Nessus mailing list
[email protected]
http://mail.nessus.org/mailman/listinfo/nessus
  • [no subject] 3p
    • Re: Michel Arboi

Reply via email to