Auditando sistemas de VoIP con SIPPTS (1/2)

Han pasado ya 4 años desde que subí la primera versión de SIPPTS a Google Code y la verdad es que nunca he llegado a escribir un post comentando su funcionamiento, así que, unas versiones más tarde, vamos a analizar y poner algunos ejemplos de cómo usar esta herramienta para realizar auditorías de VoIP. Por cierto, no tengo logo en la herramienta porque el diseño y yo no nos llevamos bien, pero si alguien se presta a hacer alguno, será bien recibido 🙂

Actualmente podemos descargar SIPPTS desde Github y su uso es totalmente gratuito. Por supuesto, he de recordar que la finalidad de esta herramienta es realizar un test de penetración para auditar y fortalecer la seguridad de los sistemas de VoIP y, en ningún caso, debe utilzarse para hacer nada ilegal.

SIPPTS es un conjunto de scripts programados en Perl que nos permiten realizar diferentes acciones y, en este primer post vamos a ver cómo utilizar las herramientas básicas para ejecutar una auditoría. Bueno, antes de entrar en materia, he de comentar que la herramienta más utilizada para este tipo de tareas siempre ha sido SIPVicious, una gran herramienta para realizar un test de penetración básico, pero que si quieres hacer más cosas debes pasar por caja y comprar la versión Pro. SIPPTS es totalmente gratuita y, además de lo que ofrece SIPVicious, incorpora algunos scripts para hacer más cosas interesantes, como explotar la vulnerabilidad SIPDigestLeak, que ya comenté en el anterior post.

En una auditoría básica sobre un sistema de VoIP, vamos a seguir 3 fases:

  1. Localizar servicios y dispositivos VoIP y obtener la máxima información posible sobre la estructura, como versiones, modelos, enumeración de extensiones, etc.
  2. Intentar vulnerar algún fallo de configuración, como el uso de contraseñas débiles o malas configuraciones que nos permita emitir llamadas.
  3. Elaborar un reporte.

En primer lugar usaremos la herramienta SIPScan. Se trata de un escáner SIP que nos permite auditar tanto direcciones IP como rangos de red en busca de sistemas de VoIP. Entre sus características principales, podemos destacar:

  • Identificación de PBX, proxy, teléfonos, gateways, etc.
  • Soporta protocolos UDP y TCP.
  • Es capaz de escanear grandes rangos de red.
  • Puede analizar rangos de puertos.
  • Permite customizar el agente de usuario, para hacer la herramienta indetectable.
  • Comprueba los puertos por defecto en busca de paneles web de administración.
  • Programación multihilo para una ejecución más rápida.
  • Permite almacenar todos los resultados en una base de datos SQLite.
$ perl sipscan.pl 

SipSCAN - by Pepelux <pepeluxx@gmail.com>
-------

Usage: perl sipscan.pl -h <host> [options]
 
== Options ==
-m  <string>     = Method: REGISTER/INVITE/OPTIONS (default: OPTIONS)
-u  <string>     = Username
-s  <integer>    = Source number (CallerID) (default: 100)
-d  <integer>    = Destination number (default: 100)
-r  <integer>    = Remote port (default: 5060)
-proto <string>  = Protocol (udp, tcp or all (both of them) - By default: ALL)
-ip <string>     = Source IP (by default it is the same as host)
-db              = Save results into database (sippts.db)
-nolog           = Don't show anything on the console
-v               = Verbose (trace information)
-vv              = More verbose (more detailed trace)
 
== Examples ==
$ perl /usr/share/sippts/sipscan.pl -h 192.168.0.1
        To search SIP services on 192.168.0.1 port 5060 (using OPTIONS method)
        To search several ranges
$ perl /usr/share/sippts/sipscan.pl -h 192.168.0.1,192.168.2.0/24.192.168.3.1-192.168.20.200
        To search SIP services using INVITE method
$ perl /usr/share/sippts/sipscan.pl -h 192.168.0.1 -m INVITE
        To search SIP services on 192.168.0.1 port 5060 (using INVITE method)
$ perl /usr/share/sippts/sipscan.pl -h 192.168.0.0/24 -v -proto tcp
        To search SIP services on 192.168.0.0 network by TCP connection (using OPTIONS method)
