Hace unas semanas creamos una pagina web desde la que podíamos comprobar si nuestro Asterisk era vulnerable a INVITES externos sin autenticación. Por la cantidad de emails que recibí tanto de usuarios de España como los de otros países, ví que una gran cantidad de usuarios admitían paquetes INVITES sin autenticación.

Por lo general, esto no es en absoluto erróneo, entra dentro de la filosofía de la VoIP que podamos admitir llamadas anónimas desde otros sistemas para poder ponerlas en contacto con usuarios que tengamos registrados en nuestro Asterisk, pero conociendo la cantidad de usuarios que permiten esto (apenas un 5%), el resto se podría considerar que utilizan un interfaz web como FreePBX que configura por defecto el famoso parámetro ‘allowguest=yes’ en lugar de rechazarlo.

Asterisk 1.4 y 1.6 también configuran por defecto este parámetro, pero por supuesto es responsabilidad de cada uno conocer el significado de estos parámetros y actuar en consecuencia.

Durante una charla/debate/brainstorming que tuvimos en el último curso de Asterisk Advanced en Bilbao, aparecieron algunas ideas bastante interesantes y que nos gustaría compartir desde aquí:

  • Utilizar la aplicación ‘Authenticate’ con un código PIN conocidos por todos los usuarios y que se ejecute antes de hacer una llamada internacional:

Por ejemplo, algo como esto:

exten => _00X.,1,NoOp(Calling International number: ${EXTEN})
exten => _00X.,n,Authenticate(0173)
exten => _00X.,n,Dial(SIP/${EXTEN}@InterProvider)

Esto ya haría que el usuario llamante que envía dicha llamada, necesite conocer nuestro código de autentificación (0173) para poder realizar dicha llamada. Este código deberán conocerlo todos los usuarios y, aunque retrase un poco el establecimiento de la llamada por tener que marcar 4 números más, seguro que el hecho ampliar dicha seguridad es algo que merece la pena hacer.

  • Evitar el acceso externo del 5060 mediante el propio firewall de Linux:

Este, sin duda es el que menos me gusta, ya que es muy interesante poder recibir llamadas a nuestros usuarios sin necesidad de tener que llamarles vía red telefónica.
Es decir, si yo desde mi softphone llamo a: SIP:jackoman@asterisk.jackoman.com suene correctamente la extensión de mi amigo sin tener que llamarlo al móvil o a su número fijo.
No obstante, si cierro el puerto 5060/UDP vía firewall, jamás podría hacerlo algo que rompería con toda la filosofía de lo que es la VoIP y una de sus principales ventajas. 🙁

  • Una configuración adecuada del dialplan:

Generalmente este es el principal error, las llamadas entrantes sin autentificar en el SIP.conf son dirigidas al contexto ‘default’ del extensions.conf.
Si el extensions.conf NO lo hemos configurado como nos han enseñado, podríamos llegar a tener algo como esto:

[default]
exten=>s,1,NoOp(Llamadas desde el exterior)
exten=>s,n,Dial(SIP/100,20)
exten=>s,n,VoiceMail(100,u)

include=>salientes ;; <<<< MUY MAL! Añadimos el contexto ‘salientes’ dentro del ‘default’

[salientes]
exten=>_1XX,1,Dial(SIP/${EXTEN})
exten=>_9X.,1,Dial(DAHDI/g1/${EXTEN})
exten=>_00X.,1,Dial(SIP/${EXTEN})    ;; <<<<< Esto es lo que hará que puedan hacer llamadas desde fuera.

De esta manera, nuestro sistema estará completamente configurado para que cualquier persona pueda llamar a costa nuestra a donde quiera. 🙁

Ante esto, un consejo… NUNCA utilizar ‘includes’ si no sabemos exactamente qué estamos haciendo.

Existen muchas otras soluciones para hacer que nuestra seguridad se refuerce un poco, aunque existe un problema mayor:

Los usuarios maliciosos incluso se autentifican y registran en nuestro sistema para hacerse pasar por una extensión con permisos y poder hacer llamadas como un usuarios normal y corriente.

