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
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