$ perl /usr/share/sippts/sipscan.pl -h 192.168.0.1-192.168.0.100 -r 5060-5070 -vv
        To search SIP services on 192.168.0.100 ports from 5060 to 5070 (using OPTIONS method)

La gran diferencia con otras herramientas es que permite escanear tanto por UDP como por TCP. Además es muy últil poder cambiar el agente de usuario, dado que es la huella de nuestra herramienta y, a medida que se hace conocida, será bloqueada de forma automática por cualquier sistema con unos mínimos ajustes de seguridad. Todos los scripts de SIPPTS usan como agente de usuario pplsip que, con una simple búsqueda en Google, vemos que está catalogado como un SIP Bot y que muchos sistemas ya lo bloquean con sus configuraciones por defecto. Es por ello que se incorpora el parámetro -ua UserAgent que nos permite personalizar el agente de usuario de los mensajes.

Usando el parámetro -db almacenaremos todos los resultados en la base de datos, que podremos consultar posteriormente para elaborar el informe. Un ejemplo basico de SIPScan podría ser:

$ perl sipscan.pl -h 192.168.0.0/24 -r 5060-5070
[+] 192.168.0.51:5060 - Sending OPTIONS 100 => 100
[-] 401 Unauthorized
[+] 192.168.0.55:5060 - Sending OPTIONS 100 => 100
[-] 200 OK
[+] 192.168.0.54:5060 - Sending OPTIONS 100 => 100
[-] 483 Too Many Hops

IP address	Port	Proto	User-Agent	                      Web
==========	====	=====	==========	                      ===
192.168.0.51    5060    udp	kamailio (4.2.1 (x86_64/linux))
192.168.0.51    5060    tcp	kamailio (4.2.1 (x86_64/linux))
192.168.0.55    5060    udp	Asterisk PBX 1.8.13.1~dfsg1-3+deb7u3
192.168.0.126	5064	udp	Grandstream GXP2130 1.0.9.69	      80/tcp
192.168.0.153	5060	udp	Fanvil X6 1.4.5 0c383e1eb36c	      80/tcp

Como se puede apreciar en el ejemplo, el propio UserAgent del servidor o del dispositivo nos ofrece mucha información últil sobre el sistema que estamos analizando, como el nombre o modelo del software usado así como la versión, o el sistema operativo sobre el que está corriendo. En el caso de los dispositivos, posiblemente estarán usando otros puertos, pero en una red local es bastante sencillo localizarlos.

Por tanto, en esta primera fase, com un simple escaneo, hemos localizado:

  • Un servidor proxy Kamailio con versión 4.2.1 corriendo en un Linux de 64 bits. Este servidor corre tanto por UDP como TCP en el puerto por defecto 5060.
  • Una PBX Asterisk con una versión bastante antigua, la 1.8.13, que se ejecuta en una máquina con Debian 7 y que corre bajo UDP.
  • Un telefono Fanvil X6 con versión de firmware 1.4.5 en el puerto 5064/udp.
  • Un telefono Grandstream GXP2130 con versión de firmware 1.0.9.69 en el puerto 5060/udp.

En resumen, se trata de una red con un proxy, una PBX y dos teléfonos, que corren por UDP, sin cifrados y con poca seguridad.

La siguiente herramienta que usaremos es SIPExten, que nos va a permitir intentar enumerar extensiones dentro de una centralita, en este caso, el servidor Asterisk que hemos localizado.

$ perl sipexten.pl 

SipEXTEN - by Pepelux <pepeluxx@gmail.com>
--------

Usage: perl sipexten.pl -h <host> [options]
 
== Options ==
-e  <string>     = Extensions (default 100-1000)
-s  <integer>    = Source number (CallerID) (default: 100)
-d  <integer>    = Destination number (default: 100)
-r  <integer>    = Remote port (default: 5060)
-p  <string>     = Prefix (for extensions)
-proto <string>  = Protocol (UDP or TCP - By default: UDP)
-ip <string>     = Source IP (by default it is the same as host)
-ua <string>     = Customize the UserAgent
-db              = Save results into database (sippts.db)
-nolog           = Don't show anything on the console
-v               = Verbose (trace information)
-vv              = More verbose (more detailed trace)