Ante esto ¿qué podemos hacer?. Pues está claro que lo primero es mejorar la seguridad básica:

  • La típica extensión 100 con contraseña 100, es tan vulnerable como no poner ninguna contraseña, por lo que debemos cambiarla a algo más robusto: algo como eLnsAaLiyÑ100.  (la ñ y la ç son letras muy útiles para las claves)
  • Cuando estos usuarios intentan registrarse desde nuestras propias cuentas, utilizan un sistema de ‘fuerza bruta‘ para buscar las contraseñas, así que de poco nos servirá algo como esto: Usuario 100, contraseña 100100, ya que tan solo van a necesitar un par de horas de intentos para conseguir registrarse y empezar a hacer llamadas.
  • Evitar a toda costa eso que hacen los interfaces de configurar todas las extensiones como nat=yes, este parámetro sólo debe estar para aquellas extensiones que realmente se encuentren detrás de NAT que realmente son las más vulnerables.

No obstante, durante el curso de Asterisk Advanced aparecieron varias ideas más entre las que había una que no me disgustó:

  • Comprobar en el log del Asterisk los intentos fallidos de autenticación y en el caso de varios intentos, añadir de forma automática en el IPTables la dirección IP de nuestro ‘supuesto’ atacante.

Lo de ‘de forma automática‘ es imprescindible, ya que los ataques suelen producirse cuando nuestro sistema es más vulnerable: los fines de semana, de forma que no les prestemos atención a los logs hasta que el administrador de sistemas vuelva el lunes, de esta forma los atacantes tienen varios días para su ataque por fuerza bruta.Así que,  analizando el log y documentándonos un poco vimos que Asterisk loguea los intentos fallidos de registro SIP como mensajes de tipo NOTICE (algo que viene por defecto en el logger.conf y que nos permite monitorizar quien se ha intentado registrar casi siempre).

A la vista de esta última idea, desarrollamos  un script que, añadido al crontab, analizaba el archivo ‘messages’ del Asterisk en busca de intentos fallidos y cuando este número superase una cantidad considerable, el script añadiría dicha IP en el IPtables para que el sistema le prohibiese acceder al puerto 5060/UDP.

El script lo podéis encontrar aquí y para activarlo, tan sólo tenéis que copiarlo al directorio /usr/local/bin y llamarlo cada cierto tiempo en el crontab editando el archivo /etc/crontab y añadiendo una línea como esta:

00 *     * * *    root   /usr/local/bin/sipcheck.pl messages

De esta forma, evitaremos que un atacante pueda conocer la contraseña de nuestras extensiones que están detrás de nat y pueda hacer llamadas internacionales a través nuestra.

Por defecto, el número de intentos fallidos antes de ser añadido automáticamente al IPTables es de 200, suficientes para detectar un ataque por fuerza bruta sin que añada extensiones que han fallado por escribir mal la contraseña. Este número se puede cambiar dentro del código.

Las direcciones IP atacantes se añaden al firewall ya existente, permitiendo “limpiar” estas direcciones con el parámetro ‘clear‘ sin que afecte al resto de la configuración del IPTables.

Por supuesto, se le pueden hacer muchas mejoras, pero de momento, esta primera versión servirá para aquellos que quieran asegurar su sistema un poco más.

Si te gusta el script y lo quieres mejorar, acuérdate de enviarme los cambios para que pueda servir a otras personas (para eso es GPL).

El script lo podeis descargar de aquí: sipcheck

Únicamente nos falta agradecer a los asistentes al curso de Asterisk Advanced Bilbao 2010 por ese BrainStorming antes de quedar para cenar que fomentó hacer el script que ha conseguido que en algunos sistemas conocidos donde instalé este script para pruebas, ya haya capturado varias direcciones IP. ;D

