Pages

Thursday, June 6, 2013

¿Dónde dejo mi bind shell?


Realizando auditorías internas me he encontrado diversas ocasiones en la que consigo shell en equipos supuestamente localizados dentro de la DMZ de la organización pero de los que desconozco su exposición al exterior. Digo supuestamente, ya que, algunas de estas auditorías tienen un enfoque black-box y por tanto desconozco al completo la topología de la red así como los dispositivos y reglas de networking configuradas en la misma. Si el número de VLANs y subredes es elevado, no es trivial conocer si las máquinas comprometidas tienen acceso desde el exterior.

A veces los servicios y conexiones de la máquina (netstat -anput), ficheros de log, etc. ofrecen pistas sobre la exposición de esa máquina hacia afuera. Así, por ejemplo, si la máquina tiene un Apache corriendo en el puerto 80 y el mismo aloja la Web de la organización se deduce que la misma es alcanzable desde el exterior (algo que podemos corroborar mirando sus logs y conexiones) y que es altamente probable que dicha VLAN tenga otras máquinas con servicios públicos. Sin embargo, en otras ocasiones no es tan claro conocer este hecho. Incluso en el caso del servidor Web lo único que sabemos es que el puerto 80 está expuesto, pero, ¿y el resto de servicios?

Conocer esta información es útil si lo que queremos es dejar una bind-shell escuchando en un determinado puerto para acceder posteriormente a la máquina desde el exterior. Pero, en este caso se presentan dos dudas.

  1. Qué IP pública hace forwarding a los servicios de dicha máquina.
  2. Qué servicios (puertos) son alcanzables desde el exterior hacia dicha máquina.

Contestando a la primera pregunta, uno podría pensar: «fácil, haciendo una petición a servicios como ifconfig.me, icanhazip.com o similares» conseguiríamos la IP pública. Desde la propia línea de comandos podemos conseguir esto con un poco de VisualBasic (o desde Metasploit con el módulo auxiliar auxiliary/gather/external_ip). 




Aunque esto es correcto, no es suficiente.  Con este dato lo único que conocemos es la IP pública para el tráfico saliente (Output). Sin embargo, ¿qué tipo de NAT está llevando a cabo el router/firewall? ¿Dicha IP es estática o bien dinámica? ¿Es elegida aleatoriamente de un pool de direcciones públicas? ¿Dicha IP hace forwarding a nuestra máquina cuando se trata de tráfico entrante (Output)? ¿Está utilizando Static Inside PAT? Para hacernos una idea de las posibles configuraciones que puede ofrecer un router/firewall véase a modo de ejemplo la siguiente tabla. En ella podemos ver algunas de las configuraciones NAT que soporta un Cisco ASA:

Book: CCNP Security Firewall

Veamos de forma gráfica alguna de estas configuraciones.




En el gráfico anterior se ha configurado Static Inside NAT. La organización cuenta con un pool de unas 30 IPs "públicas" (imaginando que la red  10.0.0.0/24 es pública). Dos de estas IPs han sido configuradas como Static Inside NAT; configuración típica en organizaciones que necesitan acceso desde el exterior y que disponen de suficientes IPs públicas. De esta forma, para alcanzar el servidor Web desde el exterior necesitaríamos apuntar a 10.0.0.20

Veamos ahora la versión Static Inside PAT. Cuando la organización no cuenta con suficientes IPs públicas suele implementarse esta configuración al permitirnos jugar con los puertos para hacer forwarding a diversas máquinas internas. Así, una única IP pública podría redirigirnos a múltiples máquinas internas en función del puerto destino de la conexión. En la figura únicamente el servidor Web será alcanzable con peticiones a la IP externa 10.0.0.20 con puerto destino 8080.



Como vemos, debido a la cantidad de configuraciones NAT/PAT que pueden implementarse, no es trivial conocer desde qué IPs y puertos es alcanzable nuestra máquina; lo que complica nuestra idea de dejar escuchando una bind shell.