Las principales características de este script son:

  • Enumeración de extensiones de una PBX.
  • Puede escanear diferentes máquinas a la vez, o rangos de red.
  • Escanea grandes rangos de extensiones.
  • Intenta averiguar si la extensión requiere autenticación o no.
  • Permite añadir un prefijo, para el caso de que la el usuario no coincida con la extensión.
  • Soporta protocolo UDP y TCP.
  • Permite customizar el agente de usuario, para hacer la herramienta indetectable.
  • Permite almacenar todos los resultados en una base de datos SQLite.

En una centralita con cero seguridad vamos a tener extensión 200 y usuario 200 pero es probable que el usuario no coincida con el número de extensión sino que se añada un prefijo, por ejemplo, extensión 200 y usuario loquesea200. En una red local y, sobre todo si se usa UDP donde las comunicaciones no van cifradas, simplemente monitorizando la red y capturando algún paquete SIP, podremos ver algún usuario y deducir que el resto tendrá la misma estructura, es decir, si en una captura vemos el usuario gestoria210, podemos imaginar que todos los usuarios serán gestoriaXXX y usaremos el parámetro -p prefix para realizar el análisis. Un ejemplo basico de SIPExten podría ser:

$ perl sipexten.pl -h 192.168.0.55 -e 100-200

IP address	Port	Extension	Authentication                  User-Agent
==========	====	=========	==============                  ==========
192.168.0.55	5060	100		No authentication required      Asterisk PBX 16.2.1
192.168.0.55	5060	101		Require authentication          Asterisk PBX 16.2.1

En este caso vemos que hay 2 usuarios que coinciden con el número de extensión y, además, una de ellas no requiere autenticación. Y al igual que el otro script, podríamos usar el parámetro -db para almacenar los resultados en una base de datos, o el parámetro -ua para cambiar el agente de usuario.

Llegados a este punto ya tenemos un mapa de la red telefónica, donde hemos podido recabar información tan interesante como:

  • Protocolos usados.
  • Identificación de servicios (proxy y PBX) con el sistema usado, modelo y versión.
  • Identificación de dispositivos telefónicos, con marca, modelo y versión.
  • Identificación de los sistemas operativos usados.
  • Enumeración de extensiones de la centralita.

Obtener información sobre la marca, modelo y versión de los servidores y dispositivos es muy importante ya que nos permite buscar fallos de seguridad conocidos.

Y continuando con nuestra auditoría, podemos usar el script SIPCrack para intentar crackear por fuerta bruta, en remoto, las contraseñas de aquellos usuarios que hemos descubierto en la fase anterior.

$ perl sipcrack.pl

SipCRACK - by Pepelux <pepeluxx@gmail.com>
--------

Usage: perl sipcrack.pl -h <host> -w wordlist [options]
 
== Options ==
-e  <string>     = Extension (default from 100 to 1000)
-s  <integer>    = Source number (CallerID) (default: 100)
-d  <integer>    = Destination number (default: 100)
-r  <integer>    = Remote port (default: 5060)
-p  <string>     = Prefix (for extensions)
-proto <string>  = Protocol (UDP or TCP - By default: UDP)
-ip <string>     = Source IP (by default it is the same as host)
-resume          = Resume last session
-w               = Wordlist
-v               = Verbose (trace information)
-vv              = More verbose (more detailed trace)

Esta herramienta tiene características similares a los scripts anteriores y nos permite conectar tanto por UDP como por TCP, cambiar el agente de usuario, etc.

Para su uso es necesario un diccionario, que se usará para realizar la fuerza bruta. Un ejemplo básico sería:

$ perl sipcrack.pl -h 192.168.0.55 -e 100-200 -w dictionary

IP address	Port	Proto   Exten	Pass
==========	====	=====   =====	====
192.168.0.55	5060	udp     100	p3p3lux
192.168.0.55	5060	udp     101	p3p3lux

Y otra herramienta bastante útil para analizar la seguridad de una centralita es SIPInvite. De esta herramienta ya he hablado en varias ocasiones aquí: Asterisk – INVITE attack y aquí: Asterisk – INVITE attack (II). Lo que hace este script es lanzar una petición de llamada, de forma que, si la centralita está mal configurada, la llamada se realizará sin que nos pida ningún tipo de autenticación.

