He descubierto recientemente el peligro de un REGISTER con una cabecera "Contact" maliciosa y la vulnerabilidad que puede suponer en entornos con gateways.
Pregunté sobre ello en la lista de users-es@mail.openser.org donde obtuve muy buenas y didácticas respuestas de miembros muy experimentados con estos asuntos.
Escenario
Supongamos una infraestructura con los siguientes personajes:
- Un proxy SIP (OpenSer) con IP 100.100.100.100 donde registramos a los usuarios SIP y les otorgamos permisos en llamadas PSTN.
- Un gateway SIP_2_PSTN con IP 1.2.3.4 (un Cisco, Nortel, Asterisk o lo que fuere) que recibe llamadas vía SIP y las convierte a la PSTN.
El flujo que realiza una llamada a la PSTN desde un dispositivo SIP es el siguiente:
-
El teléfono SIP envía un INVITE a su proxy (nuestro OpenSer) con esta pinta:
INVITE sip:0034666555444@dominio.org SIP/2.0
From: "Iñaki" <sip:ibc@dominio.org>;tag=iesxq - OpenSer nos fuerza a autenticarnos (lo que le sirve también para facturar la llamada) y posteriormente ruta el INVITE al gateway (IP 1.2.3.4).
En este punto hay que aclarar que el gateway no va a pedir autenticación "digest" para ese INVITE (el cliente ya se ha autenticado donde corresponde, es decir, en su proxy, y además OpenSer no es un B2BUA).
De hecho la autenticación en la comunicación proxy -> gateway es por IP o TLS. En nuestro caso supongamos autenticación por IP: El gateway sólo admite INVITE desde la IP de nuestro proxy (100.100.100.100) y se supone que toda la seguridad de acceso y permisos está controlada por el proxy (como ha sido en el caso de autenticar al usuario para la llamada PSTN del ejemplo anterior).
Funcionamiento del registro SIP
Cuando un usuario SIP quiere registrarse en su proxy para recibir llamadas envía un REGISTER tal que así:
REGISTER sip:dominio.org SIP/2.0
To: "Iñaki" <sip:ibc@dominio.org>
From: "Iñaki" <sip:ibc@dominio.org>;tag=pxziz
Contact: <sip:ibc@85.95.10.58>;expires=1800
Importante reseñar que:
-
En un REGISTER el campo importante es el To (y no el From) que implica el AoR (Address of Record) que queremos registrar, en nuestro caso
sip:ibc@dominio.org. - La cabecera "Contact" indica la localización donde está el usuario (suponemos que está tras IP pública y nos olvidamos por hoy de los problemas y trapicheos del NAT).
- Super-importante destacar que el contenido de la cabecera "Contact" lo escribe la aplicación cliente.
Así pues, tras el proceso de registro el proxy, en su papel de "Location Server", tendrá almacenada la siguiente información en alguna base de datos:
user contact
-----------------------------------------
ibc@dominio.org sip:ibc@85.95.10.58
Ahora cuando otro usuario llame a ibc@dominio.org el INVITE llegará (por resolución DNS de dominio.org) a nuestro proxy. OpenSer buscará entonces en la base de datos la localización de dicho usuario y obtendrá sip:ibc@85.95.10.58.
Así que rutará allí el INVITE, o sea, llegará al teléfono SIP y sonará.
Trampa en el "Contact" del REGISTER
Ahora supongamos que soy un usuario malicioso (ibc@dominio.org) y quiero aprovecharme de mi proxy para hacer llamadas gratuitas.
Con alguna utilidad SIP genero un REGISTER así:
REGISTER sip:dominio.org SIP/2.0
To: "Iñaki" <sip:ibc@dominio.org>
From: "Iñaki" <sip:ibc@dominio.org>;tag=pxziz
Contact: <sip:0034666555444@1.2.3.4>;expires=1800
Lo que genera esta entrada en la base de datos del proxy:
user contact
-----------------------------------------
ibc@dominio.org sip:0034666555444@1.2.3.4
Ahora desde otra cuenta SIP (o desde la mía propia) hago una llamada a ibc@dominio.org. Igual que antes el proxy consultará la base de datos y obtendrá en esta ocasión que debe rutar la llamada a sip:0034666555444@1.2.3.4, es decir, la rutará al gateway.
O sea, una llamada a sip:ibc@dominio.org se ha convertido en una llamada a la PSTN al número 0034666555444. Además el gateway permitirá esa llamada puesto que viene desde el proxy (IP 100.100.100.100).
Así de fácil hemos vulnerado la seguridad de nuestro proxy y obtenido privilegios en llamada gratuita a la PSTN.
Solución a este problema
El problema de raíz viene originado por el hecho de que el "Contact" en el REGISTER es creado por el usuario (o aplicación de usuario).
Una solución que inicialmente nos podría servir es la de prohibir registros en los que el "Contact" contenga alguna IP (en nuestro caso la 1.2.3.4 del gateway).
Para ello OpenSer, dentro del módulo "permissions" incluye el fichero "register.deny" y una función para consultarlo durante el REGISTER. En dicho fichero podemos escribir un listado de expresiones regulares que no permitimos en la URI de la cabecera "Contact" del REGISTER.
En nuestro caso ponemos:
ALL : "^sip:.*1\.2\.3\.4$"
Entonces si ahora mando el REGISTER malicioso anterior será rechazado por la URI del "Contact".
Ojito...
Pero como he vivido cerca de un colegio se me ocurre otra trampa. Envío este REGISTER:
REGISTER sip:dominio.org SIP/2.0
To: "Iñaki" <sip:ibc@dominio.org>
From: "Iñaki" <sip:ibc@dominio.org>;tag=pxziz
Contact: <sip:0034666555444@1.0002.3.4>;expires=1800
(obsérvese el 1.0002.3.4).
Esa IP no es detectada por la anterior expresión regular, sin embargo es válida:
$ ping 1.0002.3.4
PING 1.0002.3.4 (1.2.3.4) 56(84) bytes of data.
64 bytes from 1.2.3.4: icmp_seq=1 ttl=64 time=0.038 ms
64 bytes from 1.2.3.4: icmp_seq=2 ttl=64 time=0.056 ms
64 bytes from 1.2.3.4: icmp_seq=3 ttl=64 time=0.052 ms
Así que se nos colará de nuevo :(
Mejorando la solución
Entonces ponemos:
ALL : "^sip:.*0*1\.0*2\.0*3\.0*4$"
Y de esta forma se detecta la IP 1.0002.3.4 y se prohibe el registro. ¡Bien!
¿Seguro...?
Como atacante me estrujo el cerebro y mejoro mi estrategia:
Registro un dominio hackeando_mi_proxy.com y le asocio la IP 1.2.3.4. Ahora envío el REGISTER:
REGISTER sip:dominio.org SIP/2.0
To: "Iñaki" <sip:ibc@dominio.org>
From: "Iñaki" <sip:ibc@dominio.org>;tag=pxziz
Contact: <sip:0034666555444@hackeando_mi_proxy.com>;expires=1800
Ahora llamo (como antes) a sip:ibc@dominio.org y el proxy SIP obtendrá de su base de datos sip:0034666555444@hackeando_mi_proxy.com. No es una IP, por lo que antes de rutar el paquete tendrá que hacer una resolución DNS siguiendo el estándar "RFC 3263 - Locating SIP Servers".
Dicha resolución acabará devolviendo la IP 1.2.3.4, por lo que nuevamente hemos vulnerado la seguridad de nuestro proxy y obtenido llamadas gratuitas a la PSTN.
¿Entonces qué?
Una solución horrible es la de impedir dominios en el URI del "Contact", con lo que habríamos resulto el problema... a costa de verter heces sobre el RFC 3261, ya que el URI del "Contact" debe permitir hostnames/dominios. :(
Otra solución es permitir dominios en el "Contact" pero establecer que el gateway sólo admita INVITE con IP en el host del RURI (y no dominios o hostnames):
INVITE sip:0034666555444@1.2.3.4 SIP/2.0
y que rechace cosas como:
INVITE sip:0034666555444@hackeando_mi_proxy.com SIP/2.0
- En el caso de Asterisk esto se consigue añadiendo en "sip.conf":
allowexternaldomains=no
domain=1.2.3.4
El resto de soluciones no me apetece explicarlas aquí porque todavía las estoy digeriendo, así que os remito directamente al hilo de la lista.
Especial mención para las respuestas de Klaus y de Juha Heinanen.