Pero incluso conociendo la IP pública, no basta con hacer un escaneo externo para nuestro propósito. Los puertos marcados como closedfiltered no sabemos si son consecuencia del filtrado del Firewall o de la propia máquina. De hecho un Firewall en condiciones debería implementar una política restrictiva (deny all) y permitir únicamente tráfico dirigido a puertos abiertos en los que corren servicios públicos, además de implementar contramedidas ante este tipo de escaneos.

  • Nota: Remarco lo de "abiertos" ya que en ocasiones escucho el argumento de que no pasa nada si no se "capa" un puerto en el Firewall externo si el servicio de la máquina al que va dirigido está closed. A parte de la más que evidente brecha de seguridad de dicha configuración, si se echa un ojo a vulnerabilidades como MS11-083, (en la que es posible ejecutar código mediante una serie de mensajes UDP sobre puertos closed ) podemos encontrar razones más que suficientes para tirar por tierra dicho argumento.

Continuando con nuestro objetivo y a raíz del título del post me gustaría comentar un pequeño trick que suelo utilizar para localizar tanto la IP pública de la máquina así como los puertos accesibles desde el exterior. Si bien la opción más rápida sería descargarse herramientas como rawcap y capturar paquetes a la vez que escaneamos el equipo desde el exterior (para así deducir que puertos son alcanzables y cuales no), podemos optar por una solución "menos ruidosa" con el firewall avanzado de Windows.

Lo interesante del firewall de Windows son sus capacidades de logging, al permitirnos no solo generar un log de las conexiones permitidas sino de las  denegadas también (opción droppedconnections); siendo estas últimas las que nos permitirán deducir reglas de filtrado incorrectas en el Firewall. 


Una vez preparado el fichero de log, únicamente necesitaríamos escanear la IP externa asociada a nuestra máquina; pero, ¿Qué IP? Si no tenemos ninguna pista sobre el tipo de NAT/PAT asociada a nuestra máquina, el único enfoque es utilizar todo el rango de IPs públicas.

Supongamos, por ejemplo, que el pool de direcciones públicas de la organización es una clase C. Nuestra máquina tiene algunos servicios abiertos y sospechamos que puede tener algún tipo de acceso desde el exterior. Para ver si es alcanzable ejecutamos el siguiente script:


Ya que el log generado por el firewall de Windows registra también el puerto origen de la conexión (o del intento de conexión) utilizaremos  la opción --source-port de Nmap para conocer desde que IP pública fue alcanzado. Para ello utilizaremos como puerto origen el octeto de la IP que representa el host + 1024 (el motivo de sumarle 1024 es para evitar algunas reglas de filtrado que bloquean conexiones con puertos por debajo del 1024 en el tráfico entrante). Puede verse más claro en la siguiente captura. 


Una vez finalizado el escaneo podremos comprobar que puertos fueron alcanzados así como la IP pública afectada. 


En nuestro caso, podemos deducir del log que los únicos puertos alcanzables desde el exterior (al menos del rango especificado) fueron el 445 y el 3389. El recuadro rojo sería la IP pública desde la que realizamos el escaneo. Probablemente una mala praxis del administrador permitió el tráfico entrante al puerto 3389 para el acceso por terminal server a ciertas máquinas. Sin embargo, no restringió correctamente a que máquinas hacer forwarding, conviertiendo dicho puerto en el candidato perfecto para nuestra bind shell.


Gracias a la opción --source-port podemos deducir también que la IP pública implicada en dicha regla de  forwarding fue la  X.X.X.32 (1056-1024), por lo que para acceder a nuestra shell solo necesitamos hacer un nc X.X.X.32 3389 (desactivando previamente el firewall o creando la regla oportuna).

En el caso de tener una entrada en nuestro log con un puerto destino diferente a los utilizados en nuestro script, es probable que el firewall externo esté utilizando Static Inside PAT por lo que únicamente tendríamos que ir probando cada uno de los puertos asociadas a dicha IP para conseguir la regla de forwarding. Además, es probable que tengamos que jugar con las opciones de Nmap en función del tipo de firewall implementado.

He aquí un motivo más por el que filtrar closed ports en el Firewall.
Si aun así, ninguno de estos métodos nos vale, siempre podremos usar una reverse shell.


No comments:

Post a Comment