Este es un ataque que cada vez se realiza más, y el motivo es bastante obvio. Hasta no hace mucho, era muy típico ver muchísimos ataques por fuerza bruta, con mensajes REGISTER, intentando crackear cuentas de usuario, y aunque se siguen viendo todos los días ataques así, esto cada vez tiene menos sentido, por varios motivos:

  • Es complicado encontrar usuarios de autenticación que coincidan con el número de extensión. Si por ejemplo intentamos crackear el usuario 200 haciendo fuerza bruta con diferentes contraseñas, como el usuario sea del tipo loquesea200, nunca conseguiremos nada.
  • Cantan demasiado estos ataques dado que dejan muchos registros en los logs.
  • Son fácilmente detectables con herramientas del tipo fail2ban, que además los bloquea enseguida.
  • Son ataques lentos al ser en remoto.
  • Si conseguimos la combinación correcta, tendremos seguramente 2 canales, por lo que se podrán hacer 2 llamadas simultáneas.

Por tanto siempre es más efectivo buscar fallos de configuración que permitan llamar sin autenticarnos. Y el funcionamiento es sencillo. Mandamos un mensaje INVITE (una solicitud de llamada) al servidor y vemos qué responde. Y la respuesta irá en función de la configuración que se haya realizado. Por ejemplo:

  • Si no se permiten mensajes INVITE de orígenes anónimos, sino que sólo se acepta de servidores donde estemos registrados (nuestros proveedores), obtendremos una respuesta del tipo 403 Forbidden, o 488 Not Acceptable Here, o 500 Server Internal Error. La verdad es que todo depende de lo que programemos, sobre todo si se trata de un proxy. Una PBX como pueda ser Asterisk, siempre va a dar las mismas respuestas, pero en un proxy las respuestas las programa el administrador.
  • Si permitimos mensajes INVITE de cualquier lugar pero nuestro sistema está bien configurado, le responderemos pidiéndole que se autentique, con un 401 Unauthorized.
  • Si no tenemos bien configurados los contextos en nuestro plan de llamadas, posiblemente obtengamos un error 404 Not found o incluso un 403 Forbidden. En este caso el atacante se puede frotar las manos porque puede haber ‘chicha’ donde buscar. Un 404 indica que no ha podido llamar a ese destino, pero quizás a otro sí que se pueda.
  • Si el sistema nos devuelve un 100 Trying, ya podemos echarnos las manos a la cabeza, porque está cursando la llamada.

En realidad, cualquier cosa que no sea un 401 Unauthorized, nos indica que no se solicita autenticación, por lo que el atacante probará a llamar a diferentes destinos de distintos países, con diferentes prefijos, con diferentes números de origen. Todo con la finalidad de intentar saltar un posible filtro que tengamos. Por ejemplo poniendo ceros delante, el signo +, o cambiando la extensión llamante. He aquí algunos ejemplos de un ataque real:

Ataque con mensajes INVITE

Podéis ver que las horas del ataque son muy seguidas y que las direcciones IP son casi todas diferentes, por lo que os podéis imaginar la cantidad de ataques que se reciben por minuto. Y esto es una máquina de pruebas que no conoce nadie, con una IP cualquiera.

Y la herramienta que trae SIPPTS para realizar este tipo de ataques nos permite cambiar ciertos valores de las cabeceras, como el agente de usuario, destino, llamante, etc. Además admite autenticación, por lo que si conocemos la contraseña, es posible realizar llamadas autenticándonos, lo que nos permite testear llamadas a diferetnes destinos para ver si tenemos bien configurado nuestro sistema.

$ perl sipinvite.pl 

SipINVITE - by Pepelux <pepeluxx@gmail.com>
---------

Usage: perl sipinvite.pl -h <host> -d <dst_number> [options]
 
== Options ==
-d  <integer>    = Destination number
-u  <string>     = Username to authenticate
-p  <string>     = Password to authenticate
-s  <integer>    = Source number (CallerID) (default: 100)
-r  <integer>    = Remote port (default: 5060)
-t  <integer>    = Transfer call to another number
-ip <string>     = Source IP (by default it is the same as host)
-ua <string>     = Customize the UserAgent
-v               = Verbose (trace information)