11 Comentarios

  • […] This post was mentioned on Twitter by kore dump, Sinologic. Sinologic said: Nuevo artículo: SIPCheck: Vigila quien intenta registrarse en tu Asterisk http://bit.ly/aCbbb8 #asterisk #sip #security […]

  • Buena idea. Gracias

  • Hola Elio,

    Yo implementé hace un mes más o menos algo parecido pero enfocado a varias Asterisk distribuidas en varios sitios.

    Hace un par de meses empezé (no se cuando acabaré 🙂 a implentar OSSIM. Dentro de esta macro aplicación está OSSEC(HIDS) y con esto lo que consigo es detectar este tipo de ataques (y más), generar una alerta y enviar un comando iptables al agente(asterisk) correspondiente. Está claro que si tienes una asterisk no vas a montar un tinglado como este pero si tienes varias y ademas quieres proteger otro tipo de servicios (correo, proxy, routers etc) creo que es buena idea.

    Si te interesa me comentas

    Saludos

  • @Miguel: gracias! 🙂

    @Javi: Es interesante, sobre todo para poder crear un sistema de alarma general que active los firewalls de distintos servidores o incluso enviarle comandos al router para corte el acceso a cualquier punto de la red interna.
    Sé que esta no es la mejor forma ya que existen sistemas mucho más completos y seguros (mira por ejemplo el honeypot que está haciendo http://bytecoders.homelinux.com/, pero esto es un simple script para evitar el “peligro inminente” cuando apenas tenemos ningún sistema de seguridad. 😀

  • Lo que hace ese script lo puede hacer también fail2ban y de hecho se usa del mismo modo para el SSH por ejemplo, ya tiene programado un plugin para Asterisk y la ventaja es que además se puede configurar para que después de un tiempo determinado quite el bloqueo a la IP, además de otras cosillas útiles:

    http://www.fail2ban.org/

  • Para este tipo de cosas viene muy bien Fail2Ban (http://www.fail2ban.org/wiki/index.php).

    Es un programita en python que se encarga básicamente de mirar logs y añadir al iptables las ip’s que aparecen en los logs. Lo mejor es que se pueden crear nuestras propias expresiones regulares para indicarle en un log concreto, qué tipo de log queremos hacer que salte, y baneé la ip.

    Por defecto Fail2Ban se usa con ssh, pero viene con expresiones regulares para apache, postfix, vsftpd…

    Pero lo que aquí interesa es que ha habido alguien que se ha encargado de hacer la expresión regular para el asterisk, la podéis ver en http://www.fail2ban.org/wiki/index.php/Asterisk y tal como podéis ver hace lo mismo que el script vuestro.

    Os recomiendo probar el fail2ban, que viene muy bien para este tipo de cosas.

  • Para un solo asterisk escuchando en ip pública creo que esto es bastante sencillo de implementar y efectivo.

    Se me ocurren un par de ampliaciones puñeteras:

    1: Al intento X, en vez de bloquear la ip redireccionamos las peticiones a un fake_asterisk que sí admite todo tipo de registros y llamadas. Todas las llamadas ejecutan un playback “Esta es una llamada fraudulenta. Se ha notificado a las autoridades bla bla bla”.
    Leí hace poco que a veces era mejor hacer un fake-ok que rechazar automáticamente. Porque estos bots no paran hasta recibir un ok. Además, es divertido 🙂

    2: Que el script mande las ips bloqueadas a una lista pública que opcionalmente puedan descargar y blacklistear los que están usando el script. Supongo que ya hay de eso pero no estaría mal que pudieses tener una lista de ips que han bloqueado otros.

  • Hola, Elio.

    Interesantes las recomendaciones de esta entrada. Hace algunos días estuve también experimentando algunos ataques por fuerza bruta y bajo este escenario tal vez se pueda usar como alternativa al script que aquí presentás algo que existe hace algún tiempo llamado fail2ban:

    http://www.fail2ban.org/wiki/index.php/Main_Page

    De hecho, si usás Debian GNU/Linux, está en los repositorios.

    Saludos.

  • @donpimpon, @yuki, @daniel: si, el fail2ban también hace eso, de hecho hay cientos de aplicaciones que hacen lo mismo 😀 (podeis verlo en freshmeat), de hecho sé que son mucho más completas y monitorizan muchos más servicios (http, ssh, ftp, etc..) 😀

    No obstante, este script es bastante más sencillo y orientado para Asterisk, bien fácil de modificar y nos permite de una manera sencilla configurarlo para adaptarlo a lo que nos interese, además nunca está de más tener algo ‘extra’, sobre todo pensando en bastante gente que utiliza fail2ban y que les han colado llamadas igualmente. 🙁

    @Manwe: Me han gustado las dos ideas, de hecho la segunda ya se me ocurrió, lo único que no sé hasta qué punto le gustará a la gente que el script envíe datos para informar públicamente de las direcciones IP vulnerables y desde donde provienen los ataques.

  • Me ha encantado la parte que dice NUNCA utilizar ‘includes’ si no sabemos exactamente qué estamos haciendo.
    Rayos! Quién no ha metido la zarpa con un include.
    Bueno tal vez nadie, pero yo si 🙁

  • Excelente aporte me encanto el articulo y cada uno de los comentarios que hicieron cada uno de los compañeros felicidades

Archivos

© 2014 Sinologic, inc. All rights reserved.

Menú

Redes sociales