Como comentaba antes, este tipo de ataques cada vez se utilizan más, ya que no requiere fuerza bruta, ni tenemos que conocer la contraseña de ningún usuario. Además, si el servidor enruta el mensaje INVITE hacia el operador, el número de canales que tendremos disposibles serán los facilitados por nuestro operador en el trunk contratado para toda la centralita, que seguro que son muy superiores a los 2 que suele llevar cada teléfono.

Por parte del operador que nos ofrezca salida al exterior, serán llamadas procedentes de la IP de un cliente, por lo que en principio no las va a bloquear. Ya todo dependerá del sistema antifraude de nuestro operador el que nos hagan un agujero más o menos grande. Por eso es muy importante contratar los servicios de VoIP con alguien que nos de un buen servicio y que tenga un sistema antifraude decente, capaz de detectar y bloquear tanto ataques como este tipo de llamadas.

Y otra de las opciones que permite el script es realizar una transferencia de llamada, es decir, mandamos un mensaje INVITE a un destino. Si el servidor está mal configurado y enruta el mensaje a través del operador, sonará el teléfono marcado. Una vez que se descuelgue la llamada, el script mandará un mensaje REFER para realizar una transferencia a otro destino diferente. Y lo que se consigue con esto es poner en comunicación a dos personas diferentes, usando 2 canales de un servidor mal configurado.

SipINVITE                     SIP Server                      Phone1              Phone2
         ---> INVITE      ---> 
                                        ---> INVITE      --->
                                        <--- 100 Trying  <---
         <--- 100 Trying  <---
                                        <--- 180 Ringing <---
         <--- 180 Ringing <---
                                        <--- 200 Ok      <---
         <--- 200 Ok      <---
         ---> ACK         ---> 
         <--- 200 Ok      <---
         ---> REFER       ---> 
                                        --->           INVITE                --->
         <--- 202 Accept  <---
                                                              <--->  RTP Session <--->

Un ejemplo de uso para ver si el servidor es vulnerable sería:

$ perl sipinvite.pl -h 192.168.0.55 -d 0034666666666
[+] Sending INVITE 100 => 0034666666666
[-] 100 Trying
[-] 183 Session Progress
[-] 200 OK

O intentando realizar una transferencia de llamada:

$ perl sipinvite.pl -h 192.168.0.55 -d 0034666666666 -t 0034777777777
[+] Sending INVITE 100 => 0034666666666
[-] 100 Trying
[-] 183 Session Progress
[-] 200 OK
[+] Sending ACK
[+] Sending REFER 100 => 0034777777777
[-] 202 Accepted

Y por último, con la herramienta SIPReport podemos extraer información de la base de datos, en caso de que hayamos almacenado los resultados con el parámetro -db.

$ perl sipreport.pl
SipREPORT - by Pepelux <pepeluxx@gmail.com>
---------

Usage: perl sipreport.pl -h <host> | -u <user-agent> [options]

== Options ==
-noexten    = Show only servers and devices (not extensions nor users)
-noauth     = Show extensions where authentication is not required

== Examples ==
$perl sipreport.pl -h 192.168.0.1
	To show all data in database for host 192.168.0.1
$perl sipreport.pl -h 192.168.0.0
	To show all data in database for network 192.168.0.0
$perl sipreport.pl -h .
	To show all data
$perl sipreport.pl -h . -noauth
	To show all data with users without auth
$perl sipreport.pl -u fpbx
	To show all FreePBX in database (with User-Agent: fpbx)

Por ejemplo, para ver la información obtenida en el servidor Asterisk que hemos analizado:

$ perl sipreport.pl -h 192.168.0.55
[+] 192.168.0.55:5060/udp 	- UserAgent: Asterisk PBX 16.2.1
	[-] exten: 100 	- No authentication required
	[-] exten: 101 	- Require authentication

O también podríamos sacar unreporte de una red entera, donde nos mostrará un pequeño informe de todas las máquinas.

Y esto sería una auditoría básica en una red telefónica de VoIP. En un segundo post veremos otras herramientas incluidas en SIPPTS.

Un comentario

Deja un comentario