Archivo de la categoría ‘Artículos’

Seguridad: Sniffing. Capítulo Segundo-> Protocolos IP, DNS, TCP/UDP y Ethernet/ARP

ATENCION: Los ejemplos que se van a mostrar y “tutoriales” tan solo tienen carácter educativo. En ningún aspecto comparto filosofías de invasión a la intimidad, ataques contra un sistema informático o cuestiones similares. En la medida que sea posible siempre se usarán ejemplos y formas que puedan ser usados por cualquier persona, de forma que pueda verificar los contenidos escritos. No obstante, por motivos más que obvios, materiales como contraseñas, nombres de usuarios o de hosts, serán omitidos o modificado en las capturas de pantallas realizadas (o las lineas escritas). Es decir, los ejemplos serán completamente reales, los datos mostrados a vosotros necesarios para poder pertrechar estos ejemplos no siempre lo serán (Sí lo serán los resultados). Para que esto conste de forma clara, todo material sensible modificado o falso estará resaltado en ROJO. Por motivos de seguridad, todo el material que sea expuesto aquí (exceptuando software propietario o libre, citaciones expresas o código de terceros) tanto texto, imágenes y código son propiedad del autor y está completamente prohibido su reproducción completa o parcial en otros lugares, espero que se comprenda.

 

Protocolos ARP, IP, DNS y TCP/UDP

Internet como estructura básica está muy bien, pero es necesario así mismo una serie de protocolos que haga posible la comunicación entre distintos dispositivos interconectados por todo el mundo. Imaginemos dos personas, una en España y otra en Francia, una habla español y la otra francés. Para comunicarse hacen uso del teléfono ordinario, lo cual hace que puedan hablar de forma simultánea, en tiempo real y de forma eficaz. Pero si habla cada uno en un idioma diferente será imposible que se entiendan. Es decir, es necesario una serie de protocolos, de normas, de… para que todos entiendan correctamente todo. Vamos a tratar quizás los más importantes de ellos de cara a nosotros, no significa que no existan otros protocolos igualmente importantes o imprescindibles, pero estos son los que para nuestra tarea es importante conocer bien:

  • IP
  • DNS
  • TCP/UDP
  • Ethernet/ARP

Hay que tener presente que estos protocolos no nacen de la nada, nacen de la necesidad de crear comunicaciones fiables, que perduren en el tiempo, que sean eficaces y simples en la medida que sea posible. Comencemos entonces.

 

 

Protocolo IP

Las siglas IP provienen de “Internet Protocol” (Protocolo de Internet), no obstante esto puede ser confuso, dado que el término IP puede hacer referencia a la suite de protocolos IP que hacen posible el modelo TCP/IP, o incluso podemos referirnos muchas veces a IP para designar una “Dirección IP”. Pero detrás de todo ello, IP en sí no es más que un protocolo más que hace posible el modelo TCP/IP, aunque por supuesto pueda ser uno de los más importantes en todos ellos.

El objetivo del protocolo IP es poder entregar/recibir paquetes (recordemos que en el nivel 3 del modelo OSI, nivel de red, la unidad de información se denominaba paquete) a/desde diferentes orígenes y destinos, de modo que cada paquete tenga un origen y un destino claro. Dicho de otro modo, es el protocolo que indica el host al que se debe de enviar el paquete o el host que lo está enviando. Aunque la referencia más inmediata que solemos tener del protocolo IP es el aspecto de una dirección IP, no podemos olvidar como se hace esto posible o que significa eso que se conoce como dirección IP. Actualmente, existen dos especificaciones diferentes para el protocolo IP, aunque sería más correcto hablar de versiones diferentes. Una es la que aún se encuentra como uso mayoritario, posiblemente copando el 98% de todo Internet a día de hoy y conocida como IPv4. La segunda aun en expansión y de implantación muy lenta desde hace ya muchos años su sucesora, IPv6.

 

IPv4

Quizás la diferencia más señalada de estas dos versiones tiene relación directa con el espacio de direcciones que soporta cada una de estas. De este modo, el protocolo IPv4 permite tan solo direcciones IP de 32 bits, lo que quiere decir que aun si se pudiese asignar una a una todas las direcciones de forma independiente (aunque esto no funciona así), “tan solo” se tendrían disponibles un total de 4.294.967.296 direcciones diferentes. 4 Mil millones de direcciones pueden parecer suficientes si tenemos en cuenta que el planeta cuenta con una población aproximada de unos 6 mil millones de habitantes. No obstante el crecimiento de los dispositivos a la red ha tenido en los últimos años un aumento exponencial. Ni siquiera las tecnologías de traducción de direcciones como NAT, el uso por parte de los ISP de direcciones IP dinámicas o los espacios IP reservados para redes privadas son suficientes para evitar el agotamiento de direcciones IPv4, lo que ha producido que a día de hoy el espacio de direcciones IPv4 esté literalmente agotado. Si los datos son ciertos, y parece que lo son, a día de hoy la ICANN habría ya entregado el último paquete de direcciones IPv4, estando por tanto disponibles tan solo los paquetes de direcciones IP gestionados por los propios gobiernos regionales. Estamos en el año 2010, y parece que con toda seguridad en uno o dos años todo el espacio de direcciones esté completamente agotado.

¿Qué es una dirección IPv4?

Casi con toda seguridad, cualquier lector que pueda estar leyendo estas letras habrá visto alguna vez una dirección IPv4, la cual no es otra que un número dividido en 4 octetos. En realidad, la división de ese número de 32 bits en 4 octetos es meramente una cuestión de comodidad a la hora de poder trabajar con ellos, es por ello que no se suele usar la notación hexadecimal siquiera, la cual tendría más sentido dado que acortaría la dirección a la hora de recordarla y/o escribirla:

11000000

10101000

00000000

00000001

C0

A8

00

01

192

168

000

001

La representación clásica de estas direcciones es por tanto la separación de cada octeto con un punto: 192.168.0.1

Hemos dicho anteriormente que no era cierto que en un espacio de direcciones IP de 32 bits se pudiesen tener otorgar 2^32 direcciones diferentes. El sistema de dirección IPv4 reduce considerablemente este número debido a su propio funcionamiento, como por ejemplo direcciones reservadas, subredes, direcciones broadcast…

En realidad, una dirección IP no identifica tan solo el host origen/destino, sino también la subred a la que pertenece. Históricamente se utilizó la misma división de los octetos como divisiones entre redes y host, de este modo se podía usar el primer, segundo y tercer octeto para la identificación de las redes, y el segundo, tercero y cuarto octeto para la identificación de los host. De este modo por ejemplo, si pudiésemos disponer de todo el espacio IPv4 para nosotros podíamos utilizar tan solo el primer octeto para identificar una red concreta y el resto de los 3 octetos para identificar los host. Es decir, podríamos constituir un máximo de 256 redes diferentes, cada una de ella con 2^24 hosts. Recordemos que un octeto son 8 bits, 256 valores diferentes. Pero si lo que necesitásemos sería tener muchas redes y pocos host podríamos del mismo modo hacerlo al revés, tener 2^24 redes diferentes y cada una de ella con 256 hosts.

A día de hoy esta práctica es normal encontrarla en redes simples, pero esto no es en modo alguno una norma, y es posible usar el número de bits que se desee tanto para el número de las redes como el número de los hosts, es decir… podemos poner un punto de separación virtual en cualquier lugar de los 32 bits de una dirección IPv4. Es por ello que se requiere de un sistema o de algún identificador que diga que parte será la usada para una tarea y para la otra. Y es cuando aparece la “Máscara de subred”. Se llama máscara porque realmente lo que hace es enmascarar los bits que se usarán para cada tarea. Básicamente se realiza una operación AND lógica entre la dirección IP origen/destino y la máscara de subred. Aquellos bits que son cero serán los que identifican el host, y el resto estará indicando exactamente la subred. La única restricción es que los bits usados para una cosa o la otra deben ser consecutivos, no se pueden intercalar bits para ser usados como subred/host. Visto esto, supongamos que tenemos la misma IP ejemplo anterior:

11000000 10101000 00000000 00000001 -> Dirección IP binaria del host, correspondiente a su notación decimal: 192.168.0.1
11111111 11111111 11111111 00000000 -> Máscara de Subred, correspondiente a su notación decimal: 255.255.255.0
—————————————————- -> Operación Lógica AND
11000000 10101000 00000000 00000000 -> Red: 192.168.0 Host: .1 (192.168.0.1)

Otra forma común de expresar la máscara de subred es utilizando una barra inclinada después de la dirección IP especificando el número de bits que se han otorgado para la identificación de la subred. Por ejemplo, continuando con el ejemplo anterior:

IP: 192.168.0.1
Máscara: 255.255.255.0

Podríamos expresarlo como:

192.168.0.1/24 dado que en realidad son 24 bits los que han sido usados para la subred. En este caso el esquema coincidirá con la separación de la subred/host por los octetos, pero como hemos dicho, la máscara podría haber sido perfectamente 255.255.255.240.0 -> 192.168.0.1/20 lo que significaría que la parte de la red es identificada por 20 bits.

¿Por qué es tan importante tener configurado correctamente esta máscara? Los nodos de red como los routers necesitan conocer a quien enviar cada paquete. Para hacer esto el router tiene que mirar en sus tablas de rutado, de este modo puede identificar la subred al que pertenece el destino y enviárselo. Si la máscara de subred no es correcta, el router no dispondrá en sus tablas de rutado dicha red, y no podrá entregar el paquete.

Aunque cualquier sistema interno podría hacer uso cualesquiera del protocolo IP y de sus direcciones, este no es empleado de forma arbitraria. En teoría se podría usar cualquier máscara de subred para cualquier IP, pero la ICANN ya desde el principio (como máximo organismo que mantiene u otorga las IP) tiene perfectamente definido diferentes clases de IP y su finalidad. Podemos decir que todo el espacio de direcciones IP se encuentra perfectamente organizado en 5 diferentes clases:

Clases

Bits Primer Octeto

Rango IP

Máscara de Red

Número de Redes

Hosts/red

Direc. Broadcast

Clase A

0xxxxxxxx

1.0.0.0-126.255.255.255

255.0.0.0

126

16777214

x.255.255.255

Clase B

10xxxxxx

128.0.0.0-191.255.255.255

255.255.0.0

16382

65534

x.x.255.255

Clase C

110xxxxx

192.0.0.0-223.255.255.255

255.255.255.0

2097150

254

x.x.x.255

Clase D (Multicast)

1110xxxx

224.0.0.0-239.255.255.255

-

-

-

-

Clase E (I+D)

11110xxxx

240.0.0.0-255.255.255.255

-

-

-

-

 

Propósito

Rangos IP Reservadas

Máscara de Red

Número de Redes

Hosts/red

Direc. Broadcast

IP “Comodín”

0.0.0.0-0.255.255.255

255.0.0.0

1

16777214

0.255.255.255

Loopback

127.0.0.0-127.255.255.255

255.0.0.0

1

16777214

127.255.255.255

Enlace Local

169.254.0.0-169.254.255.255

255.255.0.0

1

65534

169.254.255.255

Sin Uso

192.0.0.0-192.0.0.255

255.255.255.0

1

254

192.0.0.255

TEST-NET-1

192.0.2.0-192.0.2.255

255.255.255.0

1

254

192.0.2.255

6TO4

192.88.99.0-192.88.99.255

255.255.255.0

1

254

192.88.99.255

Pruebas

198.18.0.0-192.19.255.255

255.128.0.0

2

131070

198.19.255.255

TEST-NET-2

198.51.100.0-198.51.100.255

255.255.255.0

1

254

198.51.100.255

TEST-NET-3

203.0.113.0-203.0.113.255

255.255.255.0

1

254

203.0.113.255

Broadcast

255.255.255

-

1

1

255.255.255.255

 

Antes de explicar algunas peculiaridades de este sistema, se hace necesario hablar ya de IP Privada Vs IP Pública

Del esquema anterior se podría inferir que la ICANN podría asignar cualquier IP o rango de estas a cualquier entidad/organización/persona que desease, pero esto no es así. No solo ya de por sí podemos ver que algunos de los rangos mostrados ya de por sí se encuentran reservados para propósitos específicos (los cuales hablaremos más adelante) y que podemos llamar como IPs Reservadas. Pero aún hay más. Con el fin de poder expandir enormemente el número de dispositivos que pudiesen conectarse a la Red de Redes y con el fin de poder crear Redes sin necesidad de estar conectadas a Internet, surgió la necesidad de usar rangos IP reservados exclusivamente para el uso privado. A estas IPs son las que conocemos como IPs Privadas. Es evidente que por el otro lado tendríamos lo que llamamos IPs Públicas. Al contrario de los rangos IP públicas, las IPs privadas y reservadas son usadas de forma simultánea en todas partes del mundo sin constituir esto un problema, ya que dichas IPs se usan tan solo dentro del marco de una Red Privada. Dicho de otro modo, cada usuario puede si desea hacer uso de los rangos de IP Privada para crear la red que mejor se ajuste a sus necesidades. El caso de las IPs reservadas es un poco más peculiar, dado que su uso generalmente no está orientado a identificar un host concreto, sino más bien son usadas por otros servicios, los cuales como ya hemos dicho se tratará más adelante.

El uso de IPs privadas para la creación de una Red Privada es muy ventajoso, pero si se desea usar conectar dicha red privada a Internet es necesario un dispositivo (generalmente hardware) que pueda convertir de algún modo nuestras direcciones IP privadas en públicas. Y esto lo conocemos como Network Address Traslation (NAT) o traductor de direcciones de red.

Se estableció así los 3 rangos diferentes de IPs privadas dentro de todo el espacio IPv4. Es evidente que al estar reservadas estas para dicho fin, no podrán ser usados para otro. Cada rango cae dentro precisamente de cada una de las 3 clases de IP principales, de este modo cada usuario/empresa/organización puede usar aquellas que más se ajuste a sus necesidades.

 

Clases

Rango IP

Máscara de Red

Direc. Broadcast

Clase A

10.0.0.0-10.255.255.255

255.0.0.0

10.255.255.255

Clase B

172.16.0.0-172.31.255.255

255.255.0.0

172.x.255.255

Clase C

192.168.0.0-192.168.255.255

255.255.255.0

192.168.255.255

 

Es muy común por tanto hablar tanto de IP privada como IP pública. Al contrario de lo que pueda pensarse, la IP privada es la que menos importancia podría tener nuestro sistema de puertas para fuera, dado que lo que realmente identifica nuestra red desde el exterior es nuestra IP pública. Son los dispositivos de red como los routers los que hacen posible el intercambio de información entre las redes privadas e Internet.

Vamos a explicar algunas cuestiones de las clasificaciones anterior a la par que vamos a aprovechar para añadir algunos términos más:

  • IP Privada: Ya hemos hablado de ella, son rangos específicos dentro del espacio de direcciones, de uso exclusivamente propio, no tiene valor más allá de nuestra red.
  • IP 0.0.0.0: Este será la primera IP reservada que nos encontremos. La IP 0.0.0.0 es digamos la IP comodín, es decir, hace referencia a cualquier IP, ya que es necesario en multitud de tareas poder usar una IP que signifique “Todas”. Pensar en cuando se desea aplicar una regla en un firewall para permitir todas las IPs, o denegar todas. La dirección 0.0.0.0 es ese “Todas”.
  • IP 127.0.0.0: También se conoce como IP de retroalimentación, de Loopback, IP del propio host. Si la IP 0.0.0.0 hace referencia a Todas, la IP de Loopback hace referencia siempre a sí mismo. Es decir, para un equipo, sea cual sea la IP que tenga asignada él se podrá siempre identificar a sí mismo para tareas locales como 127.0.0.1. Esto es tremendamente útil, dado que no depende de la IP que pueda tener asignada para poder hacer uso de sus propios recursos de red.
  • Enlace Local: Rango de IP usado tan solo en ámbitos locales por ciertos servicios, por ejemplo por APIPA, un sistema usado para configuración automática de IP cuando otros sistemas como DHCP no están disponibles.
  • Test-NET-X: Son rangos reservados para ser usados en documentación y/o ejemplos didácticos, así como en código fuente ejemplo.
  • 6TO4: Con la inminente salida de IPv6, se ha reservado un espacio por el cual podrá circular contenido IPv6 hacia direcciones IPv4 y viceversa. Esto es necesario dado que no se puede implementar un sistema que sea diferente de la noche a la mañana, y durante un tiempo (posiblemente largo) ambos estándares deberán de convivir uno con el otro, ya que el soporte hardware de los dispositivos personales, así como dispositivos de red, es completamente necesario. Este rango será usado para facilitar esta tarea.
  • ID de Red: Si uno es cuidadoso y realiza las multiplicaciones por sí mismo, se dará cuenta que siempre desaparecen dos posibles direcciones que podrían usarse para hosts. Es decir, por ejemplo para el rango de clase C 192.168.10.0, decimos que tenemos disponibles un total de 254 hosts para dicha red. ¿De dónde sale este número? Dado que la máscara de Red es 255.255.255.0, tan solo podríamos tener un total de 256 hosts, el último octeto es el que estaría reservado para ello. Lo que sucede es que dos de ellas podemos decir que se encuentran reservadas. En el ejemplo puesto, la dirección IP 192.168.10.0 no podría ser usada jamás para identificar un hosts, dado que dicha dirección en dicho ejemplo sería la red misma, es decir el ID de red.
  • Dirección de Broadcast: Continuando con el punto anterior, para la red 192.168.10.0 y la máscara de subred 255.255.255.0, existe otra dirección reservada conocida como dirección de broadcast. Esta dirección es muy importante, dado que es por así decirlo el canal de comunicación común de toda nuestra red. Esta dirección es siempre el último host de la red, en este caso sería 192.168.10.255. Pero que es ¿Broadcast?

    Existen diferentes modos de comunicación entre diferentes dispositivos. Quizás el método más simple sería aquel en el que un host mantiene una comunicación directa con otro hosts. En este caso hablaríamos de Unicast. Pero es posible que el hosts con el que queremos entablar una comunicación no sea siempre el mismo, sea tan solo uno pero dependiendo de ciertas circunstancias pueda ser uno u otro, por ejemplo en función de la distancia entre ambos. La comunicación sería de nuevo tan solo entre dos hosts, aunque el destino no tendría que estar específicamente tipificado. En este caso estaríamos hablando de Anycast. Unicast y Anycast es posiblemente los dos sistemas de comunicación más usados, pero muchas veces se puede tener la necesidad de tener que enviar un mensaje a más de un hosts. Así, por Multicast entendemos un sistema de comunicación de uno a muchos, en el que esos muchos forman entre ellos un colectivo propio dentro de la misma red por supuesto. Por último, podemos desear poder enviar o comunicarnos con todos los hosts de nuestra red, en un esquema de “Uno a Todos”, y es lo que llamamos Broadcast. Un ejemplo sencillo de broadcast es la televisión, sale de un emisor pero el receptor somos todos, no va dirigida a nadie en particular, y el ejemplo más común de multicast podría ser los servicios de televisión por internet.

    Visto esto, comprendemos el significado de la dirección broadcast de nuestra red, dado que muchos mensajes son necesarios emitirlos a todos los miembros de nuestra red, ya sean informativos o con simples fines distributivos. Podemos decir por tanto que el último host de una red, queda también reservado y no puede ser usado como un host concreto.

  • Subred: En realidad el término “Máscara de Red” sería tan solo aplicable a la máscara por defecto de una IP según su clase. Por ejemplo, la máscara de red para una IP de clase C será 255.255.255.0. Esto es importante, dado que no se debe de confundir con una Subred o una Máscara de Subred. Según la clasificación anterior, se podría pensar que no hay necesidad de subredes, dado que el espacio ya está dividido en diferentes clases que se amoldan a la gran mayoría de todos los interesados. Es cierto que la ICANN jamás otorgaría una IP de clase A a un particular, dado que sería una pérdida absurda de direcciones IP, ningún usuario particular tendría la necesidad de crear una red de 16777214 dispositivos. Al contrario, la ICANN tiene (solía asignar, dado el agotamiento de estas) asignado tan solo IPs de clase A a los propios gobiernos de cada país o a grandes empresas/organizaciones, la mayoría de ellas por razones históricas, como Intel, MIT… Hay que tener en cuenta que la ICANN tan solo disponía de 126 paquetes de direcciones de clase A. Por el contrario la ICANN asignaba IPs de clase B a grandes empresas y organizaciones de forma común, pensar que en este caso ya no disponía de tan solo 126 paquetes, sino 16380. Y por último los paquetes de clase C que serían los que podrían ser otorgados a particulares.

    Aunque este reparto pueda parecer suficiente, lo cierto es que no lo es. Según esto, si un particular recibiese por parte de la ICANN un red de clase C con sus 256 IPs, por ejemplo la red 193.125.222.0, el usuario tan solo podría tener una red con 256 hosts. Pero qué pasa si el usuario quiere tener 2 redes diferentes en vez de tan solo una? No podría. En cambio, podría tener un router en la entrada de su red, con una máscara de subred de 255.255.255.192, lo cual me daría la posibilidad de tener 4 subredes distintas, cada una de ella con 62 (64 menos el ID de red y la dirección de broadcast). Así, la dirección IP 193.125.222.2 pertenecería a la subred 1, mientras que la IP 193.125.222.130 pertenecería a un host en la subred 3.

    De este modo, la creación de subredes es el método más eficiente para la gestión de las propias IPs. Es evidente que nunca podremos trabajar con máscaras más pequeñas que la máscara por defecto que tenemos, pero si podemos trabajar con máscaras más grandes para seccionar y optimizar la red.

  • Clase D: Las direcciones de clase D están reservadas para usarse de manera interna para propósitos de multicast. Ya hemos explicado esta técnica, pero como saben los dispositivos que dirección multicast escuchar? Lo normal es que antes de que esto sea posible, un host tiene que realizar una petición de unión a un grupo multicast, petición que realizará a través de una dirección multicast. Después de esto, el dispositivo de red (generalmente un router) reenviará el mensaje de él o para él al resto, dado que el conoce quienes son todos los miembros del grupo multicast.
  • Clase E: Tan solo se puede decir que es un rango de IP reservado para poder hacer pruebas, experimentos…. o simplemente para futuros usos.
  • IP 255.255.255.255: Esta IP sería algo así como la dirección de Broadcast para redes no constituidas. Si comprendemos que la dirección 0.0.0.0 es la dirección IP que hace referencia a cualquier hosts, la dirección IP 255.255.255.255 sería su IP de broadcast, siempre por supuesto hablando dentro de una red local, una red privada.

 

A pesar del uso de direcciones IP privadas con dispositivos NAT y al excelente trabajo de gestión de la ICANN para aprovechar al máximo las direcciones IPv4, ha sido muy normal el uso de direcciones IP dinámicas. Esto no es más que una práctica de los ISP para asignarnos IPs que podríamos llamar de “sesión”. Es evidente que jamás todos los clientes de un mismo ISP estarán conectados a la red de manera simultánea, luego sería un desperdicio de IPs. Imaginar que un ISP tiene arrendado un paquete de un millón de IPs y tiene un millón de clientes, luego asigna una a cada uno de ellos y problema resuelto. Pero como hemos dicho es evidente que esto no será jamás así, y a lo mejor las estadísticas dicen que en el mejor de los casos se forman picos de 700.000 usuarios conectados. Dicho ISP podría por lo tanto tener un paquete IPs de tan solo 700.000 direcciones, lo que le costaría sensiblemente menos. Como se gestionan estas IPs? En realidad igual que las IPs estáticas. Cuando conectamos a nuestro ISP este nos asigna una IP temporal. Dicho tiempo puede venir dado en función de la sesión o de un tiempo concreto. Una vez se da dicha circunstancia, la IP es liberada y la próxima conexión/sesión usará otra IP. De este modo si apagamos por las noches el router por ejemplo, nuestro ISP podrá reasignar dicha IP a otro cliente que quiera establecer una conexión. Por tanto, consideramos una IP dinámica aquella que varía de forma habitual con el tiempo o por conexión, e IP estática aquella que persiste. Por supuesto, el concepto aplicado a un ISP es exactamente igual que aplicado a una red local (LAN), donde la IP puede ser asignada de forma estática (por ejemplo estableciéndola en el mismo adaptador) o dinámica (por ejemplo usando servidores DHCP).

El uso de una IP dinámica o estática tiene pros y contras. Por un lado el uso de IPs dinámicas por parte de los ISP les ahorra dinero en cuanto a número de IPs necesarias, así como aumenta la seguridad y privacidad de cara al usuario, dado que su IP nunca será fija y por ende un difícil objetivo de amenazas externas. Pero por otro lado el uso de IP estáticas permite tener acceso a una serie de servicios mayores, como cualquier servicio que sea IP dirigido. Al ser la IP estática nuestro equipo/red estará siempre identificada desde el exterior, haciendo muy sencillo el uso de servidores Web/eMail o cualquier otro que nos imaginemos.

Para terminar completamente con IPv4, y dado que a estas alturas deberíamos de conocer a menos a groso modo el funcionamiento del modelo OSI/TCPIP, es interesante conocer como es un paquete IP. Recordemos que en cada nivel se encapsulará el contenido de nivel superior con el contenido añadido del nivel propio. En el caso del protocolo IP, es un protocolo de nivel 3, el cual tomará el mensaje del nivel de transporte como SDU, y le añadirá una cabecera propia, para poder así conformar el PDU del nivel 3, es decir, un paquete IP, tal y como lo encontramos en las especificaciones de 1981.

Versión

IHL

DiffServ

Longitud

Identificación

Flag

Desplazamiento de Fragmentos

TTL

Protocolo

CheckSum

IP Origen

IP Destino

Opciones (Variable)

Padding (Variable)

  • Versión (4 bits): Contendrá la versión del protocolo. Para la versión IPv4 el valor de dichos bits será 0100 (4).
  • IHL (4 bits): Es la longitud de la cabecera expresada en grupos de 32 bits. Es decir, si la cabecera tiene un total de 160 bits, 160/32 => IHL = 5.
  • DiffServ (8 bits): Originalmente usado para TOS (Type Of Service), fue sustituido en un RFC de 1998 para su uso como “Differenced Services” (Servicios Diferenciados), un sistema para QoS
  • Longitud (16 bits): Especifica el tamaño en Bytes del paquete IP completo. Al tener un campo de 16 bits podemos inferior directamente que el tamaño del paquete IP mayor que podemos tener es de 65535 Bytes (64KB)
  • Flag (3 bits): El bit de mayor peso se fuerza a cero y no es usado. El segundo bit especifica si el paquete se podrá o no fragmentar, de estar marcado como no fragmentar y es necesaria su fragmentación para enviarlo, este paquete se descartará. El bit de menor peso especifica si hay más fragmentos o no los hay.
  • Desplazamiento de Fragmentos (13 bits): A groso modo especifica el byte al que pertenece dicho fragmento. si es el primer fragmento tendrá un offset (desplazamiento) de 0, si fuese el segundo pues dependiendo ya de la fragmentación necesaria. ¿Por qué es la fragmentación necesaria? Podemos asimilarlo a la segmentación en el modelo OSI. Cada red tiene una unidad máxima de transmisión llamada MTU que precisamente especifica el tamaño máximo de un paquete. Esta es una limitación de la red, no del protocolo, esto es importante. La longitud máxima de un paquete IP es de 64KB, en cambio los enlaces Ethernet estándar suelen ser de 1500 Bytes, luego la fragmentación se puede convertir en algo “normal”. Esto significa que si se desea enviar por ejemplo una cantidad de datos de 5000 Bytes y tenemos una conexión ADSL con un MTU de 1492 bytes (cosa habitual), dicha información se deberá de fragmentar en paquetes IP más pequeños, cada paquete con un tamaño máximo (cabecera IP + datos) de 1492.

    Si atendemos a la cabecera IP expuesta arriba, cada fila corresponde a un total de 32 bits. Por tanto, la cabecera IP más corta que podríamos tener sería aquella que no se tiene el campo “Opciones”, lo que sería por tanto: 32 bits * 5 (filas) = 160 bits / 8 = 20 Bytes. La cabecera IP más larga que se puede estipular por otro lado serían 60 Bytes. Supongamos que disponemos por tanto de una Cabecera IP de un tamaño de 20 Bytes (la cabecera más simple). Si nuestra conexión ADSL tan solo puede manejar paquetes IP de 1492 Bytes significa que la cantidad de datos que pueden añadirse a nuestro paquete IP sería de 1492 – 20 = 1472 Bytes. Si deseamos enviar esos 5000 Bytes, será necesario crear paquetes IP más pequeños, en este caso un total de 4 paquetes:

    Cabecera IP 1 (20 Bytes)

    1º Cuarto SDU (Offset 0, tamaño = 1472 Bytes

    Cabecera IP 2 (20 Bytes)

    2º Cuarto SDU (Offset 1472, tamaño = 1472 Bytes

    Cabecera IP 3 (20 Bytes)

    3º Cuarto SDU (Offset 2944, tamaño = 1472 Bytes

    Cabecera IP 4 (20 Bytes)

    4º Cuarto SDU (Offset 4416, tamaño = 583 Bytes

  • TTL (8 bits): Tiempo de vida, es un contador que se establece a un número dado. Cada salto que de nuestro paquete, el dispositivo de red pertinente que procese el paquete decrecerá en uno su valor. Si el TTL llega a Cero, el paquete será descartado por la red (por cualquier dispositivo de red que lo esté procesando en ese momento). Esto es una medida de seguridad para evitar que paquetes perdidos puedan circular de forma indefinida por la red.
  • Protocolo (8 Bits): Estos 8 bytes representan un número que identifica el protocolo de nivel superior que está contenido en los datos que porta el paquete IP. El protocolo IP trabaja en el nivel 3 (nivel de red), pero los datos que maneja proceden del nivel superior 4, nivel de transporte. No obstante un paquete IP puede enviar como datos un protocolo de nivel 3 adjunto como datos, como es el caso de ICMP por ejemplo. Poner la lista completa es un poco absurdo, dado que casi con toda seguridad la mayoría de ellos jamás lleguemos a verlos en la vida. Quien lo desee puede acudir al RCF 790 para conocer la lista completa. Pero si cabe destacar los protocolos más usados:

    Protocolo = 1 -> ICMP; Protocolo = 6 -> TCP; Protocolo = 17 -> UDP;

  • CheckSum (16 bits): El protocolo IPv4 realiza una operación de checksum en la cabecera para garantizar la integridad NO EL PAQUETE COMPLETO, sino de la cabecera IP. Para ello se van sumando en complemento a uno cada 16 bits de la cabecera. Una vez terminada la suma se le realiza el complemento a uno al resultado y es este el que se inscribe en este campo. A la hora de verificarlo es igual, si el resultado obtenido (omitiendo el campo checksum) es el mismo que el que está en el cabecera, el paquete es válido.
  • IP Origen/IP Destino (32 bits cada campo) : Pues no es más que eso, la IP del sistema que envía el paquete y la IP del destino. Cabe decir que en teoría es posible modificar este dato a voluntad, lo cual deja ver lo relativamente vulnerable que es el protocolo ante el IP Spoofing (al menos en teoría)
  • Opciones y Padding (Variable, de 0 a 40 bytes): Este campo es de obligada implementación en el stack TCP/IP, pero dependerá de cada protocolo y cada paquete que sea necesario su uso o no. Es por ello la importancia del campo IHL. Si este campo tiene un valor de 5 significará que el campo Opciones no estará presente, y la cabecera tendrá una longitud fija de 20 Bytes. En cambio, el IHL pude tener un valor de entre 6-13, lo que implicará que el campo de opciones se está usando y tiene una longitud también conocida, entre 0-40 Bytes, gracias al padding final que se le añade.

    Este campo se utiliza en algunas redes por temas de seguridad por ejemplo, en el que en estos campos se indica que el contenido es considerado desde sensible a alta seguridad, o también se puede usar para indicar la fecha del paquete mismo o especifique una ruta concreta que deba de seguir el paquete.

    El Padding es simplemente un relleno que se le añade al campo de opciones para que este concluya en múltiplo de 32 bits, luego puede tener un tamaño de entre 1-31 bits, de esta forma no se rompe la estructura de la cabecera y simplemente conociendo el IHL es posible conocer exactamente el tamaño de la cabecera.



IPv6

Como se ha dicho, posiblemente la causa más urgente a solucionar es el agotamiento del espacio de direcciones IPv4. Esto es algo que era previsible no ahora, sino hace ya unos años. En 1998 se terminaron las especificaciones IPv6, y evidentemente como característica más marcada fue ampliar a 128 bits los 32 bits de las direcciones IPv4, lo que permitiría un número virtualmente infinito de direcciones. En realidad no es que sea infinito, pero de unos 4 mil millones pasaríamos a unos 3.4 x 10^38, es decir, 34 con 37 ceros a su derecha. Dicho de otro modo, se podría entregar a cada persona del mundo un espacio de direcciones miles millones… de veces superior que todo el espacio de direcciones IPv4, y eso solo para cada habitante!! Es evidente que esta será la diferencia más significativa entre IPv4, pero como veremos tampoco es la única.

Hay que tener en cuenta el por qué se clasificaron las direcciones IPv4 del modo que se hizo, y no fue otro que el de la buena gestión del espacio de este. Pero en IPv6 este problema desaparece, ya que podemos disfrutar prácticamente de un espacio ilimitado de direcciones, luego el esquema que conocemos a día de hoy se parte completamente y muchos de los conceptos y tecnologías usadas a día de hoy desaparecen… y desaparecerán en los próximos años. Como organizaríamos el espacio de direcciones IP si pudiésemos disponer de forma ilimitada de estas?

En realidad la única complejidad que tiene IPv6 frente a IPv4 es que posee unas reglas mucho más específicas de direcciones, de este modo también es más fácil tener un reparto de direcciones de forma mucho más lógico y ordenado. La idea básica que se tendrá siempre presente es que si una interfaz de red tiene asignada de fábrica un ID único llamado comúnmente dirección MAC (de 48 bits), se podría usar dicha MAC como extremo último de una dirección IPv6.

¿Qué es una dirección IPv6?

Si bien a día de hoy la penetración de IPv6 es mínima, estas direcciones comenzarán a formar parte de nuestra vida de forma bastante habitual dentro de muy pocos años. En este caso hablamos de un espacio de direcciones inicial de 128 bits, es decir, 2128 direcciones posibles. Con IPv4 la forma más habitual de representarla era por medio de 4 octetos: 4*8= 32bits en notación decimal. El problema es que si se usase el mismo esquema para las direcciones IPv6 se necesitarían 16 octetos, lo que resultaría en una dirección realmente grande de expresar:

125.223.0.25.158.231.45.0.0.0.0.0.98.250.115.23

Es evidente que no es una forma eficiente de representación. En lugar de la representación clásica IPv4, se usan 8 agrupaciones de dos octetos y en formato hexadecimal, no decimal. De este modo la dirección antes expresada podría simplificarse como:

7DDF:0019:9EE7:2D00:0000:0000:62FA:7317

A priori puede parecer que se tiene la misma complejidad, pero no es así. Para empezar 1 byte en decimal tiene una representación de hasta 3 dígitos, mientras que en hexadecimal jamás pasará de 2 valores. Además, es más cómodo la agrupación en bloques de 16 bits que de 8. Aun así, las reglas de notación se expanden precisamente para evitar la complejidad de representación, permitiendo la simplificación de estas direcciones. Por ejemplo, cuando un grupo de 16 bits posee tan solo ceros, es posible acotar los 4 en uno solo. Por otro lado, se puede si se desea omitir incluso todas las palabras (16 bits) siempre y cuando estas tengan un valor de “cero” y se encuentren contiguas entre sí. Dicho esto, de la dirección anterior podríamos simplificarla como:

7DDF:0019:9EE7:2D00:0:0:62FA:7317

Pero también podríamos representarla como:

7DDF:0019:9EE7:2D00::62FA:7317 (nótese los :: contiguos)

De este forma es posible acotar bastante la representación de estas. Pero en realidad esto tan solo es un efecto secundario de tener que manejar bloques de direcciones tan enormes. Y del mismo modo que el espacio de direcciones IPv4 se encuentra clasificado, con IPv6 sucede exactamente lo mismo, salvo con matices, dado que aquí desaparece la necesidad y los conceptos de Clases de IP, y prácticamente todas las IPs IPv6 pueden clasificarse como reservadas, de enlace local y Unicast. Pero veamos que sucede con la máscara de red/subred.

A pesar de tener un número de IPs virtualmente ilimitado, la necesidad de constituir redes independientes es evidente. El concepto de máscara de red/subred será usado prácticamente del mismo modo, aunque es cierto que de forma un tanto diferente. IPv6 pretende ser completamente jerárquico, lo que hará que sea también más eficiente a la hora de conocer el destino de un paquete (de cara a los router). Esta es la clasificación actual del espacio IPv6 según la IANA:

Prefijo

Uso

0000::/8

Reservada por IETF

0100::/8

Reservada por IETF

0200::/7

Reservada por IETF

0400::/6

Reservada por IETF

0800::/5

Reservada por IETF

1000::/4

Reservada por IETF

2000::/3

Unicast Global

4000::/3

Reservada por IETF

6000::/3

Reservada por IETF

8000::/3

Reservada por IETF

A000::/3

Reservada por IETF

C000::/3

Reservada por IETF

E000::/4

Reservada por IETF

F000::/5

Reservada por IETF

F800::/6

Reservada por IETF

FC00::/7

Unicast Única Local

FE00::/9

Reservada por IETF

FE80::/10

Unicast de Enlace Local

FEC0::/10

Reservada por IETF

FF00::/8

Multicast

  • Reservada por la IETF:

    La IETF es un organismo que gestiona el funcionamiento de todo esto. Son rangos de IPs que simplemente no están asignados a ninguna tarea.

  • Unicast Global:

    Aquí encontraríamos el espacio IPv6 que sería usado de manera global para especificar cualquier dispositivo de red, lo que en IPv4 podríamos conocer como IPs Públicas. Estas IPs tienen una estructura en común:

    Prefijo de Red

    Subred

    ID de interface

    n bits

    m bits

    128-n-m bits

El prefijo de red tiene la función del rutado principal dentro de todo Internet, podemos ver este como los bloques principales de IPs que se entregarían a los ISP o las grandes multinacionales por parte de los administradores de zona como RIPE, ARIN y otros.

La Subred sería administrada de manera local por los administradores de dichos bloques con la finalidad de configurar sus propias redes.

El ID de interface sería la punta de la flecha que señalaría cada host en concreto, de forma única dentro de cada subred y a su vez dentro de cada red principal. Este ID de interface vendrá a ser de forma similar a lo que hoy en día entendemos como dirección MAC de un dispositivo de red. Dicho de otro modo, cada IPv6 señalará directamente a cada adaptador de red en Internet.

Aun así, el mismo rango de direcciones posibles dentro de las direcciones Unicast Globales, se encuentra dividido y asignado de forma diferente:

Rango IP

Asignado a

2001:0000::/29 – 2001:01F8::/29

IANA

2001:0200::/29 – 2001:03F8::/29

APNIC

2001:0400::/29 – 2001:05F8::/29

ARIN

2001:0600::/29 – 2001:07F8::/29

RIPE NCC

2001:0800::/29 – 2001:09F8::/29

No asignado aun

2001:0A00::/29 – 2001:0BF8::/29

No asignado aun

2001:0C00::/29 – 2001:0DF8::/29

No asignado aun

2001:0E00::/29 – 2001:0FF8::/29

No asignado aun

2001:1000::/29 – 2001:11F8::/29

No asignado aun

No asignado aun

2001:FE00::/29 – 2001:FFF8::/29

No asignado aun


Una vez se vaya agotando cada bloque asignado a cada RIR, se le reasignaría un nuevo bloque.

  • Unicast Única Local:

    Este rango sería el equivalente al usado para las direcciones privadas en la actual IPv4. Su estructura no obstante sería exactamente igual que las direcciones IPv6 Unicast globales. Al igual que las direcciones privadas IPv4, las direcciones Unicast Únicas Locales tan solo tienen un ámbito de uso interno, y no serán (no deberían al menos) ser enrutadas fuera de la red local. De todos modos y por seguridad, el prefijo de red en este caso se establece en 40 bits, el cual será generado de forma aleatoria con el objetivo de que si en algún momento un paquete IPv6 con IPv6 única Local fuese enrutado al exterior y del exterior inyectado a otra red local, tener la garantía de que no correspondería a ningún hosts de esta. Dicho de otro modo, la probabilidad de que el host externo existiese sería a todos los efectos prácticamente nula, dado que teóricamente la IP generada para uso local sería única en toda Internet. Todo el resto del rango pasaría a ser administrado por la persona a cargo de la red a voluntad, del mismo modo que configuramos nuestras redes privadas. De este modo tendremos la posibilidad si así lo deseamos de conectar nuestra red directamente a Internet o aislarla de esta. Si fuese este último caso, es evidente que sería necesario hacer uso de dispositivos NAT para traducir las direcciones locales a una dirección IPv6 Unicast Global en caso de querer conectar dicha red al exterior, del mismo modo que se realiza a día de hoy con IPv4

  • Unicast de Enlace Local:

    A diferencia de Unicast única local, en este caso la IPv6 no solo no tendría un ámbito local, sino que esta no sería única. Es decir… esa misma IP podría ser encontrada en otros puntos del planeta, todo lo contrario que lo que sucede con el apartado anterior, que pese a ser de ámbito local pueden considerarse IPs únicas. Estas IPs corresponderían a las que en IPv4 podríamos llamarlas IPs APIPA, es decir, IPs de autoconfiguración propia sin necesidad siquiera de un enlace a un nodo de red:


    Prefijo de Red (10 bits)

    Subred (54 bits)

    ID de interface (64 bits)

    1111111011

    0

    Host


  • Multicast:

    En IPv6 el término IP Broadcast desaparece, y tan solo permanece el de Multicast. A fin de cuenta para enviar un paquete a toda una misma red no hace falta una dirección específica, ya que todos estos hosts pueden formar parte de un mismo grupo Multicast. Es decir, en IPv6 las direcciones de punto final :FF señalarían a hosts concretos.

    Por ello se reserva un rango específico para direcciones Multicast. Estas, si poseen una estructura algo diferente a las direcciones Unicast vistas hasta el momento, y tiene su lógica. Estas direcciones Multicast pueden tener tanto un ámbito local como global, por lo tanto se requerirán de ciertos bits específicos para esta diferenciación:


    Prefijo de Red (8 bits)

    Flag (4 bits)

    Ámbito ( 4 bits)

    ID de grupo (112 bits)

    11111111

    0 | R | P | T

    Ver tabla

    ID

Flag: Especifican algunas opciones de la IP multicast, como por ejemplo si la IP es permanente (T) o si es una IP que pertenece al propio prefijo de red (P).
Ámbito: Según el valor que tome, especificará el alcance de la dirección Multicast. Así por ejemplo, para un ámbito 1110 la IP multicast sería escuchada de manera global, mientras que si es 0010 el ámbito sería local. Las especificaciones completas las podemos encontrar si lo deseamos en el RFC 4291.

En adición de esto, existen ya preestablecidos grupos estándares, así como especificaciones mucho más amplias de cómo usar estas IPsv6 Multicast, pero tampoco es demasiado importante para nosotros.

  • IP no especificada e IP de Loopback:

    Del mismo modo que en IPv4 existen las IPs especiales 0.0.0.0 como IP comodín e IP 127.0.0.1 conocida como IP de retroalimentación o Loopback, en IPv6 existe exactamente lo mismo. Así la IP no especificada será la correspondiente a ::/128, mientras que la IP de Loopback corresponderá a ::1/128.

 

Además del ingente espacio de direcciones IP, IPv6 posee principalmente tres grandes mejoras frente a IPv4. La primera es que IPv6 está creado de base para ser usado con IPSec, protocolo punto a punto para el cifrado de las conexiones. Esto no significa que IPSec será usado en todo internet, sino que su implementación es obligada y cualquier sistema preparado para ello. La segunda característica es que los propios hosts y nodos extremos podrán auto negociar su propia IP, sin necesidad de un servidor DHCP. El proceso se realiza gracias al nuevo protocolo ICMPv6. El host enviará así un paquete ICMPv6 de descubrimiento a la dirección multicast de enlace local y si existe un router configurado para ello en un extremo, este le responderá directamente con los ajustes de configuración de este, según la estructura actual de su red. La tercera mejora son los conocidos como los paquetes Jumbo. Estos no son desconocidos, ya que actualmente son usados en redes GigaEthernet para mejorar la transmisión de los datos, ya que es posible exceder el MTU de la red, enviando paquetes con un mayor tamaño.

De cara a como es en sí un paquete IPv6 (su cabecera) hay que destacar la simplificación que se ha realizado de la actual IPv4:

Versión

Clase de Tráfico

Etiqueta de Flujo

Longitud

Cabecera Siguiente

Límite de saltos

IP Origen

IP Destino



  • Versión (4 bits): Corresponde exactamente igual al valor de IPv4, es decir, específica la versión del protocolo. Para IPv6 tomará por tanto un valor de 0110
  • Clase de Tráfico (8 bits): Similar a al campo DiffServ de IPv4. Su objetivo es proveer al protocolo capacidades QoS, es decir, capacidades para priorización del tráfico, dado que por desgracia el ancho de banda siempre será limitado.
  • Etiqueta de Flujo (20 bits): Aun se encuentra en experimentación. La idea original consistía en la posibilidad de poder etiquetar los paquetes de forma que fuese adecuado para aplicaciones en tiempo real como VoIP, o para sistemas QoS no estándares. No es un requerimiento actual, y puede establecerse todo a ceros si no es usado. Recordemos que IPv6 es aún un protocolo experimental que está en sus primeras fases. Hasta que no pase X tiempo en el entorno real y a gran escala, no se podrá con casi toda seguridad retocarlo para obtener las mejores prestaciones.
  • Longitud (16 bits): Especifica ni más ni menos la longitud en bytes de los datos que serán enviados por el paquete sin contar la propia cabecera. Es decir, si el SDU de la capa superior ocupa 60KB, la longitud será 60KB. A esto hay que añadir que IPv6 permite extensiones de la cabecera para añadir funcionalidades opcionales. Estas extensiones de la cabecera NO forman parte de la cabecera en sí, e irían justo antes del SDU. Esto quiere decir que el tamaño de las extensiones de la cabecera sí será contabilizado en este campo. Al ser un campo de 16 bits permitirá de nuevo un tamaño máximo de paquete de unos 64KB.
  • Cabecera Siguiente (8 Bits): Tiene la misma funcionalidad que el campo “protocolo” de IPv4. Especifica la cabecera que se encontrará después de la cabecera actual. En IPv4 hacía referencia prácticamente tan solo al protocolo usado en el SDU superior, pero aquí puede especificar también las extensiones de cabecera, como por ejemplo extensión de cabecera para fragmentos.
  • Límite de Saltos (8 bits): Es el campo TTL (Time To Live) de IPv4. Cada salto que dé el paquete, este contador será decrementado en 1. Si llegase a cero, el paquete se descarta de la red.
  • IP Origen/Destino (128 bits cada campo): Cada dirección IPv6 de 128 bits, primero la IP de origen y después la IP destino.

Es interesante ver como por ejemplo se ha eliminado de la cabecera IPv6 el checksum, dejando la comprobación de integridad directamente sobre los niveles superiores e inferiores. Aunque las ideas en papel son buenas, hay que tener en cuenta que las estadísticas y la realidad son otras. A lo mejor en un principio se estimó que la comprobación de la integridad de una cabecera IP era adecuado a principios de Internet dado la poca fiabilidad de las redes antiguas. A día de hoy se ha demostrado que la comprobación de la cabecera en IPv4 quizás tan solo era útil (es decir, existía un error y este era detectado) en un porcentaje tan ínfimo que su uso ha dejado de ser necesario, máxime cuando niveles superior e inferiores ya poseen controles de integridad adecuados (los cuales antes también existían)

Las extensiones de cabecera son igualmente parte imprescindible de IPv6. Si bien es cierto que la cabecera base ha sido completamente reducida, parte de las opciones que existían en IPv4 ahora las podremos encontrar como extensiones. Estas extensiones serán indicadas en el campo “cabecera siguiente” antes descrito, que nos dirá que cabecera será la que encontraremos justo después de la cabecera base, es decir, antes de los datos superiores. Estas cabeceras no obstante jamás serán procesadas por un nodo de red, esto quiere decir que todos los nodos de los saltos intermedios que de un paquete desde el origen al destino, tan solo se procesará la cabecera base. Las extensiones de cabecera serán por tanto tan solo procesadas cuando el paquete alcance su destino final. La única excepción se dará cuando exista la extensión de cabecera Hop-By-Hop. La cual será siempre añadida como primera extensión de cabecera e identificada por “Cabecera siguiente” como un cero.

Las extensiones especificadas actualmente en IPv6, así como su orden (en caso de que exista más de una extensión de cabecera) es el siguiente:

Cabecera IPv6 Base
Cabecera Hop-By-Hop
Cabecera de Opciones de destino (Para ser procesada tan solo por el primer destino/salto)
Cabecera de Rutado
Cabecera de Fragmentos
Cabecera de encapsulación de seguridad de los datos
Cabecera de Opciones del destino (Para ser procesada tan solo por el destino final)
Cabecera de nivel superior

Cada cabecera tiene sus campos y opciones concretos, que podríamos especificar pero sería rizar más el rizo. De todos modos se puede acudir a las especificaciones para obtener las especificaciones detalladas en el RFC 2460. Lo que es evidente es que cada cabecera de extensión tendrá un campo que será también “Siguiente Cabecera”, puesto que en IPv6 puede existir más de una extensión de cabecera. No obstante, el tamaño de estas extensiones será siempre un número múltiplo de 64 bits, con la idea de que en ningún momento se pierda la alineación de los 64 bits (La cabecera completa de un paquete IPv6 será por tanto siempre múltiple de 64)

Para terminar con IPv6, hay que tener en cuenta que algunos protocolos asociados a IPv4 son modificados ligeramente para poder soportar IPv6, como es el caso por ejemplo de ICMPv6 o DCHPv6. Es evidente que por ello IPv4 e IPv6 son completamente incompatibles entre ellos. No obstante, durante algunos años viviremos posiblemente una utilización de ambos. Esto será posible no porque ambos protocolos sean compatibles, sino porque se usarán técnicas de túneles para poder lograr esta interoperabilidad. Es decir, cuando un router obtenga una petición IPv6 y quiera enviarla por una red IPv4 tendrá que encapsular el paquete IPv6 como un paquete IPv4 estándar. El paquete podrá viajar así a través de toda la red IPv4 hasta el nodo destino, en el cual el paquete IPv4 se abriría para dar origen al paquete IPv6 que sería rutado a través de la red IPv6. Este mismo concepto puede ser usado a la inversa. El problema principal al que uno se encuentra es el soporte hardware de IPv6, así como de técnicas de túneles descrita.

Para que un usuario a día de hoy pueda realizar una conexión a redes IPv6 de forma directa, necesitará primero que su ISP tenga una infraestructura IPv6 ya creada (cosa que actualmente es muy raro que tengan), por no hablar de que el router de cada particular sea compatible con IPv6. De cara a los PCs de los usuarios esto no es problema en Windows ni en Linux desde hace tiempo. El soporte para IPv6 existe desde hace tiempo y los equipos estarían perfectamente preparados para recibir direcciones IPv6 y conectarse a las redes pertinentes. Microsoft implementó además del soporte nativo IPv6 técnicas de túneles como Teredo para permitir la interoperabilidad, aunque como he dicho actualmente la penetración de IPv6 es mínima. Poco a poco las pruebas van terminándose, y además urge un nuevo espacio de Direcciones, IPv6 como hemos dicho está acabado. El principal problema por tanto recae tan solo en los routers y otros dispositivos de red, si no tenemos soporte en ellos, así como en las redes de nuestro ISP, no podremos hacer mucho. Veamos un ejemplo de conexión a una red IPv6:

Interfaz en Windows 7 para IPv6:

Adaptador de Ethernet Local Area Connection:
Sufijo DNS específico para la conexión. . :
Descripción . . . . . . . . . . . . . . . : Marvell Yukon PCI-E

Gigabit Ethernet Controller #2
Dirección física. . . . . . . . . . . . . : xx-xx-x-xx-xx-xx
DHCP habilitado . . . . . . . . . . . . . : sí
Configuración automática habilitada . . . : sí
Dirección IPv6 . . . . . . . . . . . . . :2002:xxxx:xxxx:x:xxxx:xxxx:xxxx:xxxx(Preferido)
Dirección IPv6 temporal. . . . . :2002:xxxx:xxxx:x:xxxx:xxxx:xxxx:xxxx(Preferido)
Vínculo: dirección IPv6 local. . . : xxxx::xxxx:xxxx:xxxx:xxxx%12 (Preferido)

Dirección IPv4. . . . . . . . . . . . . . : 192.168.x.x(Preferido)
Máscara de subred . . . . . . . . . . . . : 255.255.255.0
Concesión obtenida. . . . . . . . . . . . : sábado, 05 de junio de 2010 21:05:12
La concesión expira . . . . . . . . . . . : miércoles, 13 de julio de 2146 3:39:47
Puerta de enlace predeterminada . . . . . : xxxx::xxx:xxxx:xxxx:xxxx%12
192.168.x.x
Servidor DHCP . . . . . . . . . . . . . . : 192.168.x.x
Servidores DNS. . . . . . . . . . . . . . : 192.168.x.x
NetBIOS sobre TCP/IP. . . . . . . . . . . : habilitado

 

Petición DNS IPv6:

ipv6.l.google.com: type AAAA, class IN, addr 2a00:1450:8002::68
Name: ipv6.l.google.com
Type: AAAA (IPv6 address)
Class: IN (0×0001)
Time to Live: 5 minutes
Data length: 16
Addr: 2a00:1450:8002::6a

 

Paquete TCP/IPv6:


 

 

Protocolo DNS

Domain Name System (o Sistema de Nombres de Dominio en español) es la segunda piedra angular en la que se sustenta no solo Internet, sino todas las rede en general. Al igual que IP, DNS no es más que un espacio de direcciones por así decirlo, aunque sería más correcto usar el término de espacio de nombres. Es curioso el hecho de que incluso los menos instruidos en la materia en algún momento ha escuchado o ha tenido que tratar con IPs, pero en cambio los términos DNS parecen mucho más difusos y raramente tenidos en cuenta, quizás tan solo cuando el ISP nos da la configuración de nuestra línea. No obstante, gracias al sistema DNS conocemos internet como la conocemos. ¿Es realmente necesario el sistema DNS? No, su existencia no nace de una “necesidad” propiamente dicha, sino de ser un recurso de increíble valor para cualquier persona, dada las limitaciones mentales que todo el mundo tenemos: Siempre conoceremos el nombre de una persona, pero solo algunos de sus números de teléfono.

El sistema DNS puede verse por tanto como un sistema de mapeo de direcciones IP a nombres. Es simple, cualquier persona del mundo será capaz de recordar nombres como google.es, microsoft.com, intel.com o theliel.es con infinita más facilidad que recordar (en el mismo orden): 216.239.59.104, 207.46.197.32, 198.175.96.33, 188.121.46.128. Y eso por supuesto si tenemos en cuenta el sistema actual IPv4, si tenemos en cuenta la proximidad de IPv6 el problema sería infinitamente mayor. Es evidente por tanto que aun cuando técnicamente no es imprescindible, de cara a las capacidades limitadas del ser humano podemos decir que sí lo es.

Cada vez que hacemos mención en alguna red (ya sea local o externa) de un nombre de domino, el sistema DNS hace posible la comunicación con dicho host, lo que sucede es que este sistema trabaja aparentemente siempre de forma transparente para nosotros, del mismo modo que para un usuario que navega por internet no entiende de IPs ni las necesita, lo cual no significa que sin saberlo las esté empleando de forma continuada.

Hay que tener presente como se vio en el capítulo anterior, que al igual que se gestiona el espacio de direcciones IP, se gestiona el espacio de nombres. Esto quiere decir que no existirán dos nombres iguales para el mismo dominio. ¿Dominio? Esto es algo que también se explicó. El sistema DNS es jerárquico, dividido por así decirlo en dominios, de forma que cada dominio superior gestiona sus dominios secundarios, y estos secundarios los dominios terciarios y así sucesivamente. Ya vimos el papel de la ICANN a la hora de gestionar los dominios de primer nivel y como se delegan los dominios de segundo o tercer nivel a cada autoridad. También se habló de los servidores raíces y de función, pero aquí veremos realmente la importancia de estos, así como el funcionamiento real del sistema DNS. En esta ocasión vamos a suponer un ejemplo, y de este todo el funcionamiento DNS, comenzando por el ejemplo más simple y aumentando su complejidad:

 

  • Caso 1: No necesaria resolución DNS, especificación de IP de forma directa

    El caso más sencillo que podemos ver es cuando realizamos una solicitud directamente sobre una IP. Por ejemplo si deseamos obtener acceso a un recurso de red interna y conocemos de antemano la IP de dicho servidor. Si en el explorador de archivos de Windows tecleamos la ruta \\192.168.5.23 (por supuesto damos por hecho una correcta configuración de puerta de enlace, máscara de subred e IP), el PC se comunicará directamente con el host especificado, en este caso sin siquiera necesidad de acceder a la puerta de enlace del router, ya que la tabla ARP del sistema ya contiene la dirección de este (más adelante se verá el protocolo ARP), con lo que se hace la petición sobre la propia dirección MAC:

    Interfaz: 192.168.5.2 — 0xc
    Dirección de Internet Dirección física Tipo
    192.168.5.1 00-xx-xx-xx-xx-xx dinámico
    192.168.5.23 00-xx-xx-xx-xx-xx dinámico

    En el caso que la petición sea realizada en el navegador, por ejemplo especificando de forma directa la IP del servidor de google en España: “216.239.59.104″, el proceso será exactamente igual, la petición saldrá por nuestro router e irá directamente hacia dicha IP (nuestro paquete irá saltando de router en router hasta alcanzar el host indicado, pero sin ninguna necesidad de uso del sistema DNS:

    tracert 216.239.59.104

    1 <1 ms <1 ms <1 ms Alpha5 [192.168.x.1]
    2 35 ms 35 ms 36 ms 192.168.153.1
    3 35 ms 35 ms 32 ms 209.Red-81-46-42.staticIP.rima-tde.net [81.46.42.209]
    4 80 ms 42 ms 42 ms So6-0-0-0-grtmadno1.red.telefonica-wholesale.net.10.16.84.in-addr.arpa [84.16.10.65]
    5 43 ms 64 ms 64 ms Xe9-1-0-0-grtpartv2.red.telefonica-wholesale.net [84.16.15.174]
    6 65 ms 65 ms 63 ms Xe0-3-0-0-grtpartv1.red.telefonica-wholesale.net [84.16.12.213]
    7 * * * Tiempo de espera agotado para esta solicitud.
    8 77 ms 72 ms 104 ms 209.85.251.40
    9 76 ms 74 ms 72 ms 209.85.248.95
    10 75 ms 78 ms 75 ms gv-in-f104.1e100.net [216.239.59.104]

     

  • Caso 2: Resolución DNS en archivo local

    En este caso no se hace uso del sistema DNS como tal, sino de archivos de texto existentes en cada equipo que contienen precisamente este mapeo de nombres-IPs. Históricamente era el sistema usado para esta tarea, y aun cuando a día de hoy el sistema DNS es usado de forma global, este sistema se continúa usando de forma relativamente extendida, aunque generalmente por propósitos un tanto diferentes. Ya hemos hablado alguna vez de ello: El archivo “Hosts”. Este archivo presente en la gran mayoría de todos los sistemas operativos es el que mantiene esta lista, puesto que no es más que una lista. En Windows por ejemplo podemos encontrarlo en “C:\Windows\System32\Drivers\etc\Hosts”, mientras que en Linux lo encontramos en “/etc/hosts”. Veamos un ejemplo de este fichero:

    192.168.x.52 alpha
    192.168.x.52 beta.com
    209.85.229.104 google.es
    127.0.0.1 webpeligrosa.com

    Dado este fichero LOCAL de nuestro sistema, nuestro sistema estaría en condiciones de aceptar los primeros nombres en lugar de las direcciones IPs. Así, para acceder al hosts con la IP 192.168.x.52 se puede realizar conociendo su IP o su nombre de dominio, en este caso “alpha”. El segundo caso, beta.com es exactamente igual, solo recordar que el sistema jerárquico actual de dominios de primer nivel, segundo nivel… es una cuestión de eficiencia, organización y acuerdos, para una resolución local no es necesario tener el hombre de host asociado a un dominio TLD (de primer nivel).

    Más interesante es el tercer caso. Los dos primeros hacen referencia a direcciones locales, mientras que la tercera es una dirección global. Pero el proceso es el mismo. Sin la existencia de un sistema DNS como el actual, el archivo hosts de cada PC debería de tener dicha entrada si se quisiese poder acceder al servidor de google.es sin necesidad de conocer la IP de este. En este caso la IP mostrada es la IP real de google.es, esto es muy importante saberlo, puesto ¿qué sucedería si la IP que hemos añadido a dicho archivo realmente no perteneciese al servidor de google.es? El archivo hosts es un archivo de mapeo, sean las direcciones mapeadas legítimas o no. Esto quiere decir que si sustituimos dicha entrada del archivo hosts por ejemplo esta otra:

    217.146.186.221 google.es

    tendríamos algo tan gracioso como acceder a la web de Yahoo cuando en el navegador introducimos google.es. El mapeo del archivo hosts prevalece sobre cualquier resolución de nombres externa. ¿Qué utilidad puede tener esto? A día de hoy muchos tipos de malware modifican el archivo de hosts para enviar a los afectados a sitios donde realizar pishing o webs con código maligno para lanzar exploits o ataques XSS (entre otros) contra el usuario.

    El último caso, y posiblemente el más usado a día de hoy, es la redirección de ciertas páginas a la dirección IP de Loopback. Esta simple práctica abre la posibilidad a un sin fin de posibilidades, como por ejemplo el filtrado de hosts, ya que cualquier hosts redirigido a la dirección de Loopback será anulado por así decirlo (siempre que en el equipo local no tenga levantado ningún servidor web, claro está. Así por ejemplo en el caso mostrado, si redirigimos la URL webpeligrosa.com, que por ejemplo conocemos es altamente dañina, a nuestra dirección de Loopback, en cualquier momento que el PC intente una conexión a dicho host, ya sea premeditado o por la intervención de un malware, nuestro equipo la enviará a la dirección de Loopback, y con ello la web no será válida.

    Estos archivos hosts, este sistema tiene una gran serie de ventajas, pero tienen tres características que lo hacen completamente inviable de cara a una red extensa: La primera de ella es que un archivo local de estas características es fácil de administrar cuando los hosts a filtrar son pocos, en cambio si el número es elevado tendríamos desde problemas de rendimientos (cientos de miles de direcciones supondría tamaños de archivos considerables) hasta entradas duplicadas. El segundo problema es aún peor. Si poseemos un archivo de hosts con la resolución de 10 equipos, y uno de ellos cambia de IP es fácil localizarlo y cambiarlo. Si manejamos archivos de hosts de cientos o miles de equipos, se hace imposible la actualización de estos archivos. La tercera es que no dispone de ningún sistema centralizado, esto significa que cada archivo hosts debería de ser almacenado en principio de forma local, y cualquier actualización de cualquier hosts tendría que ser modificada en todos los equipos.

  • Caso 3: Resolución DNS en caché local

    Sin un archivo de hosts ni especificación de la dirección IP de forma directa, el equipo necesita de un sistema “superior” que permita darle a conocer dicha IP, y es por ello que el sistema DNS es necesario. Pero si se realizase una petición DNS por cada nombre de dominio introducido, sería una práctica enormemente ineficiente. Es cierto que la actualización en el caso 2 de la IP de un hosts es algo más que inviable en grandes magnitudes, pero igualmente es cierto que tampoco es algo que suceda constantemente. Si la IP de un hosts se mantiene relativamente “estable” con el tiempo, sería una tontería estar realizando peticiones DNS constantemente para resolver la dirección del hosts. Más aun, cada petición DNS que se realiza, tiene un coste en el ancho de banda y en la sobrecarga de los servidores de resolución DNS (estos los veremos más adelante)

    Por todo ello, no es rara la existencia de una caché a nivel local que almacene las peticiones más realizadas o más recientes. Imaginar por ejemplo que se desea acceder a la web de google.es y que 5 segundos más tarde deseamos realizar otro acceso a la misma web. Esto implicaría dos peticiones DNS. Con una caché de DNS local, con un tiempo de vida limitado evidentemente, sería el equipo local quien respondería la petición DNS de nuestro navegador, sin necesidad de enviar una petición DNS a nuestra puerta de enlace o directamente a nuestros servidores DNS:

    C:\Users\Theliel>ipconfig /displaydns >> dns.txt
    zxlinks.com
    —————————————-
    Nombre de registro . : zxlinks.com
    Tipo de registro . . : 1
    Período de vida . . . : 86400
    Longitud de datos . . : 4
    Sección . . . . . . . : respuesta
    Un registro (host). . : 127.0.0.1

    zxlinks.com
    —————————————-
    No hay registros de tipo AAAA

    arstechnica.com
    —————————————-
    Nombre de registro . : arstechnica.com
    Tipo de registro . . : 1
    Período de vida . . . : 2091
    Longitud de datos . . : 4
    Sección . . . . . . . : respuesta
    Un registro (host). . : 75.102.3.15

    Con ipconfig /displaydns mostramos el contenido de la caché DNS de Windows. En este caso vemos dos entradas en ella, una de ellas apunta a la dirección de Loopback, la otra la IP de dicho hosts. Esto es debido a que Windows introduce los host del archivo hosts en su caché DNS, con un tiempo de vida de 24 horas (86400 seg). Por otro lado registrará cualquier petición DNS reciente que sea realizada, de este modo si el sistema requiere la resolución de otro host en un tiempo en el que la caché aun tenga dicho registro, será esta quien devuelva el resultado en vez de realizar una petición. El lado negativo en cambio es que si un host modifica su IP en el tiempo que nuestro sistema está cacheando la IP, la IP no será actualizada para nuestro sistema, y posiblemente nos toparemos con una URL no disponible. Es decir, el uso de caché aumenta el rendimiento considerablemente, pero de cuando en cuando puede existir un problema de coherencia. Es por ello que casi cualquier sistema permite el vaciado de la caché DNS, en Linux suele ir asociado simplemente a reiniciar el servicio (dependiendo del servicio usado), en Windows se realiza mediante: “ipconfig /flushdns”

    Por encima de esta caché local, podríamos situar un caché aún más cercana al usuario que se resolvería antes que enviar la petición al sistema. Algunos navegadores como Firefox poseen una pequeña caché interna de resolución de DNS que realiza una función igual. Esta caché suele ser más pequeña y suele ser mucho más eficiente, dado que esta caché tan solo es usada para peticiones realizadas mediante el navegador. Esto quiere decir que cualquier otro tipo de peticiones producidas por gestores de correo, clientes FTP, conexiones de juegos/aplicaciones… ninguna de estas estarán registradas en dicha caché. En Firefox, para poder acceder a las opciones de caché de DNS es necesario acceder a la página de configuración avanzada mediante la dirección en la barra de direcciones: about:config, y dentro de esta buscar la clave “network.dnsCacheEntries” y “network.dnsCacheExpiration”, siendo ambos nombres bastante descriptivos sobre su función.

  • Caso 4: Resolución DNS en caché de nuestro router

    Del mismo modo que nuestro sistema cuenta con una pequeña caché para almacenar las peticiones DNS más recientes o más comunes, no es extraño pensar en que un sistema similar podría ser incluido por ejemplo a nivel de nuestro propio router, de modo que el router serviría a todos sus clientes conectados como servidor de DNS. Sería por tanto este quien resolvería por los clientes las peticiones pertinentes y devolvería a estos el resultado. Pero por el mismo motivo, podría mantener una caché interna de DNS con las peticiones no de un solo cliente, sino de todos los clientes conectados. Es decir, si el cliente 1 necesita acceder por vez primera al servidor google.es y segundos más tardes el cliente 2 quiere acceder al mismo servidor, es más que probable que el router no vuelva a realizar una petición DNS para conocer la IP del servidor google.es, sino que ya tendrá almacenada dicha entrada debido a la petición anterior del cliente 1, con lo que todo el sistema se agiliza de forma considerable, optimizando además el ancho de banda. De lo contrario el router tendría que esperar la contestación de los servidores DNS configurados en él, estos a su vez o devolver la petición o realizarla a un servidor superior… y tan solo cuando se obtiene la IP destino devolverla al hosts que la pidió, y una vez el hosts tiene la IP dele servidor poder realizar ahora sí la petición http (por ejemplo) pertinente. Esta función no obstante depende del router en cuestión, y al igual que la resolución de DNS en caché local, posee de pros y contras (en el 90% de las situaciones es una práctica que merece bastante la pena)

    Hay que tener en cuenta y no hay que confundir una caché DNS con un servidor DNS, el cual evidentemente mantiene una caché DNS. Existen routers en la actualidad que poseen funciones de servidor DNS y por tanto cachea las peticiones DNS. Por ejemplo podemos ver esto en las firmware del equipo de DD-WRT.

Resolución DNS por medio de los servidores DNS (caso 5)

Aunque sería el caso 5, vamos a verlo independientemente de los otros 4 casos, dado que es aquí donde se pone en marcha en realidad el sistema DNS. Todos los casos anteriores lo que impiden de un modo u otro es tener que hacer uso de este sistema, no porque sea ineficaz, sino para evitar la sobrecarga en este. Además, es evidente que cualquier petición realizada al exterior consumirá un tiempo superior a cualquier petición respondida de forma local. Veamos algunos tiempos de resolución gracias a la herramienta de resolución DNS Dig, disponible tanto para Linux (suele venir incluida) como para Windows (se debe de descargar):

theliel@Anarchy:~$ dig theliel.es
; <<>> DiG 9.7.0-P1 <<>> theliel.es
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 58146
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;theliel.es. IN A

;; ANSWER SECTION:
theliel.es. 2362 IN A 188.121.46.128

;; Query time: 2 msec
;; SERVER: 192.168.3.1#53(192.168.3.1)
;; WHEN: Fri Jun 11 17:34:21 2010
;; MSG SIZE rcvd: 44

theliel@Anarchy:~$ dig @80.58.61.250 theliel.es

; <<>> DiG 9.7.0-P1 <<>> @80.58.61.250 theliel.es
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 3856
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;theliel.es. IN A

;; ANSWER SECTION:
theliel.es. 2361 IN A 188.121.46.128

;; Query time: 66 msec
;; SERVER: 80.58.61.250#53(80.58.61.250)

;; WHEN: Fri Jun 11 17:34:22 2010
;; MSG SIZE rcvd: 44

Como podemos ver, la resolución DNS realizada por mi router en este momento es de tan solo 2 msec, es más que probable que tenga en su caché la resolución ya realizada. En cambio, si especifico que la resolución se lleve a cabo por medio de mi ISP, el tiempo se eleva a 66 msec, en este caso es el servidor DNS primario de telefónica España. Esta utilidad puede ser usada también para comprobar que servidores DNS son más óptimos para nuestra red. Por ejemplo, podemos ver el tiempo que tardaría los servidores de DNS de google, y si son mejores que los de nuestro ISP:

theliel@Anarchy:~$ dig @8.8.8.8 theliel.es
; <<>> DiG 9.7.0-P1 <<>> @8.8.8.8 theliel.es
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 49868
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;theliel.es. IN A

;; ANSWER SECTION:
theliel.es. 3594 IN A 188.121.46.128

;; Query time: 97 msec
;; SERVER: 8.8.8.8#53(8.8.8.8)

;; WHEN: Fri Jun 11 17:43:00 2010
;; MSG SIZE rcvd: 44

En este caso, el servidor de DNS de Google (8.8.8.8) tiene unos tiempos de resolución peores a los servidores de mi ISP. Esto también tiene su explicación. Por un lado la cercanía de los servidores, por otro lado la necesidad de dichos servidores de recurrir a servidores DNS superiores.

Cuando ningún sistema “local” puede resolvernos un nombre de dominio, es necesario realizar una petición DNS a un servidor DNS para que este nos devuelva la IP del host al que deseamos acceder. Cuanto antes sea respondida dicha petición, antes será alcanzado el hosts. La mejor forma de ilustrar esto es poner dos ejemplos: El mejor de los casos y el peor de los casos. De este modo se puede ver perfectamente el funcionamiento jerárquico de DNS y la importancia última de los servidores DNS raíces.

En el mejor de los casos, el servidor DNS de nuestro ISP tiene directamente la respuesta de nuestra petición. Es decir, imaginar que deseamos conocer la IP del servidor donde está alojado el dominio theliel.es. Si nuestro ISP posee esta entrada directamente en su servidor DNS, este no tendrá que acudir a un servidor de DNS superior y de forma inmediata devolverá la IP de este host. Pero si dicha entrada no se encuentra presente en el servidor de DNS de nuestro ISP, este a su vez debe de realizar una petición DNS a un servidor DNS superior a él, De este modo se realiza lo que se conoce como peticiones DNS recursivas, en la que nuestra petición DNS va saltando entre los diferentes servidores DNS hasta que alguno de estos servidores devuelve la IP deseada. Veamos el peor de los casos de este ejemplo cuando se desea conocer la IP del host earth.google.es:

theliel@Anarchy:~$ dig +trace @80.58.61.250 earth.google.es

; <<>> DiG 9.7.0-P1 <<>> +trace @80.58.61.250 earth.google.es
; (1 server found)
;; global options: +cmd
. 472319 IN NS f.root-servers.net.
. 472319 IN NS g.root-servers.net.
. 472319 IN NS h.root-servers.net.
. 472319 IN NS i.root-servers.net.
. 472319 IN NS j.root-servers.net.
. 472319 IN NS k.root-servers.net.
. 472319 IN NS l.root-servers.net.
. 472319 IN NS m.root-servers.net.
. 472319 IN NS a.root-servers.net.
. 472319 IN NS b.root-servers.net.
. 472319 IN NS c.root-servers.net.
. 472319 IN NS d.root-servers.net.
. 472319 IN NS e.root-servers.net.
;; Received 228 bytes from 80.58.61.250#53(80.58.61.250) in 400 ms

es. 172800 IN NS ns1.crn.nic.es.
es. 172800 IN NS ns1.nic.es.
es. 172800 IN NS ns1.cesca.es.
es. 172800 IN NS ns3.nic.fr.
es. 172800 IN NS sun.rediris.es.
es. 172800 IN NS ns-ext.nic.cl.
es. 172800 IN NS sns-pb.isc.org.
;; Received 376 bytes from 202.12.27.33#53(m.root-servers.net) in 99 ms

google.es. 7200 IN NS ns2.google.com.
google.es. 7200 IN NS ns1.google.com.
;; Received 79 bytes from 130.206.1.2#53(sun.rediris.es) in 66 ms

earth.google.es. 345600 IN CNAME earth.google.com.
earth.google.com. 86400 IN CNAME www3.l.google.com.
www3.l.google.com. 300 IN A 209.85.229.102
www3.l.google.com. 300 IN A 209.85.229.100
www3.l.google.com. 300 IN A 209.85.229.101

;; Received 132 bytes from 216.239.34.10#53(ns2.google.com) in 116 ms

En este caso, el servidor DNS de nuestro ISP (80.58.61.250) es incapaz de resolver la IP del host earth.google.es. Dado que no es capaz de resolver dicha dirección, no tiene otro remedio que realizar una petición DNS a un servidor que pueda conocer algo más de ese host. Aquí es donde cobra gran importancia la jerarquía de los dominios. En el host earth.google.es, el dominio de primer nivel es “es”. El servidor de DNS de telefónica no conoce cuales son los servidores de resolución DNS para los ccTLD .es, pero sí conoce la dirección de los servidores DNS raíces. El servidor DNS de telefónica consulta la lista de los servidores raíces y opta por enviar la petición al servidor raíz m (m.root-servers.net). El servidor raíz m recibe por parte del servidor DNS de telefónica una petición de resolución para el servidor DNS .es. El servidor raíz m SI CONOCE y si tiene en su base de datos la dirección de los servidores DNS que gestionan las direcciones ccTLD .es, y de entre todas ellas escoge el servidor sun.rediris.es, con lo que envía esta IP al servidor DNS de telefónica. Este conoce ya la IP del servidor de DNS que le podrá resolver la IP del dominio google.es, con lo que envía al servidor DNS anteriormente devuelto por el servidor raíz una petición de resolución para el dominio de segundo nivel google.es. El servidor sun.rediris.es recibe la petición por parte del servidor raíz M para resolver la dirección del host google.es (ya dentro del dominio de primer nivel .es). Esta consta en su base de datos, con lo que le responde de nuevo con la IP de la de la resolución del host del servidor de DNS de google, concretamente ns2.google.com. Dado que este es el último servidor de DNS que necesita, el servidor de telefónica que está realizando la recursividad solicita la resolución de earth.google.es a dicho hosts, dicho servidor recibe la petición de resolución para earth (ya dentro del dominio google.es), y dado que la posee envía la contestación al ISP y este a nosotros.

Lo normal es que todo este proceso se realice de forma completamente transparente por parte de nuestro ISP, y nuestro sistema tan solo realice una petición DNS, mientras que nuestro ISP puede realizar la petición recursiva DNS (es quien va enviando las diferentes peticiones según las respuestas que va recibiendo por parte de los servidores DNS) y es él quien al final nos envía a nosotros la dirección IP final. Aquí podemos ver la gran importancia de los servidores raíces, podemos decir que estos son los que poseen acceso directo a los servidores de DNS TLD. Si estos servidores raíces fallan, Internet falla, de ahí a ser objetivo de hackers desde que Internet nació y de ahí a que estén repartidos por todo el mundo y con numerosas réplicas en él.

Esta es la mejor imagen que he encontrado que ilustra todo el proceso: caché del navegador, caché del PC, caché del ISP y de cómo este envía la petición recursiva:


 

Tipo de Registros DNS:

Hasta ahora hemos hablado sobre cómo funciona el sistema DNS, pero está incompleto. Hasta ahora podríamos hacernos la idea de que un servidor DNS es a groso modo un sistema que procesa las peticiones DNS recibidas con una gran base de datos en la que asocia una IP a un nombre de dominio. Pero esto no es cierto. Esta base de datos no está constituida por una asociación IP -> Nombre de dominio, sino por un conjunto de registros asociados a cada dominio. Esto otorga al sistema DNS de funcionalidades mucho más extendidas, que no simplemente el mero hecho de conocer la IP de un host. Estos registros almacenan cierta información sobre el dominio en cuestión, por ejemplo el registro A lo que contiene es precisamente la IP de dicho dominio.

Aun cuando en la actualidad la lista de posibles registros DNS es mucho mayor, la inmensa mayoría de toda la red continúa usando tan solo algunos de los registros DNS que se crearon originalmente, aquellos especificados en el RFC 1035. De este primer abanico de registros, algunos son experimentales como los registros MB o MR, mientras que otros como MD y MF fueron sustituidos por otros más usados y con la misma finalidad. Veamos los registros DNS que podríamos considerar “útiles” de esta primera especificación:

 

  • A: Almacena la IPv4 del host, es decir, el mapeo de nombre de dominio – dirección IP de host.
  • NS: Especifica un servidor DNS para dicho dominio, es decir, el servidor DNS autorizado para dicho host.
  • CNAME: Más comúnmente conocido quizás como un alias. Es decir, especifica el nombre de otro nombre. Podría verse quizás como una redirección a nivel de DNS de un dominio a otro. Por ejemplo una entrada de este tipo: “correo.theliel.es CNAME gl2.gmail.com” significa que cada vez que se debe de resolver la IP para “correo.theliel.es”, se devolverá en su lugar la IP de gl2.gmail.com. En este caso, decimos que correo.theliel.es (o solamente correo, si damos por hecho que estamos en el dominio theliel.es) es un alias del host de google dado. Esto es usado constantemente. Hay que tener en cuenta que por su propia definición no es posible solicitar a un servidor DNS que nos respondan los alias de dicho dominio, pero sí podemos saber si un dominio/subdominio… dado es un alias de otro simplemente haciendo un ping. Veamos la diferencia entre hacer un ping a un alias o hacer ping a un host directamente:

    Ping a un alias:

    C:\Users\Theliel>ping earth.google.com
    Haciendo ping a www3.l.google.com [209.85.227.100] con 32 bytes de datos:

    Ping al host real anterior:

    C:\Users\Theliel>ping www3.l.google.com
    Haciendo ping a www3.l.google.com [209.85.227.139] con 32 bytes de datos:

    Al hacer un ping a un alias, este automáticamente nos “redirige” al host al que apunta el alias. Es decir, en los servidores de nombres de Google en algún lugar existirá una entrada de este tipo: earth.google.com CNAME www3.l.google.com. Para terminar indicar que aunque se puede hacer, no es recomendable anidar alias, es decir, un alias que apunta a otro alias que apunta al host.

  • SOA: Marca el comienzo de una zona DNS, entendiendo por zona DNS algo así como el ámbito de acción de dicha red. Es decir, los servidores DNS de google forman una zona DNS que casi con toda seguridad englobaría todos los servicios de google, todas sus redes, etc… pero es evidente que los servidores DNS de google casi con toda seguridad no poseen registros de otras zonas DNS como las de Yahoo, Microsoft…

    El registro SOA por tanto contiene en primer lugar el servidor DNS principal de la zona, así como datos administrativos: correo del administrador, número de serie, temporizadores de refresco… datos concretos sobre la propia zona DNS.

  • PTR: Puntero a un nombre de dominio. Su función principal es hacer resoluciones DNS inversas, es decir, en vez de obtener la IP por el host obtener el host por la IP. Un ejemplo de esto:

    C:\Users\Theliel>dig -x 74.125.77.104
    ; <<>> DiG 9.7.1rc1 <<>> -x 74.125.77.104
    ;; global options: +cmd
    ;; Got answer:
    ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 1981
    ;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

    ;; QUESTION SECTION:
    ;104.77.125.74.in-addr.arpa. IN PTR

    ;; ANSWER SECTION:
    104.77.125.74.in-addr.arpa. 86400 IN PTR ew-in-f104.1e100.net.

    Es decir si realizamos una resolución inversa de la IP 74.125.77.104 nos devuelve que es el host ew-in-f104.1e100.net, host de google.es

  • MX: Registro de intercambio de correo. Este registro es fundamental para el uso del correo electrónico, mapea un dominio a un servidor de correo (o una lista de posibles candidatos). Cada vez que enviamos un correo electrónico a una dirección, es necesario conocer el servidor de correo de dicho dominio. ¿Cómo? A través de la consulta de sus registros MX. Una vez obtenemos el host de dicho servidor podemos conectarnos a él para entregar el correo. En realidad el funcionamiento del correo electrónico es muy simple. Si enviamos desde Gmail por ejemplo (interfaz web) un correo a una dirección @live.com, aunque no sea nuestro navegador quien haga la consulta, el servidor de google por nosotros para poder entregar dicho mensaje primero tiene que conocer la IP o el destino de dicho realm (el realm es el @live.com). Por ciencia infusa Google no puede conocer la IP del host al que debe de entregar el correo. Realizaría algo similar a lo siguiente:

    theliel@Anarchy:~$ dig live.com MX
    .

    ;; QUESTION SECTION:
    ;live.com. IN MX

    ;; ANSWER SECTION:
    live.com. 2426 IN MX 5 mx1.hotmail.com.
    live.com. 2426 IN MX 5 mx2.hotmail.com.
    live.com. 2426 IN MX 5 mx3.hotmail.com.
    live.com. 2426 IN MX 5 mx4.hotmail.com.

    theliel@Anarchy:~$ ncat -C mx1.hotmail.com 25
    Connected to mx1.hotmail.com.
    Escape character is ‘^]’.
    220 col0-mc2-f34.Col0.hotmail.com Sending unsolicited commercial or bulk e-mail (bla bla bla)
    ehlo test
    250-col0-mc2-f34.Col0.hotmail.com (3.10.0.73) Hello [81.34.161.58]
    250-SIZE 29696000
    250-PIPELINING
    250-8bitmime
    250-BINARYMIME
    250-CHUNKING
    250-AUTH LOGIN
    250-AUTH=LOGIN
    250 OK
    mail from: <test@gmail.com>
    550 DY-001 Mail rejected by Windows Live Hotmail for policy reasons. We generally do not accept email from dynamic IP’s as they are not typically used to deliver unauthenticated SMTP e-mail to an Internet mail server. http://www.spamhaus.org maintains lists of dynamic and residential IP addresses. If you are not an email/network admin please contact your E-mail/Internet Service Provider for help. Email/network admins, please visit http://postmaster.live.com for email delivery information and support
    Connection closed by foreign host.

    Es decir, primero hay que conocer el servidor de correo, que es posible gracias a una consulta DNS de su registro MX. Este servidor nos responde con una lista de hosts disponibles, TODAS en esta ocasión con la misma prioridad (el número 5 que las precede, a menor número mayor prioridad a la hora de conectarse a uno u otro). Una vez que disponemos ya del host (mx1.hotmail.com en este caso) podemos conectarnos a él. OJO!! aunque se da ya por sabido en realidad cuando intentamos conectarnos al host citado, nuestro sistema deberá realizar otra petición DNS para conocer la IP del host mx1.hotmail.com, consultando el registro A de dicho dominio. Una vez que se realiza la conexión (en mi caso de ejemplo con ncat) el servidor de Gmail intentaría algo como lo expresado, mail from: <test@gmail.com>. En este caso el servidor de correos de live.com no nos permite continuar dado que detecta que la IP origen es dinámica (cuestiones de seguridad de los servidores de correo). En el caso de Gmail permitiría la conexión. Evidentemente es solo un ejemplo.

  • TXT: Es un registro reservado para cualquier tipo de información que se quiera añadir. A día de hoy se usa para una gran multitud de propósitos, ninguno específico.


No obstante, con el paso de los años se han ido haciendo necesario algunos registros adicionales, y a esta lista inicial deberíamos de añadir algunos más para poder dar la lista como “completa”, aunque evidentemente existan muchos otros registros, aunque también mucho menos usados:

  • AAA: Si el registro A mapeaba hosts a direcciones IPv4, es necesario disponer de un registro DNS que permite devolver del mismo modo direcciones IPv6. Su función es exactamente la misma, salvo que en vez devolver los 32bits de una IPv4 nos devolverá los 128 bits de la dirección IPv6.
  • SRV: Registro de servicios, otorga información sobre ciertos servicios. A día de hoy su uso es fundamental en aplicaciones tipo VoIP o muchos otros servicios modernos que dependen de una forma u otra de servidores más o menos específicos.


Paquete DNS:

Las peticiones DNS a fin de cuentas son datos que se envían, y al igual que una petición HTTP, este tiene su estructura por así decirlo. No obstante, DNS opera en el nivel de aplicación, por tanto hace uso de otros protocolos inferiores como UDP o IP para transmitirse. DNS usa el protocolo UDP para enviarse, usando el puerto 53 para tal efecto:

1 0.000000000 192.168.x.124 192.168.x.1 DNS Standard query A theliel.es
2 0.117633000 192.168.x.1 192.168.x.124 DNS Standard query response A 188.121.46.128


 

Problemas y soluciones a DNS:

Existen ciertas limitaciones en cuanto al sistema DNS. En realidad no son limitaciones en sí, sino problemas que surgen con los años. Para empezar y el más importante quizás es que DNS como tantos otros protocolos no se crearon para ser seguros, sino eficientes. Pensar por ejemplo que cualquiera podría construir un servidor DNS e intentar suplantar unas peticiones por otras malignas. O realizar ataques de envenenamiento DNS (que se verá en otro momento).

A todo esto se añade el problema de los actuales hosting virtuales, que permiten albergar en el mismo host diferentes servidores web funcionando al mismo tiempo. Con esto nos topamos cada día y nadie se pregunta en realidad cómo es posible, dado que un registro A tan solo devolverá la IP de un host, no la web que se quiere acceder a él. Es decir imaginar que deseamos acceder a una web http://ejemplo.com. Para poder realizarse la conexión es necesaria conocer la IP e imaginemos que la IP es 2.2.2.2. Ahora bien, en teoría solo bastaría una conexión a dicha IP por el puerto 80 y mediante el protocolo http para recibir dicha web. El problema aparece cuando en dicho host hay múltiples servidores web funcionando todos en el mismo puerto y al mismo tiempo. Es por eso que si en el navegador intentamos acceder a estos servidores por IP no podremos. Como saben estor servidores que web devolver? Gracias a las cabeceras HTTP que sirven de referencia al servidor para conocer la web que debe de devolver.

Por último y no menos importante son los conocidos como DDNS, o DNS dinámicos. Ya hemos visto la importancia de un dominio, y que los servidores DNS se van actualizando con el tiempo para tener siempre actualizada la IP a la que apuntan dichos nombres de dominio. No obstante la IP de un host no debería de variar demasiado, pero que sucede si tenemos un dominio que queremos que apunte a un host que posee una IP dinámica? Pues bien, existen servicios tanto gratuitos o de pago para sofocar esto. El sistema funciona de forma muy simple:

  1. Se nos otorga un dominio, normalmente un subdominio de segundo nivel, tipo “pepito.dyndns.org”
  2. Dado que nuestra IP puede variar incluso con cada conexión a la red, se crea una aplicación cliente que envía los datos de la nueva conexión cada vez que la conexión se debe de actualizar, y estos datos los envía precisamente a este proveedor de servicios, en este caso dyndns. Esta aplicación cliente enviaría nuestra IP actual, nombre de usuario y contraseña y con esos datos ellos actualizarían sus servidores DNS para actualizar así la IP asociada a dicho dominio.
  3. Nuestro host, aun teniendo una IP dinámica siempre sería accesible por medio del servicio de DDNS proporcionado por dyndns.

Para que esto sea posible SIEMPRE debe de existir una aplicación cliente que sea la que se encargue siempre de enviar los datos de la nueva conexión al servidor del proveedor. Lo que se hace a día de hoy para facilitar esto es añadir soporte en los propios routers para esto, es decir, muchos routers poseen internamente clientes DDNS, de modo que en realidad todo el proceso queda completamente transparente al usuario, este tan solo tiene que configurar el router y una vez realizado, cada vez que la IP cambia el router conecta con el servidor del servicio y actualiza la IP. Como digo es un servicio muy importante a día de hoy, sobre todo para aquellos que necesitan acceder a servicios de su red de forma remota sin importar la IP de esta.

 

 

Protocolos TCP y UDP

En conjunto con el protocolo IP conforman el núcleo principal de prácticamente todas las redes existentes a día de hoy, recordemos que estamos usando el modelo TCP/IP, luego el protocolo TCP seguro que jugará un papel importante.

Estos dos protocolos serán básicamente los dos únicos protocolos a nivel de transporte que vamos a tener. Podríamos añadir en todo caso SCTP usado para streaming, pero vamos… el 99% de todo el tráfico se gestiona por uno de estos dos protocolos. Recordemos que el nivel de transporte será quien establezca una comunicación entre aplicación origen- aplicación destino (en los niveles inferiores en realidad las comunicaciones son entre nodos). La idea es proveer a la comunicación con ciertos mecanismos como el control de flujo, detección de errores y otras cuestiones que iremos viendo.

Como hemos dicho veremos dos protocolos tan solo:

  • UDP (User Datagram Protocol)
  • TCP (Transmission Control Protocol)

Vamos a ver primero UDP por su gran sencillez, sería prácticamente la mínima expresión. A partir de este no obstante es mucho más simple comprender un protocolo bastante más complejo como TCP. Pero antes de entrar en los protocolos en sí hay que hablar de los puntos de accesos a estos, dado que será algo primordial para estos: Los puertos.

 

Puertos:

De cara al modelo TCP/IP o modelo OSI, los puertos serían los SAP del nivel de transporte, los puntos de acceso. Visto de forma más práctica los puertos permiten conexiones múltiples simultáneas entre distintos o iguales hosts sin que ninguna conexión interfiera en la otra. Visto de un modo más simple aun, los puertos serían las diferentes entradas/salidas en las comunicaciones.

Cuando un host desea enviar un mensaje a otro por medio de TCP o UDP primero debe de solicitar al OS un puerto de salida por el cual poder realizar la comunicación. Del mismo modo que necesita de un puerto de salida, dicho mensaje deberá de especificar ya no solo el destino (la IP o el nombre de host), sino el puerto al que quiere acceder en dicho host e informar al destino de puerto de salida que está usando para la comunicación, a fin de que el destino pueda contactar del mismo modo con el emisor. La necesidad del puerto de salida es clara, por algún lado tiene que salir el mensaje. ¿Pero y el puerto de entrada? En realidad es igualmente importante, ya que tanto puertos de entrada/salida se asocian generalmente a servicios/aplicaciones concretas. Es decir, gracias a estos puertos ya no solo debemos de especificar un host destino, sino que dentro de este, a que servicio o aplicación deseamos enviarle el mensaje.

Estos puertos se identifican como un número entero sin signo de 16 bits, es decir, un número comprendido entre el 0 y el 65535. Estos números hacen de ID de puerto por así decirlo. Estos puertos no son compartidos es decir, existirán por tanto 65536 puertos para TCP enumerados de 0 a 65535 y otros tantos para UDP enumerados exactamente igual, es por ello que el número del puerto no especifica si es UDP o TCP, esto es importante.

Como he dicho el 99% de todas las comunicaciones que hacemos se basan en este concepto, aun cuando no lo sepamos porque el proceso sea transparente a nosotros. El mejor ejemplo de esto es por ejemplo la navegación web. Hemos hablado de la necesidad de la IP o de las DNS, pero nadie ha visto en ningún momento nada parecido a un puerto o a un número que no sea la IP y que podamos imaginar que es un puerto. Pero esto es porque los navegadores lo hacen de forma implícita. Cuando en un navegador especificas por ejemplo “http://” estás especificando el protocolo http que por defecto (no significa que no pueda ser otro) se le asocia el puerto 80. Es decir, si en el navegador accedemos a la web http://www.google.es se realizará una petición al host www.google.es por el puerto 80 TCP, y con puerto no me refiero al puerto de salida de nuestro host, sino el puerto destino del host remoto.

Esto de que el puerto 80 esté asociado a los servidores web es así porque la IANA estableció que el puerto 80 sería el puerto “conocido” para el servicio web. En realidad la IANA mantiene un extenso listado con todos los puertos “conocidos”, así como los puertos registrados. Pero esto no quiere decir que los servicios de dicha lista se deban de asociar a dichos puertos, dado que un administrador de sistemas tiene siempre la última palabra sobre qué puerto asociar a que servicio. De todos modos esto tiene su lógica. Si se establece que el puerto para web será el 80, cualquier aplicación estará configurada para ello y no será necesario conocer en cada ocasión el puerto, lo mismo sucede con infinidad de puertos. Otras veces en cambio lo deseable puede ser exactamente lo contrario, y por motivos de seguridad no queremos asociar un servicio a su puerto preestablecido.

Se podría decir que generalmente tan solo los puertos de destino suelen tener un servicio asociado, pero esto sería incorrecto dado que un puerto de entrada se convierte en puerto de salida cuando tiene que enviar un mensaje. Así que podríamos matizar diciendo que generalmente los puertos de salida al iniciar la comunicación no suelen estar asociados. Por ejemplo, si realizamos una petición http al servidor web de google, sabemos que debemos de enviarla al puerto 80 TCP, ¿pero por qué puerto saldrá el mensaje de nuestro equipo? podríamos pensar en primer lugar que por el mismo puerto, que por el 80, pero esto no es así, el puerto 80 lo usaríamos para enviar datos (lo normal claro) tan solo de tener instalado un servidor web. Luego… ¿qué puerto se usará de salida? En este caso lo normal es que el navegador solicite una conexión de salida al OS, y sea el propio sistema quien le asigne un puerto que en ese momento no esté en uso para realizar dicha conexión, posiblemente entre un rango de puertos ya preestablecidos. Es decir, cada comunicación que hagamos incluso para navegar, el puerto de salida de nuestro mensaje será diferente casi el 100% de las veces. Es más, ahora mismo por ejemplo mi navegador Firefox mantienen de forma simultanea 5 conexiones activas, usando los puertos de salida 44384, 44385, 44387, 44388 y 44389, pero esto es en este mismo instante!! en cuanto la conexión TCP finalice y se abra una conexión TCP nueva, se le asignará un nuevo puerto de salida, y así el navegador quedará mientras dure la conexión “a la escucha” de dicho puerto preparado para recibir cualquier información que entre por él, que es de suponer que el mismo navegador estará esperando. Evidentemente los puertos que ya no están en uso se reutilizan sin problema alguno.

Podemos decir también que un puerto tiene 2 estados fundamentales, Abierto y Cerrado. Para que un puerto pueda enviar/recibir información, debe de estar abierto, es decir, algún servicio o programa asociado a él. Cuando en el ejemplo anterior nuestro navegador tiene que comunicarse con el puerto 80 TCP de un servidor web, antes de poder realizar la conexión el OS asocia a dicha aplicación (Firefox) el puerto temporal para la comunicación, digamos que el puerto queda abierto. Al otro lado en cambio, el puerto 80 del servidor web estará permanentemente abierto a la espera de cualquier comunicación externa entrante, el puerto 80 en este caso estará asociado a por ejemplo un servidor web Apache o IIS. En cambio, el puerto temporal abierto por el OS para Firefox para dicha conexión estará abierto tan solo el tiempo que dure la comunicación, cuando esta finalice, el puerto se cerrará. Esto es muy importante de cara a la seguridad como se verá en otro momento.



UDP:

Es un protocolo no orientado a la conexión, es decir, no provee ningún mecanismo de control de flujo, ni tampoco implementa ningún sistema propio de detección de errores o de pérdida de mensajes/datagramas (en nivel 4 no se puede hablar ya de paquetes, que es propio del nivel 3). Aunque en realidad el término “orientado a conexión” hace referencia a que no es necesario una negociación previa entre los dos dispositivos para comenzar la comunicación. Cuando tratamos con UDP debemos de tener claro por tanto que a este protocolo no le importa si se pierden datos en el camino, es más, el destino puede incluso estar saturado o colgado y UDP no tendrá constancia de ello, como si el puerto de comunicación está abierto o simplemente no es válido.

Esto parece tener muchos inconvenientes, pero en cambio todo depende de la aplicación que necesite enviar los datos o qué tipo de datos sean. Por ejemplo, la corrección de errores o el control de flujo puede implementarse a nivel de aplicación, o simplemente la pérdida de datagramas podría no ser importante, cosa muy habitual por ejemplo en aplicaciones en tiempo real como juegos online, Streaming, VoIP… ¿Pasa algo si 1 de cada 1000 datagramas se pierde en una videoconferencia? Pues la verdad es que prácticamente no afecta absolutamente en nada, a lo mejor vemos en ese momento un punto de otro color en la imagen recibida de la webcam del otro usuario, o puede que la conversación tenga un poco de más ruido de fondo, pero para nosotros es mucho más importante la fluidez de la conversación a la calidad de esta. Puede que UDP tenga muchos puntos negativos, pero no hay que verlo como negativos, sino como características, que dependiendo de la situación son mucho más deseables que otras. ¿Cuál es el objetivo por tanto de UDP? es fácil, la transmisión rápida de datos, la sencillez de la comunicación, en que prácticamente no hay que ocuparse de nada.

Hay que tener en cuenta que cuanto más complejo es un protocolo más sobrecargado está, y esto tiene un impacto notable en el uso de las redes. Imaginar que solo quiero enviar la palabra “Casa” a otro host. Con UDP me vasta dos datos y medio y lo envío. En TCP como ya veremos tendríamos que negociar la conexión, enviar los datos, cerrar la conexión… y todo ello además con cabeceras mucho más grandes en fin.. que a lo mejor en vez de enviar 20 bytes tendríamos que enviar 200 bytes para la misma tarea.

Como hemos dicho UDP no requiere del establecimiento de una conexión previa, de ningún sistema de acuerdo entre los dos hosts. Si un host quiere enviar un mensaje UDP a otro, tan solo tiene que (a nivel de transporte claro está) rellenar la cabecera UDP y adjuntar los datos que quiera:

Puerto de Origen

Puerto de Destino

Longitud

Checksum

  • Puerto de Origen/Puerto de Destino (16 bits cada uno): Especifica el puerto de origen y el puerto de destino del mensaje UDP. Al ser un número de 16 bits se infiere que tendremos un máximo de 65536 puertos posibles
  • Longitud (16 bits): Es un registro ya típico, en este caso especifica la longitud en bytes de todo el mensaje UDP, incluyendo tanto cabecera como el SDU del nivel superior, es decir, los datos realmente. Hay que recordar que cada nivel normalmente añade/elimina su propia cabecera a los datos recibidos y los envía hacia abajo o hacia arriba en el modelo TCP/IP. Dado que la cabecera tiene un tamaño fijo de 64 bits, la longitud mínima para un mensaje UDP sería 8 Bytes, es decir, un mensaje UDP vacío. Por la misma razón, la máxima cantidad de datos que se pueden enviar por un mensaje UDP sería 64K menos 8 Bytes.
  • CheckSum (16 bits): La detección de errores en este caso es un poco peculiar, y además, en IPv4 es opcional (obligatoria en IPv6, recordemos que IPv6 NO tenía comprobación de checksum a nivel de protocolo IP). El algoritmo que usa es exactamente el mismo que el que se realiza en IP, se realiza el complemento a uno a la suma en complemento a uno resultante de cada palabra, pero en este caso no se hace sobre la cabecera de UDP, sino sobre la llamada pseudo cabecera UDP. Esta cabecera en realidad no existe, tan solo es una composición que se crea para crear el checksum. Esta cabecera está compuesta por la IP de origen, la IP destino, un byte de ceros, un registro que especifica el protocolo y otro registro que especifica la longitud del mensaje UDP, es decir, esta cabecera virtual toma algunos elementos de la cabecera IP. Pero repito, tan solo se “construye” esta cabecera para calcular el checksum, esta cabecera como tal no existe, no se transmite.

Eso es todo. Es la mínima expresión, una cabecera con lo mínimo, en que lo más “complejo” puede ser el checksum y que ni siquiera es obligado en IPv4. Después de la cabecera evidentemente se adjuntarían los datos del nivel superior, el SDU, que junto a la cabecera conformarían el 4PDU, el mensaje UDP completo que pasaría al nivel de red (en caso de que se esté enviando).

¿Cuál es el mejor ejemplo de mensaje UDP? Los mensajes DNS, DNS se transmite por medio de mensajes UDP. Qué pasa si se pierde un mensaje DNS? Pues posiblemente que si el navegador o el host tenga un tiempo de espera predeterminado para la petición DNS, si no recibe la respuesta casi de inmediato, enviará casi seguro una segunda o una tercera petición. Pero no es algo que requiera una integridad especial o una complejidad enorme. Además, son mensajes que se están retransmitiendo constantemente. Usar TCP para mensajes tan cortos sería hacer un uso enorme de la red tan solo para las peticiones DNS. Con UDP funcionan el 99% perfectamente, y hacen un uso muchísimo más optimizado de la red. Además, cuanto más pequeños sean los mensajes, menor probabilidad de errores existirá en su retransmisión.


TCP:

Es todo lo contrario a UDP. Para empezar, es un protocolo orientado a conexión, es decir, requiere del establecimiento previo de una conexión antes de poder comenzar a retransmitir datos. Es infinitamente más complejo que UDP, pero por otro lado TCP hace posible comunicaciones fiables, tolerantes a fallos, con una buena gestión del control de flujo… aunque todo ello requiere por ende un protocolo más complejo, una cabecera más grande y una menor cadencia a la hora de transmitir datos en definitiva.

Al igual que le pasara a UDP, no se puede ver esto como algo negativo, sino como algo necesario para poder tener una comunicación fiable para aplicaciones que así lo requieren. Posiblemente el caso más ilustrativo sería la navegación web por ejemplo. Una web puede pesar considerablemente, desde unos KBs a MBs de datos. Que importa en este caso gastar unos KBs de más si nos garantizamos que el navegador recogerá correctamente la información del servidor opuesto. Pensar cuando enviamos un formulario (al margen de que se pueda enviar o no por protocolos seguros como TLS/SSL), no podemos permitirnos en modo alguno que al servidor no le llegue un mensaje TCP correcto, dado que ese mensaje podría ser desde un número diferente en el DNI, en el nombre o en cualquier otro lugar. Recordar que protocolos como UDP no tienen siquiera ningún mecanismo para saber si los datos han llegado o no, mucho menos si lo hicieron correctamente. En la mayoría de las comunicaciones necesitamos saber que los datos se han enviado correctamente o se han recibido sin errores.

Existen pues muchas aplicaciones que hacen uso de ambos protocolos, por ejemplo la mayoría de programas P2P o juegos online. ¿Por qué? Habilitan por ejemplo un puerto UDP para maximizar el envío/recepción de datos, y se usa la misma aplicación para controlar que estos lleguen en buen estado. Pero a la par se usa un puerto TCP para aquellas cuestiones que si requieran precisión, normalmente pequeños mensajes, pero que sí necesitamos conocer que han llegado y en buen estado:

 

Puerto de Origen

Puerto de Destino

Número de Secuencia

Número de ACK

Offset

Reservado

U

A

P

R

S

F

Ventana

CheckSum

Puntero “Urgente”

Opciones

Padding

 

  • Puerto de Origen/Destino (16 Bits cada uno): Tiene exactamente el mismo uso que el citado en el protocolo UDP, especifica mediante un entero sin signo el puerto de origen que usará el mensaje TCP, así como el puerto destino al que va dirigido.
  • Número de Secuencia (32 bits): Recordemos que TCP posee funciones de control de flujo, esto significa que de algún modo cada mensaje enviado tiene que ser claramente identificable de otro. Esto quiere decir que si dos mensajes TCP llegan al destino de forma desordenada, el host receptor podría ordenarlos perfectamente dado el número de secuencia. Del mismo modo si se recibe un mensaje cuyo número de secuencia no concuerda con el esperado, el mensaje podría descartarse por interpretar que dicho mensaje es ajeno a la comunicación actual entre los dos hosts, por ejemplo un mensaje inyectado desde un tercer host que intentase manipular la conversación entre ambos. Si el flag Syn (S) no está especificado, será el número de secuencia del primer octeto (byte) de datos adjuntos en dicho mensaje (después de toda la cabecera). En cambio, si el flag Syn está habilitado, el primer octeto adjunto en dicho mensaje será el número de secuencia + 1.
  • Número de ACK (32 bits): La gran mayoría de las veces, para nosotros un ACK será un mensaje o paquete de confirmación. Este tipo de mensajes son muy comunes en gran multitud de protocolos, son como pequeñas señales de respuesta para indicar que se ha recibido la información. Gracias a estos mensajes también solucionamos el problema de conocer si un mensaje llega correctamente o no a su destino, dado que si llega, el destinatario nos responderá con un ACK (ACK proviene de Acknowledgment). Por ello, si el flag ACK (A) está activado, el número de ACK corresponderá al próximo número de secuencia del mensaje que espera recibir por parte del emisor. Es decir, en el caso de que la comunicación sea correcta, si un host envía un ACK con número de ACK “200″, significará que está esperando que el otro host le envíe un mensaje (del tipo que sea) con un número de secuencia de 200.
  • Offset (4 bits): El número de bloques de 32 bits que ocupará la cabecera, por tanto indica cuando empiezan los datos (el SDU). Como ya se viese en el protocolo IP, para que este tipo de registros sean posible es necesario que la cabecera siempre sea múltiplo de 32 bits, lo cual se hace con un padding, puesto que existen campos en la cabecera de longitud variable.
  • Reservado (6 bits): bits reservados, se deben de establecer a cero.
  • Flags (1 bit cada una): Los flag o banderas son bits que básicamente dicen cuando un flag está activado o no. Cada uno de esos bits especifican algo concreto:

    URG (U): Usado conjuntamente con el campo “Puntero Urgente” para especificar que existe un dato en el mensaje que debe de ser procesado con anterioridad.
    ACK (A): Usado conjuntamente con el número de ACK para indicar una contestación, como ya se ha explicado.
    PSH (P): Esta señal está relacionada directamente con la ventana del protocolo TCP que se verá a continuación. Si el flag PSH es especificado, el mensaje por pequeño que sea será enviado.
    RST (R): Básicamente es una bandera que de habilitarse indica al otro host que reinicie la comunicación, algo así como un reset de la sesión.
    Syn (S): Formalmente realiza la sincronización del número de secuencia. El primer mensaje enviado por cada una de las partes al otro tendrá activada el flag Syn, es decir, al inicio de la comunicación.
    FIN (F): Se usa para comenzar o forzar el cierre de la sesión. Técnica significa que no serán enviados más datos por parte del emisor.


  • Ventana (16 bits): Especifica en Bytes el tamaño de la ventana de recepción. Es decir, el tamaño máximo (comenzando desde el número de secuencia de ACK) de datos que puede recibirse en una comunicación TCP, antes de contestar con un ACK. En realidad esta ventana no es más que un buffer, cuyo tamaño queda especificado por este campo. Cuanto mayor sea el tamaño de ventana se obtendrá una mayor cadencia en los datos (el término exacto es throughput, pero creo que no existe un equivalente exacto en español). En contra partida, una ventana grande es perjudicial cuando la calidad de la red no es demasiado buena, puesto que en caso de error (por pequeño que sea), se requerirá enviar de nuevo toda la ventana completa, repercutiendo negativamente en el rendimiento. No es lo mismo a fin de cuenta enviar un mensaje de 1 byte en un byte, teniendo en cuenta que entre byte y byte hay que responder con un ACK, que enviar un mensaje en bloques de hasta 64KB, lo cual es muchísimo más eficiente… aunque menos seguro y menos fiable.

    A día de hoy cada vez se está optando por incrementar casi al máximo las ventanas de recepción, o en caso de Windows por ejemplo permitir al propio OS establecer de forma dinámica el tamaño de esta en función de la calidad de la comunicación y otros factores.


  • CheckSum (16 bits): El sistema de comprobación de errores de TCP es el mismo que el que se explicó en UDP.
  • Puntero Urgente (16 bits): Especifica un desplazamiento de Bytes (comenzando desde el número de secuencia) en el que se encuentra el primer byte que se ha tipificado como “mensaje urgente”
  • Opciones y Padding (Variable): Especifica una serie de opciones que pueden añadirse antes del SDU. Dado que se debe de conservar la divisibilidad entre 32 Bits, se usará un padding rellenando de ceros para cubrir siempre cualquier pico que pudiese existir en dichas opciones.

Es evidente que la complejidad aquí es mucho mayor que en UDP. Describir el funcionamiento de todo el protocolo sería algo inviable, y para eso están las especificaciones oficiales en el RFC 793. No obstante, aunque no se explique cada uno delos posibles casos pueden darse en una comunicación TCP, si es interesante ver a groso modo como se llevaría a cabo una comunicación modelo, sin entrar en demasiados detalles, en lo que sería el establecimiento y cierre de la comunicación. Como digo esto es tan solo una pequeña parte de todo el protocolo TCP, se pueden presentar un millón de posibilidades y de comportamientos anómalos en la conexión y la respuesta de cada host a dicho comportamiento está en algunos casos especificados y en otros no. De todos modos, esto se podrá ver en otros temas, como por ejemplo en los escáneres de puertos, donde es muy importante conocer el funcionamiento de estos protocolos:

 

Sabiendo los registros de la cabecera, se puede más o menos inferir las características de TCP. Por ejemplo, la fiabilidad en los datos enviados/recibidos queda asegurada gracias a los números de secuencia, por los cuales es posible conocer el orden incluso en el que deben de llegar los mensajes, o en caso de que un mensaje no sea recibido el host emisor puede ser informado sobre ello para reenviar de nuevo el mensaje perdido. El número de secuencia de ACK tiene un cometido similar, dado que si el emisor no recibe el ACK de un mensaje que ha enviado, puede interpretar que el mensaje no ha sido recibido y podría enviarlo de forma automática de nuevo, mientras que de cara al receptor si le llegan dos mensajes con el mismo número de secuencia (por ejemplo porque el emisor ha reenviado el mensaje y el primero no llegó por una latencia excesiva de la red) ignoraría simplemente el segundo, siempre y cuando el número de secuencia fuese correcto, si recibe un número de secuencia erroneo simplemente descartaría el mensaje.

Por otro lado, el uso de una ventana (buffer) también garantiza un correcto control de flujo, mientras que técnicas como los algoritmos de congestión de red hacen posible que la comunicación sea todo lo fluida que se pueda cuando la intensidad del tráfico amenaza la comunicaicón. Estos algoritmos se basan simplemente en los mismos flags de las conexiones TCP para ajustar ciertos parámetros como la ventana de recepción, el tamaño máximo del mensaje (especificado en las extensiones de la cabecera TCP) o la gestión de ACKs. Por ejemplo, el algoritmo de congestión que puede usar Windows Vista/7 se llama Compound TCP. Este algoritmo posee dos ventanas, las cuales aumentan en tamaño o disminuyen en función del retraso en las comunicaciones. De forma similar actáa por ejemplo el protocolo de congestión por defecto de Linux: TCP Cubic. A la par que las comunicaciones son más rápidas y fiables, es normal que los algortimos de congestión usados vayan cambiando con el tiempo, dado que el que es bueno ahora no lo será mañana.

 

 

Protocolo Ethernet y ARP

Llegados a este punto sería conveniente hablar de Ethernet, aunque sin entrar en mucho detalle sobre este. Ethernet es un protocolo… una tecnología para redes locales. Al ser un protocolo de nivel 1 y 2, tiene más componentes físicas que informáticas. Por ejemplo, Ethernet tiene sus propios estándares para cables que pueden usarse, conectores, hardware… cuestiones que podrían ser interesantes ver, pero que se escapan al alcance de este capítulo. Ahora veremos Ethernet como el protocolo de nivel más bajo que tendremos dentro del modelo TCP/IP o modelo OSI, y será la misma tecnología Ethernet y sus protocolos los que convertirán al final los datos en meras señales eléctricas que serán transmitidas por un cable.

Desde el punto de vista físico, para nosotros tan solo nos interesa conocer cuestiones como la velocidad, modo de funcionamiento y tipo de medio. Desde el punto de vista lógico nos interesa no obstante conocer la estructura de un frame ethernet.

Físicamente para nosotros podemos diferenciar 3 estándares atendiendo a la velocidad de enlace de Ethernet: Ethernet, Fast Ethernet y Gigabit Ethernet, La diferencia de ellos es por tanto el ancho de banda posible. ASí, Ethernet tiene una capacidad máxima de transmisión de datos de 10Mb/sec (ojo!! Megabits, no MegaBytes), Fast Ethernet 100Mb/s y GigaEthernet una capacidad de 1000Mb/s. Actualmente existen estándares menos usados domésticamente como 10 GigaEthernet o 100 GigaEthernet, cuyos nombres son completamente descriptivos.

De cara al medio, estamos acostumbrados a ver Ethernet siempre usado sobre el famoso cable “Categoría 5e” y conectores RJ45. Este cables son a groso modo 4 parejas de hilos trenzados. Pero esto es solo una de las especificaciones de Ethernet, ya que en realidad Ethernet puede ser usado no solo sobre estas parejas de hilos trenzadas, sino por ejemplo sobre fibra óptica también. Lo que sucede es que los cables de hilos trenzados son infinitamente más baratos que otras infraestructuras como pueda ser la de fibra óptica, por no hablar de la facilidad de crimpar (añadir un conector a un extremo de un cable) a un cable de hilos trenzados a uno de fibra, o la flexibilidad de uno y de otro. Actualmente sobre hilos de cobre trenzados es posible llegar hasta 10GigaEthernet, mientras que sobre fibra hasta los 100GigaEthernet. De todos modos, lo más común, barato y cómodo para un usuario doméstico son los estándares 100BaseT y 1000BaseT, es decir, Fast Ethernet y Giga Ethernet sobre cables de cobre trenzados. En el caso de 100BaseT se usarán 4 hilos en total de un cable de pares trenzados Categoría 5 como mínimo, mientras que en redes GigaEthernet requeriremos de los 4 pares de hilos de un cable Categoría 5e o Categoria 6. En ambos casos, el estándar asegura una longitud máxima de cable entre nodos de 100 metros, a partir de los cuales sería necesario regenerar la señal. Como nota personal, en entornos especialmente ruidosos o cuando dichos cables serán usados externamente, recomendaría que los cables fuesen apantallados para aislar mejor las interferencias, aunque esto es tan solo opcional.

Desde el punto de vista del modo de funcionamiento, tan solo decir que Ethernet puede funcionar tanto en Half-Duplex como en Full-Duplex. Esto se verá más en detalle en otro capítulo cuando se vean Hubs y Switchs.

Desde un punto de vista lógico tenemos que ver como es un frame Ethernet, y teniendo en cuenta los diferentes protocolos que hemos visto hasta ahora, Ethernet no supondrá mayor problema. Un frame Ethernet II (los frames usados a día de hoy) no poseen otra cosa que la dirección MAC origen y destino, el protocolo superior que lo usará, los datos que portará y un checksum:

Cuando se trató el protocolo IP se mencionó MTU como unidad máxima de transmisión, que es una limitación de la red y no del mismo protocolo IP, ya que el protocolo IP podía incluir paquetes de hasta 64KB. Pues bien, ese MTU proviene de los niveles inferiores, en caso de usar redes Ethernet dicha limitación procede de aquí. ¿Por qué dijimos que lo normal para conexiones ADSL es un MTU de 1492 Bytes? El 99% de las redes locales domésticas son redes Ethernet. Como podemos apreciar perfectament en la imagen superior, los frame Ethernet tienen un tamaño mínimo de 64 bytes y un tamaño máximo de 1512 Bytes. De esos 1512 Bytes, 1500 son los reservados para los datos adjuntos. Dado que nuestros equipos se comunican principalmente por cable a nuestros routers, estos enlaces son Ethernet con un MTU de 1500. Pero por otro lado, la mayoría de nuestras conexiones ADSL están apoyadas por el protocolo PPPoE (Punto a Punto sobre Ethernet), el cual (el protocolo) tiene una cabecera de 8 Bytes. Es decir, el tamaño máximo de los datos que pueden enviarse por medio de una conexión ADSL mediante PPPoE debería de ser exactamente 1492, dado que PPPoE usa frames Ethernet. Ahora bien, esto no quiere decir que un MTU de 1942 para conexiones ADSL PPPoE sea el óptimo, pero explicar esto implicaría de nuevo salirnos del ámbito de este capítulo.

Hay que tener bien presente que estos frames existen tan solo para nosotros, para nuestra red local Ethernet, y en el caso específico de las conexiones ADSL PPPoE. Siempre que usemos un Sniffer para ver que tipos de frames nos están llegando hay que comprender bien esto, dado que podemos ver solo lo que llega a nuestros equipos, no como dichos datos son transportados desde un punto del planeta a otro, hablamos por tanto en este caso de un protocolo de puertas para dentro.

De la cabecera Ethernet II anterior, EtherType especifica el protocolo inmediato contenido en los datos adjuntos. Así por ejemplo, para un paquete IPv4, EtherType tendrá un valor de 0×0800, 0x86DD para IPv6, 0×8863 y 0×8864 para PPPoE, o un valor de 0×0806 si es el protocolo ARP. Para quien quiera una lista completa puede verla en el estándar de la IEEE de los tipos de redes Ethernet


Una dirección IP es una dirección lógica asociada a un host, mientras que una dirección MAC es una dirección “física”. Quizás el término dirección física no sea realmente correcto, pero sí podemos decir que una dirección MAC especifica inequívocamente una interfaz NIC (o al menos debería). Tal y como se plantea toda la red de Internet, así como los protocolos TCP/IP y DNS, parecerá innecesario un protocolo como ARP, pero sin embargo es un protocolo crucial, sobre todo dentro de redes locales como las redes Ethernet (casi todas las redes locales).

Gracias al protocolo IP podemos encontrar en el globo un host simplemente conociendo su dirección IP. Pero esta dirección no es más que una dirección lógica. En IPv6 esto es diferente dado que la asociación IP-NIC es casi estructural, pero en IPv4 esto no es así ni mucho menos. Volviendo al tema principal, puede que una dirección IP especifique un host en internet, pero… ¿Como saben los equipos o los routers a que interfaz de red enviar dichos paquetes? Es importante conocer siempre lo que pueda ser la parte física de una comunicación a la parte lógica. Podemos pensar en la parte física aquello que podemos tocar o ver: Cables, Routers, Switchs, Bridges, Interfaces de Red (NIC)… hardware a fin de cuenta. En cambio, en la parte “lógica” tendríamos fundamentalmente los protocolos de comunicación que funcionan sobre esa parte física, y en última instancia bits de datos que circulan de un lado a otro. Pues bien, en algún punto por tanto es necesario unir esa parte física con esa parte lógica, y el protocolo ARP se encarga de ello, al menos en cuanto a conocer el origen/destino de un paquete IP.

El protocolo ARP será el encargado por tanto de conocer el host físico emisor/receptor de un paquete por medio de su IP, dicho de otro modo, el protocolo ARP se encargará de saber las direcciones MAC de las NIC. El protocolo IP trabaja en el nivel 3 del modelo OSI (nivel de red), TCP/UDP son protocolos del nivel 4 (de transporte), mientras el protocolo DNS es un mensaje concreto UDP (luego es un protocolo a nivel de aplicación). ¿A que nivel pertenece por tanto ARP?

El problema del ámbito de ARP no es nuevo. En teoría es un protocolo a nivel de enlace de datos (nivel 2), pero no obstante para que ARP pueda trabajar correctamente necesita tener acceso al nivel 3 para conocer la IP. Si vemos esto desde un modelo OSI estricto, ARP quedaría fuera de este, dado que requeriría acceder a ambos niveles, lo cual violaría los principios del modelo OSI. Pero por un lado el modelo usado actualmente es TCP/IP, y por otro podríamos ver el modelo OSI como algo más flexible. Otros expertos concluyen que aun cuando el modelo OSI fuese completamente fijo e inflexible, ARP no violaría el modelo, dado que su función es meramente de nivel de red, con la única salvedad de que porta datos pertenecientes a IP, y que por tanto ARP es un protocolo de nivel 2. Personalmente creo que las dos opciones son correctas. No se puede ver el modelo TCP/IP u OSI como algo completamente rígido, y tampoco podemos pensar en que un frame solo puede contener datos propios. Quizás el ejemplo más significativo estaría en el protocolo ICMP. Sin entrar en detalle a explicar este protocolo, ICMP depende y se apoya sobre IP, con lo que debería de ser un protocolo superior a IP, pero en realidad no presta ningún servicio de transporte o de nivel superior. ICMP es un protocolo puramente de nivel 3, aunque necesite o se apoye en IP. Bueno, de forma similar podríamos ver ARP. Para mi por tanto ARP es un protocolo de nivel de enlace de datos (nivel 2), pero quizás sería correcto decir que es un protocolo tanto de nivel 2 como de nivel 3.

 

¿El problema?

La finalidad de ARP queda clara. Un protocolo que permita extraer de algún modo de la dirección física MAC de un host. ¿Por qué es esto estrictamente necesario? La mejor forma de ver esto es intentar componer la red TCP/IP más sencilla que pueda existir, para evitar pensar en routers, hubs u otros elementos de red: Dos hosts conectados uno a otro por un cable Ethernet. Imaginar por tanto que disponemos de dos host configurados manualmente y conectados por un cable de red, formando entre ambos equipos una red muy simple. El host A se configura para tener una dirección IP 192.168.0.1 y el host B para tener la dirección 192.168.0.2. Si lo vemos de una forma completamente lógica, decimos simplemente que el host A se comunica con el host B enviando los paquetes IP a la dirección 192.168.0.2. ¿Pero como sabe el host A quien es el host B? Visto desde un punto de vista completamente físico, la tarjeta de red del host A tan solo sabe que ella tiene una dirección física por ejemplo de 00:00:00:00:00:01, a la cual hay conectada un cable por el cual enviar o recibir datos, y lo mismo para el host B, 00:00:00:00:00:02. Los adaptadores de red no tienen por qué entender de IP, recordemos que Ethernet es un protocolo de nivel 2. En última instancia, el adaptador de red simplemente pone los datos que sean en las lineas de transmisión del cable y listo. En este caso es simple, dado que tan solo hay un equipo conectado al otro extremo, los datos enviados por A llegarán siempre al equipo B. El host B cuando recibe lo que sea por su interfaz de red podría simplemente tomarlo por bueno y tomar cualquier dato que llegue por él como válido y procesarlo. En este caso no haría falta siquiera conocer direcciones físicas. Pero que sucede si creamos una red en vez de dos equipos de tres?

Imaginar que a los dos equipos antes mencionados incluimos un Host C con dirección física 00:00:00:00:00:03. ¿Como? En el caso más simple de todos esto se haría con un dispositivo de red conocido como Hub. Básicamente los Hub conectan todos los diferentes hosts conectados a él entre sí de una forma muy simple. Un cable/interfaz Ethernet o Fast-Ethernet tiene dos lineas para transmitir datos y dos para recibir, pues el hub lo que hace es conectar internamente las dos líneas de transmisión de datos de cada cable con las dos de recepción de los otros. Es decir, cuando el host A envíe un paquete, este será recibido tanto en B como en C, y exactamente lo mismo para cualquier paquete enviado por B o por C. El problema es evidente, ante esta situación ya no basta simplemente con poner el dato en el cable y dejar que los hosts tomen por bueno y procesen el dato. Por otro lado cada host puede tener una IP diferente sí, pero como hemos dicho los adaptadores de red no tiene por qué saber nada de IP, y por otro lado las aplicaciones no entienden de direcciones MAC, solo de paquetes IP.

 

¿La solución?

Si al enviar el dato que sea desde A especificamos la dirección MAC destino (es decir, el adaptador de red a quien está destinado dicho frame), esta dirección o ID si puede ser comprobada/verificada por el adaptador de red. En este caso del Hub, tanto B y C recibirán un frame de A, pero el frame de A especificará que el destino será 00:00:00:00:00:02, con lo que el host C simplemente ignorará el frame, puesto que la dirección MAC no es la suya. Con esto podría parecer que el uso de IP es innecesario, pero recordemos que la función de un protocolo de nivel de red es completamente diferente a un protocolo de nivel de enlace de datos. IP hablará con todos los protocolos superiores, mientras que Ethernet es un protocolo de bajo nivel. Visto esto vemos la necesidad de las direcciones MAC, pero no del protocolo ARP. Pues bien, se ha dado por echo que el host A conoce la dirección MAC del host B, lo cual puede ser que la conozca o puede ser que no la conozca. Si arrancamos en frió todos los dispositivos, la única forma que el host A conozca la dirección MAC de los otros host y viceversa es manteniendo un archivo local en cada equipo que especifique dichas direcciones. Esto ya vimos en DNS que no aceptable en ningún modo, hace falta un protocolo que se encargue de dicha tarea.

Cuando un host no posea la dirección mac de otro, necesitará realizar una petición ARP para conocer dicha dirección. ARP tiene tan solo dos métodos de funcionamiento: Enviar peticiones y Enviar respuestas. El procedimiento base es muy simple, si necesita conocer la MAC del host B (del cual evidentemente conoce la IP, dado que el mismo paquete IP especifica dicha IP), enviará una petición a la dirección física de broadcast de la red con la solicitud. Todos los host recibirán Y ATENDERÁN la petición puesto que la dirección física a la cual está destinado el frame son TODOS los host, pero tan solo el host B contestará a ella, dado que dicha petición especifica la IP del host B. La respuesta de B por otro lado será dirigida directamente a A, dado que en la misma solicitud se incluye la dirección MAC del host A. La respuesta llegará a todos los host (estamos usando un hub), pero estos no la procesaran porque la dirección MAC especificada en el frame será la de A. A recibirá la contestación por parte de B con un frame que contendrá la dirección física de B, y el host A podrá actualizar su caché ARP, donde almacenará la asociación IP host B -> MAC host B.

Lo primero será por tanto conocer la estructura de este frame un tanto especial, ya se ha dicho que aun siendo (a mi juicio) un protocolo de nivel 2, lleva consigo una IP:

 

Tipo de Hardware
Tipo de Protocolo
Long. Dirección HardwareLong. Dirección del Protocolo
Operación
Dirección Hardware del Origen
Dirección del Protocolo del Origen
Dirección Hardware del Destino
Dirección del Protocolo del Destino

Hay que tener en cuenta que ARP depende de dos protocolos, el superior y el inferior. Para nosotros, ARP será usado extensamente en redes IPv4 sobre Ethernet, pero esto no quiere decir que son los únicos protocolos con los que podría funcionar ARP.

  • Tipo de Hardware (16 bits): Especifica el hardware del nivel inferior que será usado. En caso de redes Ethernet, el valor de dicho campo será un 0×0001
  • Tipo de Protocolo (16 bits): Especifica el protocolo superior al que referenciará, en caso del protocolo IP el valor de dicho campo será de 0×0800
  • Long. Dirección Hardware (8 bits): Especifica el tamaño en bytes que ocupará una dirección del tipo hardware especificado en el campo “Tipo Hardware”. En caso de redes Ethernet, las direcciones MAC tienen un tamaño de 48 bits, luego este campo estará fijo en 48/8 = 6 Bytes -> 0×06
  • Long. Dirección del Protocolo (8 bits): Especifica el tamaño de la Dirección del protocolo de nivel superior, en nuestro caso una dirección IPv4 tiene una longitud de 32 bits -> 32/8 = 4 Bytes -> 0×04
  • Operación (16 bits): Especifica el modo de operación del protocolo ARP. Ya se dijo que ARP actúa o realizando una petición (Request, un valor de 1 en dicho campo) o respondiendo a una (Reply, con un valor de 2 en dicho campo)
  • Dirección Hardware/Protocolo Origen/Destino (variable): Dado que el hardware y el protocolo sobre los cuales ARP va a funcionar puede ser diferente, estos campos no tienen una longitud fija, de echo estos campos son fijados en los registros anteriores. En estos campos se almacenará la dirección MAC de origen y la dirección MAC destino en caso de los registros Dirección Hardware y la dirección IP de origen y destino en el caso de los campos de Dirección del Protocolo.


En realidad es un frame muy simple, no lleva mayores complicaciones ni sobrecargas en el protocolo. Vamos a ver un ejemplo de frame tipo ARP IP sobre Ethernet capturado por un Sniffer:

+Frame 1: 60 bytes on wire (480 bits), 60 bytes captured (480 bits)
-Ethernet II, Src: Cisco-Li_xx:xx:xx (00:xx:xx:xx:xx:xx), Dst: AsustekC_xx:xx:x (00:xx:xx:xx:xx:xx)
Destination: AsustekC_xx:xx:x (00:xx:xx:xx:xx:xx)
Source: Cisco-Li_xx:xx:xx (00:xx:xx:xx:xx:xx)
Type: ARP (0×0806)
Trailer: 00000000000000000000000000004fe127ba

-Address Resolution Protocol (request)
Hardware type: Ethernet (0×0001)
Protocol type: IP (0×0800)
Hardware size: 6
Protocol size: 4
Opcode: request (0×0001)
Is gratuitous: False
Sender MAC address: Cisco-Li_4c:fc:8a (00:25:9c:4c:fc:8a)
Sender IP address: 192.168.x.1 (192.168.x.1)
Target MAC address: 00:00:00_00:00:00 (00:00:00:00:00:00)
Target IP address: 192.168.X.2 (192.168.x.2)

El primer bloque pertenecería al protocolo Ethernet. Tan solo se especifica como ya se dijo la dirección MAC origen y destino, el tipo de protocolo (en este caso ARP) y el trailer. El trailer es el fin de la trama (frame), lo cual hay que explicarlo. Como hemos visto un frame Ethernet termina con una secuencia de 4 Bytes que es el checksum. No obstante por regla general no será posible acceder a estos datos del frame por un sniffe, dado que el checksum se calcula de forma automática en el propio adaptador, y para tener acceso a ello sería necesario drivers específicos que realmente no merece la pena molestarse por ello.Es decir, el trailer NO ES el checksum en modo alguno, sino un padding necesario. ¿Por qué? Un frame Ethernet debe de tener un tamaño mínimo de 64 bytes. En este caso podemos comprobar que el Frame capturado tiene curiosamente 64 Bytes (60 Bytes + 4 Bytes del Checksum que se omiten), pero se obtiene un valor exacto de 64 Bytes gracias al trailer, sin este el frame ethernet tendría un tamaño inferior. Es por ello que la propia interfaz de red añade un padding después de los datos para rellenar ese tamaño mínimo de 64 bytes (60 si no contamos el checksum), o lo que es lomismo, un tamaño mínimo de datos de 46 Bytes.

El segundo bloque corresponde al protocolo ARP. La captura muestra exactamente cada uno de los campos de este protoclo, el tipo de Hardware (Ethernet), el tipo de protocolo de red (IP), el tamaño en Bytes de las direcciones, el modo de operación y las direcciones MAC e IP. Aparece no obstante un campo llamado “Is gratuitous”. En el protocolo ARP se denomina un frame gratuito a un auto anunciamiento. Es decir, imaginar que el frame anterior ARP en vez de tener como emisor la MAC y la IP del router tuviese la MAC e IP de él mismo, pero el destino fuese igualmente la dirección indeterminada: 00:00:00:00:00:00. En este caso, es evidente que nadie contestaría al frame ARP, pero este mensaje SI actualizaría probablemente las tablas ARP locales de cada equipo.

El frame completo ARP del ejemplo lo que realmente significa es que pregunta a toda la red por la dirección MAC de la IP 192.168.x.2. ¿Como es posible? porque el frame no está siendo enviado a una dirección MAC concreta, sino a la dirección indefinida 00:00:00:00:00:00, dado que no se conoce cual es. Esto hace que todos los host en la red escuchen tal frame. Cabe esperar que inmediatamente de lanzar el route dicha peticion ARP, el host del cual se desea conocer la dirección MAC responda con un frame ARP reply a dicha petición.

¿Que sucede cuando una petición ARP se contesta?

Al igual que las caché DNS, todos los equipos poseen una caché generalmente dinámica ARP que almacena las asociaciones MAC/IP, lo que evita el uso continuo de realizar peticiones ARP para conocer dichas direcciones MAC. Estas tablas se actualizarán a medida que sean necesaria, pero al contrario de lo qeu se piense, generalmente son actualizadas al recibir cualquier ARP reply de la red, sea legítimo o no, y esto será tratado en profundidad en otro capítulo de este tema. Dado que existe esta tabla/caché ARP, es posible tanto eliminar entradas de esta como añadir entradas manualmente, como listar la tabla ARP.

En windows:

C:\Users\Theliel>arp -a

Interfaz: 192.168.x.3
Dirección de Internet Dirección física Tipo
192.168.x.1 00-xx-xx-xx-xx-xx dinámico
192.168.x.255 ff-ff-ff-ff-ff-ff estático
224.0.0.22 01-00-5e-00-00-16 estático
224.0.0.252 01-00-5e-00-00-fc estático
239.255.255.250 01-00-5e-7f-ff-fa estático
255.255.255.255 ff-ff-ff-ff-ff-ff estático

Interfaz: 192.168.x.2
Dirección de Internet Dirección física Tipo
192.168.x.1 00-xx-xx-xx-xx-xx dinámico
192.168.x.6 00-xx-xx-xx-xx-xx dinámico
192.168.x.8 00-xx-xx-xx-xx-xx dinámico
192.168.x.13 00-xx-xx-xx-xx-xx dinámico
192.168.x.255 ff-ff-ff-ff-ff-ff estático
224.0.0.22 01-00-5e-00-00-16 estático
224.0.0.252 01-00-5e-00-00-fc estático
239.255.255.250 01-00-5e-7f-ff-fa estático
255.255.255.255 ff-ff-ff-ff-ff-ff estático

En Linux:

Anarchy:/# arp -n
Address HWtype HWaddress Flags Mask Iface
192.168.x.1 ether 00:xx:xx:xx:xx:xx C eth0
192.168.x.2 ether 00:xx:xx:xx:xx:xx C eth0
192.168x.25 ether 00:xx:xx:xx:xx:xx C eth0


El protocolo ARP es simple y altamente efectivo, no obstante no está libre de problemas de seguridad. Cuanto más simples es un protocolo más efectivo es, pero también es intrínsecamente más inseguro la mayoría de las veces. Recordar que Internet no se pensó como una fortaleza en la que todo estuviese medido, sino todo lo contrario, un sistema lo más simple posible y efectivo. Y viendo los protocolos que la hacen posible, tengo que decir que lo lograron, y a día de hoy es sin duda alguna la red de redes.

Seguridad: Sniffing. Capítulo Primero -> Modelo OSI y TCP/IP

ATENCION: Los ejemplos que se van a mostrar y “tutoriales” tan solo tienen carácter educativo. En ningún aspecto comparto filosofías de invasión a la intimidad, ataques contra un sistema informático o cuestiones similares. En la medida que sea posible siempre se usarán ejemplos y formas que puedan ser usados por cualquier persona, de forma que pueda verificar los contenidos escritos. No obstante, por motivos más que obvios, materiales como contraseñas, nombres de usuarios o de hosts, serán omitidos o modificado en las capturas de pantallas realizadas (o las lineas escritas). Es decir, los ejemplos serán completamente reales, los datos mostrados a vosotros necesarios para poder pertrechar estos ejemplos no siempre lo serán (Sí lo serán los resultados). Para que esto conste de forma clara, todo material sensible modificado o falso estará resaltado en ROJO. Por motivos de seguridad, todo el material que sea expuesto aquí (exceptuando software propietario o libre, citaciones expresas o código de terceros) tanto texto, imágenes y código son propiedad del autor y está completamente prohibido su reproducción completa o parcial en otros lugares, espero que se comprenda.

 

Modelo OSI y TCP/IP

Antes de poder hablar de términos como IP, DNS, ARP, tramas, paquetes… es indispensable tener un conocimiento mínimo de como se constituye internet y de como funciona. Esa es la idea que nos trae hoy aquí. Estrictamente no es necesario conocer y comprender este tipo de términos a la perfección ni mucho menos, pero su conocimiento ayuda enormemente en cualquier tarea que tenga de forma directa o indirecta relación con una Red, como pueda serlo Internet. No obstante a la hora de tratar con prácticas como el Spoofing y el Sniffing (esta última especialmente) estos conocimientos sí pasan a ser imprescindibles.

Por ello vamos a centrar esta primera parte a comprender más o menos como se estructura Internet a un nivel, más que nada, teórico:

  • Modelo OSI y concepto de encapsulación
  • Capas/Niveles del modelo OSI
  • Modelo TCP/IP e Internet

 

 

Modelo OSI y concepto de encapsulación

En los setenta comenzaron a forjarse lo que serían las primeras redes entre diferentes sistemas. Pero como todo en esta vida, cada fabricante tenía su idea y para cada uno de ellos su idea era la mejor en comparación con el resto. La tecnología tiene que lidiar siempre con un problema siempre recurrente: La compatibilidad. Si una red se establece para poder interconectar entre sí una serie de diferentes dispositivos y/o sistemas, el problema era evidente… ninguna red era capaz de “hablar” con la red vecina, y solo mediante costosos equipos, recursos y otros hacían posible la operatividad entre ellos. Es así que fue necesario un acuerdo para establecer un modelo único por el cual regirse todos los fabricantes, de este modo sería mucho más simple crear interoperatividad entre sistemas diferentes. Así nació el modelo OSI.

La definición formal puede resultar un tanto confusa. OSI son las siglas Modelo de Interconexión de sistemas abiertos (Open System Interconnection), o incluso una definición más exacta podría darse como un modelo M.A.R.I.S.A. -> Modelo de Arquitectura de Referencia para la Interconexión de Sistemas Abiertos. Dicho de otro modo, de una forma más simple, podemos decir que el modelo OSI no es más que un modelo de referencia en el que se asientan ciertas ideas y sistemas para crear la conexión de múltiples sistemas entre ellos. Con este modelo de base, se comenzaron a crear protocolos y más protocolos… todo ello es lo que hace posible en última instancia lo que es Internet a día de hoy.

El modelo OSI se crea desde el inicio con la idea de una jerarquización y especialización clara de cada elemento que lo constituye. Es decir… cada elemento que va a jugar en OSI se intenta que sea aislado al resto, con una función bien definida. De este modo nacen los 7 niveles o capas (layers) en las que está constituida OSI. Cada capa layer en OSI está fuertemente especializada, tan solo se encargan de  recibir un dado de un layer adyacente, tratar el dato y enviar el dato al otro layer adyacente (si el layer es el último evidentemente no lo envía a ningun otro layer, al igual que si es el primero no lo recibe de otro).

Es importante recalcar el uso y función de cada una de estas capas, puesto que el conjunto de todos los protocolos que manejamos actúan de forma mayoritaria sobre una sola capa concreta del modelo OSI (algunos protocolos actúan en más de una capa, como pueda serlo por ejemplo Ethernet):


Esta imagen muestra perfectamente el modelo OSI y sus 7 capas o niveles. Pero antes de explicar la función de cada una hay que comprender como funciona.

Hemos dicho que la idea es que cada nivel sea especializado y en la medida de lo posible completamente independiente de los niveles superiores o inferiores. Esto se logra con el concepto de “Encapsulamiento”. Cada nivel no comprenderá ni tocará los datos que procedan de un nivel superior o inferior, lo tratará todo ello como una simple caja negra en la que no importa el contenido. Es por ello que cada unidad de información en cada nivel del modelo OSI posee un nombre distintivo. Existe no obstante un nombre genérico para todos ellos, PDU (Protocol Data Unit , o Unidad de datos del protocolo). Este término suele acompañarse con la letra al nivel que corresponde o el numero del nivel. Por ejemplo, la unidad de datos del novel 5 sería un 5PDU o SPDU. A partir del nivel 4 no obstante, cada nivel tiene un nombre también conocido diferente a PDU, aunque es igual de correcto usarlo. No obstante en informática está muy mal visto mezclar estos términos. Así, si nos encontramos en el nivel físico tan solo podemos hablar de bits. Frames si nos encontramos a nivel 2, paquete si estamos en nivel 3 o mensaje si estamos en nivel 4.

Para explicar el encapsulamiento, es necesario conocer esas PDU, puesto que explica perfectamente como funciona el modelo OSI y como un nivel envía información a otro:

Componentes PDU

El proceso de ascensión por los niveles es sencillo, el descenso de un dato sería exactamente igual pero en sentido contrario. Imaginemos que el nivel n+1 va a recibir un dato desde el nivel n. El nivel n realiza la función que tenga que realizar y cuando termina llama al nivel superior por medio del SAP (Punto de acceso al servicio) para enviar la información. Esa unidad de información se llama en dicho momento SDU del nivel n. Existen primitivas que realizan estas “llamadas” entre niveles, pero no compliquemos más el proceso. El caso es que ese nSDU justo antes de enviarse al nivel superior, es concatenado con un pequeño trocito de información adicional, llamado ICI (Interface Control Information, Información de Control de Interface) que es necesario para el paso de nivel. El nuevo bloque de información (ICI+SDU) pasa a llamarse IDU. En cuanto el IDU (Interface Data Unit, Unidad de datos de la Interface) cruza el nivel, el nICI es eliminado y el nSDU pasa a llamarse PDU del nivel n+1. Si fuese el nivel 3, se llamaría frame como ya hemos dicho. Un PDU es una unidad compuesta a su vez de una “cabecera” llamada PCI y el SDU. Este SDU por tanto contiene en realidad el PCI y el SDU del nivel n+2. La ÚNICA información por lo tanto que maneja el nivel n+1 será la PCI n+1. El SDU n+1 será enviado tal cual al nivel superior tal y como sucedió en el nivel n.

Dicho de otro modo, cada nivel tan solo se encarga de leer y eliminar, o añadir, la PCI de su nivel, dado que ICI es tan solo un trozo temporal de información que al final queda desechado. Es por ello que se llama al procedimiento encapsulamiento.

Visto de forma aun más resumida, imaginar que un navegador envía un dato a la red. El nivel de aplicación tomaría los datos enviados (7SDU) y le añadiría un PCI con información como el protocolo usado (HTTP), la longitud de los datos que se está enviando… El nivel de aplicación JAMÁS modificará por tanto el SDU entrante, ni siquiera mirará que datos son, simplemente recibirá el SDU y le añadirá en la PCI la información que tenga que añadirle. Despues de añadirle la PCI, la unidad pasará a llamarse 7PDU y será enviada por el SAP al nivel de presentación. Desde el punto de vista del nivel de presentación el proceso es exactamente igual al nivel de aplicación. El tan solo ve que recibe un SDU (que en este caso no sería más que la PCI+SDU del nivel de aplicación). Construye la 6PCI en el que especifica por ejemplo que los datos han sido cifrado por un algoritmo concreto o incluso encripta los datos (OJO!! si existe una encriptación o compresión de datos es evidente que el SDU es modificado) y la concatena con el 7SDU para formar el 6PDU, el cual es enviado al nivel inferior. El proceso continua hasta que al final en el nivel 1 todo es convertido en una mera secuencia de señales eléctricas enviadas por el cable de red. Cuando el otro extremo recibe la información, en realidad lo que está recibiendo sería algo como esto:

Encapsulamiento OSI

Aunque no se ha hablado anteriormente, un nivel puede no solo añadir una cabecera (PCI), sino que en algunas ocasiones y/o niveles encontramos que se añade al final del SDU una cola. Es el caso por ejemplo del nivel de enlace de datos. La capa física no obstante carece de PCI, ella es una mera intermediaria entre el medio y los datos lógicos.

Por último hay que añadir que aunque las dos imágenes anteriores son ciertas, existen mecanismos que no se han explicado, y que pueden ser usados en diferentes niveles si así se requiere por el protocolo. Es el caso de la segmentación/reensamblaje y la concatenación/separación:

Segmentación y Concatenación

En el caso de la segmentación, de un mismo SDU se forman diferentes PDU dentro del mismo nivel. Una vez que los diferentes PDU han sido creados se envía uno tras otro como si se tratase de PDUs diferentes de diferentes SDU. En el proceso inverso, el nivel n recibirá los diferentes PDU y los reemsamblará todos ellos en un solo SDU, que será el que se envíe al nivel superior.

La concatenación es diferente. En la concatenación se parte de diferentes SDU que producen diferentes PDUs. Esos PDUs se concatenan uno tras otro, y al finalizar es enviado todo el bloque, que corresponderá al SDU del siguiente nivel.

 

 

Capas/Niveles del modelo OSI

Capa 1, Capa Física

Esta capa es la encargada de enviar o recibir el flujo de bits final por el cable (o por el aire en el caso de conexiones wireless).  Es decir, en este nivel no importa en absoluto el contenido de esos bits de información, no importa si son correctos o son erróneos, si existe manipulación de bits o no existe manipulación de bits. Aquí no importa el destino de los datos o el origen de ellos, simplemente se codifica el flujo de bits de la forma necesaria para poder ser enviados por el medio que se esté usando (O al contrario, decodificar las señales recibidas del medio y convertirlas en bits de datos). Si es una red Ethernet por el cable Categoría 5e+, si es un Modem ADSL por el cable de teléfono de dos hilos de toda la vida, si es por WIFI por el aire. Dicho de otro modo, se transforman los bits en señales eléctricas (o viceversa) que serán las que transporten la información por el medio subyacente.

El nivel físico es posiblemente el más sencillo de comprender en función, aunque no por ello no deja de tener una complejidad importante. Aquí podríamos decir que las especificaciones eléctricas/electrónicas/magnéticas de los dispositivos de red son imprescindibles, normativas, temperaturas de operación, ruido del medio, especificaciones y/o estándares… y tampoco significa que no existan protocolos a este nivel, todo lo contrario, la mayoría de los lectores conocerá muchos de estos protocolos que operan exclusivamente a este nivel: Ethernet (IEEE 802.3), WIFI (802.11 b/g/n/a), xDSL, ISDN, GSM… en definitiva los protocolos de punto inicial/final por así decirlo que hacen posible las comunicaciones. Por ejemplo, un Modem ADSL actua en la capa física, Modulando o DEModulando las señales que tendrá que enviar o recibir por el cable de teléfono, y tendrá que hacerlo según el protocolo ADSL.


Capa 2, Capa de Enlace de datos

Es una de las capas del nivel OSI que mayor trabajo soporta y con no pocas tareas a llevar a cabo. Dicho de un modo simplista se encarga de la transmisión de los datos al medio adyacente (o a la capa física o a la capa de red) de una forma fiable y eficiente. Tomará un paquete (nombre de la unidad de información del nivel de red) del nivel de red y lo convertirá en un frame o trama (unidad de dato del nivel de enlace de datos) que será convertido en un flujo de bits y señales eléctricas que serán enviadas gracias al nivel físico. Si el dato es ascendente, tomará el flujo de bits procedentes del nivel físico y lo transformará en una nueva trama que será enviada al nivel superior, al nivel de red.

Esta capa se divide a su vez en dos subcapas, llamadas LLC (Logical Link Control o Control de Enlace Lógico) y MAC (Media Access Control, o Control de Acceso al Medio). Según la subcapa las funciones son diversas. Por ejemplo, en la subcapa LLC se realizan tareas como de corrección/detección de errores (según protocolos, por ejemplo en Ethernet no se realiza detección de errores en este nivel, pero si en WIFI) o el control de flujo.

LLC:

-Detección/corrección de errores: Se encarga precisamente de eso, asegurarse que los datos que se van a trasmitir al medio están libre de errores, o que los datos recibidos desde el medio se encuentran libres de ello. Alguna de estas técnicas se ha hablado en el capítulo de encriptación y autentificación cuando se habló de checksums y CRC.

-Control de Flujo: Es necesario la implementación de sistemas que garanticen que las tramas sean enviadas en el orden correcto o al menos conocer que trama es la primera y cual es la segunda en caso de que sean recibidas en otro orden (lo cual es bastante normal). Por otro lado es necesario la creación de frames especiales que indiquen el éxito o fracaso de la recepción de un frame de datos, como pueden ser los frames o paquetes ACK, y gracias a estos ACK y otras técnicas es posible conocer no solo el orden de los frames, sino si es necesario reenviar alguno que se ha perdido o transmitido con errores o cuestiones similares.

-Multiplexación de protocolos: Digamos que es posible multiplexar (“unir”) en una misma trama diferentes protocolos, es decir que en una misma trama exista dos o mas tipos de informaciones diferentes, de modo que cuando se realiza el proceso inverso se obtienen dos tramas diferentes con funciones completamente diferentes. Pensar en ISP que emiten simultaneamente a sus suscriptores televisión y conexión a Internet, de forma simultanea. Esto es posible exactamente por este procedimiento, las tramas de televisión se multiplexan con las tramas destinadas al tráfico de internet, y el Modem/router del cliente identificará que información tiene que destinar para la televisión de pago y cual de la información pertenece a Internet (no televisión).

MAC:

-Control de Acceso al medio: Como su propio nombre indica. El nivel de enlace de datos necesita conocer como tiene que acceder al medio para poder enviar los datos. La capa física tan solo coloca los datos en el canal y no se preocupa absolutamente de nada, es el nivel de enlace de datos quien tiene que supervisar cuestiones como que el medio se encuentre disponible en dicho momento. ¿Por qué es esto necesario? Imaginar que sucedería si se pretende enviar un frame via WIFI al router si en dicho momento exactamente el router está recibiendo un frame de otro equipo. En tal caso se produciría una colisión. Por ello es necesario sistemas de control que supervisen esto. Los dos modelos más comunes que podemos encontrar es por ejemplo el estandar CSMA/CD que es el empleado en redes Ethernet o el estandar CSMA/CA usado en WIFI, las redes Token Ring y Token BUS están perdiendo fuelle en estos últimos años. Hay que tener en cuenta que la eficacia de estos sistemas no depende si uno es más sofisticado que otro o cual es mejor, sino cual es más idóneo para cada medio. Por ejemplo, en caso de Ethernet y CSMA/CD el procedimiento de control es muy simple

a) CSMA/CD: Se comprueba que nadie esté transmitiendo en dicho momento. Si el medio no está libre se vuelve a intentar. En cuanto el medio esté libre se envía el primer bit y el protocolo permite conocer si ha existido o no colisión. Si ha existido se intenta enviar de nuevo el bit. Si no ha existido colisión se procede a enviar el segundo bit. Así hasta completar el envío de toda la trama

b) CSMA/CA: Se envía al medio una trama especial (RTS) preguntando si el medio está libre. Cuando el medio lo esté, recibirá una trama especial CTS, momento en el que se enviará la trama. Una vez enviada la trama y recibido un ACK de trama recibida, se procederá a la espera de un tiempo aleatorio. Tras el cual se procederá al envío de la segunda trama y así sucesivamente.

-Sincronización de Frames: Si el control de flujo es necesario para la fiabilidad de los datos, igualmente es necesario un mecanismo que sea capaz de separar o crear las tramas como tales. Es decir, de un flujo de bits que procede del nivel físico saber donde comienza y donde termina una trama y localizar donde comienza y termina la siguiente. Del mismo modo se tiene que encargar de “marcar” la trama que se va a enviar para que el destino pueda del mismo modo conocer cual es el inicio y fin de las tramas.

-Direccionamiento MAC: la gran mayoría conoce lo que es una dirección IP, pero si acudimos al modelo OSI, IP es un protocolo de nivel de red. En realidad existe un direccionamiento a más bajo nivel basado en en un direccionamiento físico. Se denomina físico porque la trama como tal no se envía en realidad a una IP, sino a una interfaz física. Cada interfaz física por tanto posee una dirección física única en el mundo, y así sucede. Es lo que llamamos comúnmente como dirección MAC, que no es más que un identificador grabado en fábrica que se le asigna a cada dispositivo de red. Recordemos que cada nivel no comprende, ni tiene que hacerlo, que sucede por encima o por debajo de su nivel. De este modo el nivel de enlace de datos especificará (o leerá) en la trama el origen y destino de la trama a nivel físico. De este modo, el nodo de red que reciba la trama sabrá a quien tiene que destinarla, o si tiene simplemente que desecharla porque dicha trama no tiene nada que ver con él.

Este ID que denominamos como dirección MAC es un ID que administra la organización IEEE y que es necesario comprar si se desea crear con fines comerciales un dispositivo de red. Este ID está constituido por una cadena de 6 bytes hexadecimales, generalmente expresado como 00:11:22:33:44:55 o como AA-12-BB-34-CC-56. Cada adaptador físico posee su dirección MAC única, lo cual no quiere decir que esta pueda ser alterada por software de algún modo.

-QoS: En este nivel y subnivel se lleva a cabo una labor también importante, como es QoS (Quality Of Service o Calidad de Servicio). QoS son sistemas de priorización de tráfico. Dado que el ancho de banda queramos o no es limitado (no es infinito) es necesario en algún momento priorizar un tráfico frente a otro. De lo contrario se producirían errores de transmisión intolerables en cuestiones que requieran aplicaciones sensibles al tiempo. Por ejemplo solo hay que pensar en un software de monitorización de un paciente, en la que las órdenes se realizaran y recibiesen por red. En una aplicación similar no podríamos permitirnos el lujo de la existencia de retrasos en las señales debido a una sobrecarga en nuestra red. No podríamos permitir que (dado que el ancho de banda no es infinito) por leer el correo en nuestra red, descargar archivos o cualquier otra labor, pudiese relentizar dicha monitorización. Es necesario por tanto priorizaciones de tráfico. Así por ejemplo podríamos disponer de tráfico pesado pero que poco importa su retraso o completamente el caso concreto, tráfico muy ligero pero con un retraso mínimo. O tráfico normal pero para el que se requiere una sincronización y estabilidad absoluta.

-Otros: Existen otras funciones quizás menos conocidas o usadas de forma popular, como VLAN o la commutación de paquetes.

como protocolos que podemos indicar en el nivel de enlace de red tenemos desde Ethernet, ARP (que se verá exhaustivamente), Frame Relay, PPTP/L2TP…

 

Capa 3, Capa de Red

Quizás la capa más conocida de forma popular dado la importancia manifiesta del protocolo IP. Este nivel tiene 2 funciones principales:

-Encaminamiento: A fin de ser posible la comunicación entre dos dispositivos en la ubicación que sea, es necesario un sistema que sea capaz de destinar un paquete desde un origen a un destino por una ruta que sea la óptima según el momento o situación. Esta ruta puede variar por razones de latencia o simplemente congestión.

-Control de congestión: Dado que es importante conocer aquellas rutas que no son eficaces, es necesario disponer de mecanismos que puedan identificar dichos nodos y poder así establecer rutas diferentes

Hay que tener en cuenta que IP no es más que un protocolo más de este nivel, existen otros muchos protocolos que no requieren de una IP para poder ser usados, como por ejemplo IPX o ICMP. No obstante las redes que tenemos constituidas a día de hoy, la infinita mayoría, corresponde al modelo TCP/IP, en el que el protocolo IP está presente prácticamente en todo momento. Pero IP será tratado en otro momento de forma más exhaustiva.

Como hemos dicho existen otros protocolos de nivel de Red como pueda serlo IP, ICMP, IGMP, IPX…

 

Capa 4, Capa de Transporte

Los niveles 1 2 y 3 están orientados a mantener una comunicación directa tan solo entre sí mismos y el nodo de red adyacente. A partir del nivel 4 la comunicación pasa a ser entre host y host. Toda la información que se trata en los niveles 1 2 y 3 es tan solo de interés para los nodos de red, e incluso estos mismos son los que la modifican según necesiten para poder ir encaminando, detectando y enviado el mensaje al destino final. la comunicación que mantienen los 3 primeros niveles por tanto se limita entre nodos adyacentes.

En el nivel 4 esto cambia. La unidad de información pasa a llamarse mensaje, y aquí ya no importa el destino o el origen del mensaje dado que de eso se encargarán otros niveles. El nivel 4 se preocupa tan solo en garantizar el correcto transporte y entrega de los datos al host destino, no al nodo de red siguiente, que eso es función del nivel de enlace de datos. Hay que tener en cuenta que a lo mejor el mensaje tiene que cruzar medio mundo, 20 routers para poder llegar al destino final. Eso es lo que no le importa a la capa de transporte, el no ve el destino como un punto del mapa del mundo, sino como un dispositivo que está a su lado y con el que quiere comenzar una comunicación. Es por ello que muchas de las funciones que realiza el nivel de red pueden ser encontradas en las funciones que realiza el nivel de enlace de datos. ¿Pero entonces no es algo redundante? ¿No sería suficiente con permitir un control similar en el nivel de enlace de datos? No. El nivel de enlace de datos tan solo garantiza un medio libre de errores y correcto entre nodos, no más allá. El nivel de transporte no garantiza un medio libre entre dos nodos, sino que su información es recibida de forma correcta en el destino. Sin este tipo de control en la capa de transporte, se podría enviar un mensaje por el mismo equipo de forma correcta, pero podría darse el caso que en el salto número 10 por el router 10 por el que transita el mensaje el mensaje se perdiese por una desconexión del mismo o por una congestión intensa. De cara al host origen, del nivel de enlace de datos, la trama fue correctamente recibida por el router 1, luego para él no existiría problema alguno. En cambio, el nivel de transporte se mantendría esperando para la recepción de los datos y jamás sabría que el mensaje se perdió en algún punto de la red.

Es por ello que las funciones que puede desempeñar la capa de transporte (Dependiendo siempre del protocolo usado) son muchas de ellas similares a las que encontramos en enlace de datos, aunque esta vez siempre entre hosts:

-Control de Flujo y Corrección/Detección de Errores: Tal y como fue explicado en el nivel 2

-Acceso múltiple: Comúnmente conocemos esto como “puertos”. Todos los niveles del modelo OSI tienen una primitiva (un elemento) llamado “Service Access Point” (SAP, punto de acceso al servicio) por el cual se accede al nivel superior/inferior. En el caso del nivel de transporte este SAP es lo que denominamos de forma coloquial “Puerto”. La funcionalidad de estos puertos no es otra que la de poder establecer conexiones múltiples de forma simultanea sin que unas infieran en otras. Es decir, se requieren diferentes accesos diferentes a este nivel. Se puede pensar que que este mecanismo podría ser necesario igualmente en otros niveles, pero no es así. Recordemos que por debajo del nivel de transporte está el nivel de red y a él le da exactamente igual el dato que esté recibiendo, el trata todos los mensajes que recibe del mismo modo, le da igual orden, prioridad, si tiene o no tiene errores… en cambio, para el nivel de red si es muy importante conocer que mensaje está destinado a cada puerto, dado que cada puerto será una comunicación que se está realizando de forma simultanea, tiene que conocer que mensaje es cada cual y a quien está destinado.

Podemos decir igualmente que existen dos tipos de protocolos en la capa de transporte, aquellos orientados a la conexión y aquellos no orientados a la conexión. Podemos decir que en el primer caso, la idea es que antes de transmitir los datos es necesario el establecimiento de una conexión antes de transmitir los datos y la finalización de esta al acabar. Por el contrario en aquellos no orientados a la conexión esto no es necesario, y cada mensaje es enviado sin necesidad de crear conexiones. Generalmente se usan protocolos de transporte orientados a conexión como TCP cuando los datos a transmitir requieren de cierta fiabilidad y control sobre ellos, mientras que lo común es usar protocolos no orientados a la conexión cuando lo que se requiere es simplemente el envío de datos sin importar siquiera si hay errores en la transmisión. Es el caso de UDP. Pensar por ejemplo en aplicaciones que es necesario controlar perfectamente la información, como por ejemplo a la hora de querer ver una página web, no queremos que la página se muestre mal. Por el contrario, podemos pensar en un juego online en el que se está transmitiendo de forma continuada y masiva las coordenadas de la posición de nuestro personaje al servidor. No sucedería realmente nada si algunos datos se pierden por el camino, dado que no son datos que podríamos entender como críticos. Otras muchas veces es preferible usar este tipo de protocolos y dejar que la aplicación en sí la que por otros mecanismos software verifique la fiabilidad de dichos datos.

De todos modos TCP/UDP será también extendido de forma amplia, y esto servirá más que nada como una “mera” introducción.

 

Capa 5, Capa de Sesión

La función de la capa de sesión no es otra que la de abrir, configurar, mantener y cerrar una sesión entre dos aplicaciones, generalmente en un esquema de aplicaciones cliente-servidor. En realidad ha sido un nivel poco usado, dado que la mayoría de las funciones de las que puede encargarse suelen ser aplicadas en la misma Capa 7, en nivel de aplicación. No obstante tenemos algunos protocolos tipo que nos muestran perfectamente de lo que hablamos, como el protocolo SSH (bastante usado) o SCP. Otro ejemplo común de ello es el protocolo de Microsoft NetBios para la resolución de nombres en redes Windows.

 

Capa 6, Capa de presentación

La función de la penúltima capa es preparar los datos para la capa final (en caso de una conexión entrante) y prepararlos para que sean enviados. Es por ello que esta capa se encarga fundamentalmente de tres funciones:

-Conversión de datos: Las redes pueden estar compuestas por diferentes sistemas que tratan los datos de manera diferente. Por ejemplo diferente codificaciones de caracteres. La capa de presentación es necesaria por tanto si se quiere que diferentes sistemas que usan codificaciones diferentes puedan hablar entre ellos.

-Compresión: Poco es necesario añadir. En el nivel de presentación puede ser necesario una compresión o descompresión de estos. Esto no quiere decir que cualquier compresión de datos en una red se sitúe en este nivel, aunque este nivel se debería de encargar de ello

-Cifrado: Los datos pueden necesitar un cifrado de datos o descifrado a este nivel. Aunque protocolos como SSL/TLS puedan ser usados a nivel de transporte, puedes ser usado igualmente en nivel de presentación, siendo posiblemente una solución más segura.

Protocolos que funcionen en este nivel? TLS o SSL para comenzar, aunque podemos citar también por su gran implementación “MIME”, protocolo usado ampliamente en la codificación de correos electrónicos.

 

Capa 7, capa de aplicación

Por último, el nivel de aplicación. Si el nivel físico hace de nexo entre los datos lógicos y meras señales eléctricas, el nivel de aplicación hace de nexo entre la aplicación y por tanto el usuario y la red. Es el nivel más cercano al usuario e interactua directamente con él. Posiblemente aquí encontremos la mayoría de los protocolos más conocidos, quizás excluyendo TCP o IP: HTTP, SMTP, POP, IMAP, DNS, FTP, DHCP… así un navegador web es el que interactua con el usuario para poder visionar una web, y el protocolo más cercano al usuario es por tanto HTTP y DNS. Si usamos un gestor de correo es SMTP, IMAP y POP los protocolos que hacemos uso para poder leer nuestro correo… estos protocolos interactuan directamente con nosotros, y serán las diferentes capas las que se irán transformando los datos hasta acabar convirtiéndolos en una mera sucesión de señales eléctricas que contienen toda la información necesaria para alcanzar el destino.

 

 

Modelo TCP/IP e Internet

A medida que ascendemos por los niveles del modelo OSI, comprobamos ciertos aspectos que pueden o podrían ser implementados en otros niveles, o agrupar varios de ellos por el poco uso que puede darse. Hay que tener en cuenta que el modelo OSI es tan solo un modelo de referencia, y por supuesto no se pensó en modo alguno en la existencia de Internet, y menos aun de lo que es Internet a día de hoy. Es por ello que del mismo modo que nació el modelo OSI, apareció el modelo TCP/IP, por supuesto basado íntegramente en el modelo OSI. Es más… el modelo TCP/IP que es el que es usado hoy en día es prácticamente el modelo OSI solo que simplificado y algunos pequeños cambios.

El modelo TCP/IP es el siguiente:

TCPIP Vs OSI

Como se aprecia, básicamente el modelo TCP/IP condensa los niveles de aplicación, presentación y sesión en tan solo un Nivel Aplicación. Por otro lado condensa los niveles Físicos y enlace de datos en un nivel de Enlace de datos (o acceso a la red). De este modo, el modelo TCP/IP pasa a tener tan solo 4 niveles diferentes, niveles que funcionan exactamente igual que en el modelo OSI, salvo los niveles de enlace de datos y aplicación que se encargarían también del peso restante.

Aunque el modelo TCP/IP se puede ver como una simplificación al modelo OSI, no podemos en ningún momento afirmar que el modelo TCP/IP sea siquiera compatible con OSI. Es cierto que las funciones de los diferentes niveles es el mismo con la diferencia de que algunos de ellos están condensados, pero existen muchas otras diferencias a menor escala que hace que cada día que pasa el modelo TCP/IP sea más diferente a OSI. Esto tiene también una explicación.

El modelo OSI es un modelo muy antiguo en lo que toca al ritmo galopante de nuestros días en cuestión de tecnología. Se crean o destruyen protocolos así hagan falta, e incluso muchos de ellos es complicado ubicarlos en un nivel concreto, tanto en OSI como en TCP/IP. Mientras que OSI es un modelo de referencia, TCP/IP es un modelo que podríamos llamar “en producción”, sujeto a modificaciones en el tiempo según las necesidades. Es cierto que la inmensa mayoría de estas necesidades se satisfacen con protocolos y/o técnicas diferentes, pero no tiene por qué limitarse a esto. Podemos ver OSI por tanto como un modelo rígido y TCP/IP como un modelo derivado de OSI que ha continuado por si mismo, aunque como hemos dicho, una vez más, es muy muy similar en forma y contenido a OSI.

Es evidente que el modelo TCP/IP tiene como características casi indiscutibles la necesidad del protocolo de red IP o el protocolo de transporte TCP. Pero dentro del modelo TCP/IP existe un conjunto bastante grande de protocolos, lo que se conoce como la pila (o stack) de protocolos TCP/IP. Muchos de ellos nos son más que conocidos: IP, ARP, DNS, TCP, UDP, ICMP, IGMP, IPsec,L2PT, PPTP… aunque es posible hacer funcionar una red TCP/IP con un conjunto limitado de esta pila de protocolos. Así, el modelo TCP/IP no solo es una arquitectura propia que explica como se pueden relacionar los diferentes protocolos entre sí, sino que especifica los diferentes protocolos que harán uso de dicho modelo.

Su importancia es evidente: Internet y redes LAN. Podríamos decir que Internet ha sido el gran logro, pero no hay nunca que olvidar las redes locales. Es cierto que Internet está constituida por el modelo TCP/IP, pero las redes LAN no tienen por qué estarlo. Por ejemplo aun se encuentran redes en IPX, lo que hace necesario elementos para la correcta interoperatividad entre diferentes modelos.

 

Para terminar este capítulo, hay que hablar de Internet. Modelo OSI, modelo TCP/IP, protocolos… toda esa teoría, conceptos y herramientas ha servido a día de hoy para poder constituir la red de datos más grande que se ha conocido (si excluimos el cerebro humano como red neuronal). Actualmente Internet se puede concebir como una red con vida propia. El éxito de Internet y su gran importancia desde el punto de vista de este escritor es que es la primera “construcción” humana de la cual TODOS formamos parte (al menos si así lo deseamos). Ese es el principal peligro que siempre acosará Internet y que esperemos que por siempre Internet pueda sortear la política o los intereses económicos.

¿Que es Internet? ¿Quien es el dueño? ¿Que es de los ISP?

Internet es una red abierta, libre, gratuita. Pero para poder mantenerla, expandirla y hacer un buen uso de ella, actualmente existen dos organizaciones sin animo de lucro que se encargan de ello. Podríamos verlos como “sus dueños”, aunque esta afirmación es completamente errónea.

La primera organización nacida relativamente ayer, en el 1998, es la encargada de la asignación de direcciones IP y de nombres de dominio, es la ICANN (Internet Corporation of Assigned Names and Numbers), de la cual pende una rama de ella conocida como IANA, la cual se encarga de parte de esta labor, aunque su papel era el de ser la misma ICANN antes de que esta fuese constituida como tal. Actualmente IANA se encarga principalmente de la coordinación del direccionamiento IP, los servidores DNS raíces o de cuestiones como los puertos TCP/UDP. Por el otro lado tendríamos a la IETF, que sería la organización que crea, elimina o modifica los protocolos del nucleo de TCP/IP, como pueda serlo el mismo protocolo IP, TCP, UDCP… si bien es cierto que muchos protocolos de Internet son mantenidos por otras entitades, la IETF tan solo se encarga de aquellos protocolos esenciales. Por ejemplo el cada día más próximo IPv6. Pese a la polémica siempre suscitada de si la ICANN debería de ser una organización americana o no, personalmente por ahora siempre han realizado una labor impecable.

Como vemos, Internet por tanto es la red que se forma con los mismos cientos de miles, millones de dispositivos conectados entre sí de una u otra forma, ya sean redes privadas o redes públicas. Así, cuando conectamos nuestro equipo a Internet, estamos formando parte en dicho momento de Internet. Quizás sea más fácil pensar en Internet como un cable interminable al cual el que quiera puede cuando quiera acercar el brazo y unirse, haciendo que al cable le crezca otro brazo más. Y aunque parezca lo contrario, es una red libre, nosotros no pagamos por el acceso sus infraestructuras… ¿o si? Para poder tener acceso a la red de redes necesitamos un ISP, un proveedor de servicios que nos alquila sus infraestructuras para poder conectarnos a ella. Podemos pensar que en u principio Internet no era más que un cable que conectaba dos universidades, una en Estados unidos y otra en ginebra. Podemos pensar que en algún momento se lanzó otro cable a otro pais en estados unidos, formando la primera pequeña rad de ordenadores interconectados y separados por cientos o miles de kilómetros. A esta imagen tan solo hay que añadirle ramas y más ramas y más ramas… universidades interconectadas entre ellas, infraestructuras y cableado que surcan los océanos… del mismo modo los ISP crean o mantienen sus propias redes, se conectan a los enlaces principales de internet, y así poco a poco se forma la mayor red de las redes:

Gracias al direccionamiento IP y a la eficiencia de los servidores de nombres de dominios, podemos acceder virtualmente a cualquier servidor público del planeta con tan solo conocer o su IP o su nombre de dominio de tenerlo. De ahí la importancia de la ICANN. No obstante, la ICANN delega en organizaciones regionales la gestión de las direcciones IP. Dicho de otro modo, mientras que la ICANN es la organización padre, las organizaciones regionales RIR (Regional Internet Registries) serían sus hijas. Existen 5 entidades registradoras de Internet, cada una de ellas se ocupa de una región diferente del planeta, de modo que ninguna se solapa. Es decir, cada una de estas RIR serían la máxima autoridad registradora IP, tan solo estando por encima de ellas la ICANN e IANA

  • RIPE NNC -> Se encarga de toda Europa y prácticamente toda Asia, excluyendo el Sur de esta.
  • AfriNIC -> Se encarga del continente Africano en su totalidad
  • APNIC -> Todo el Sur de Asia más toda Australia
  • ARIN -> América del Norte
  • LACNIC -> América Central y Sur América


Distribución de las Organizaciones RIR


Del mismo modo que se gestiona todo el direccionamiento IP, es gestionado todos lso nombres de dominio. Esto es necesario para el correcto funcionamiento de la Red, es fundamental. Esta función recae igualmente y en última instancia en la ICANN, aunque esta permite a empresas tanto públicas como privadas actuar como agentes registradores, por supuesto con todos los permisos pertinentes y todas las restricciones de cada caso. Así, la ICANN es la encargada de la gestión y control de los dominios de primer nivel, conocidos como Top-Level Domain o simplemente TLD

¿Pero que es un nombre de dominio? Un nombre de dominio no es más que un identificador asignado a un usuario (ya sea físico, empresa…) que generalmente se enlaza a una IP, de modo que su ubicación en Internet queda completamente definida por dicho identificador. El sistema de nombre de dominios es jerárquico, y debe de ser leído siempre de derecha a izquierda, donde cada punto separará los diferentes niveles del dominio.

Dicho esto, los dominios de primer nivel por tanto son aquellos identificadores que se encuentran a la derecha del todo, antes de encontrar el primer punto de separación. No obstante, los dominios de primer nivel no son infinitos como cabría esperar, existen dos grupos bien definidos de los dominios de primer nivel:

  • ccTLD (Country Code TLD): Podríamos traducirlo algo así como TLD regionales o traducirlo literalmente como TLDs por código de País (o algunas regiones), los cuales son los únicos dominios de primer nivel que poseen tan solo dos letras. La ICANN concede a cada País por tanto un dominio de primer nivel, correspondiente este a dos letras, que coinciden con un estandar ISO (exceptuando alguna que otra excepción por motivos históricos). Así por ejemplo, el dominio de primer nivel reservado para España es “.es” o para francia “.fr”. No obstante, cada País tiene el derecho de explotación de su dominio de primer nivel, dándose el caso de que algunos países lo vendieron a empresas por dinero.
  • gTLD (Generic TLD): TLDs genéricos. Todos ellos poseen tres o más caracteres, aunque la mayoría son de 3 y 4. Aquí de nuevo hay que hacer distinción entre 3 subgrupos:

    -Generales: Aquellos que dependen exclusivamente de la ICANN y regidos por sus respectivas normas de registro: .com .net .org .pro .bif .info .name
    -Patrocinados: dominios propuestos a la ICANN por agencias u organizaciones privadas por diferentes motivos, desde culturales, estatales… y algunos de ellos bien “pagados” a la ICANN: .aero .asia .cat .coop .edu .gov .int .jobs .mil .mobi .museum .tel .travel.
    -Infraestructura y Reservados: Son dominios de primer nivel que no se usan. Algunos se usan para pruebas, otros se mantienen por razones históricas: .example .invalid .localhost .test .arpa

Según lo explicado, para una persona física sería imposible registrar un dominio de primer nivel, dado que los administra tan solo la ICANN y hay los que hay. Cuando registramos dominios realmente lo que hacemos es en el mejor de los casos registrar dominios de segundo nivel, aunque muchas veces se confunde y se les llama de primer nivel. Así por ejemplo, el dominio Theliel.es no es un dominio de primer nivel, sino de segundo. El primer nivel es “.es”, el segundo nivel es “theliel.es”.

Los ccTLD son administrados de manera local por las agencias de cada Pais encargadas a ello, por ejemlo en españa la agencia encargada del registro y mantenimiento de los dominios .es es “nic.es” perteneciente al propio gobierno, lo que no quita que existan entidades intermediarias que son agentes registradores legales. Los gTLD no obstante, son gestionados por agencias o empresas privadas y por supuesto en última instancia por la ICANN. Pero esto no evita el problema de preguntarse como se enlazan esos nombres de dominio al sistema de direccionamiento IP. Y es ahí donde entra en juego el protocolo DNS y los servidores de nombres de dominios. Aunque DNS será explicado en el siguiente capítulo, si hay que comprender que es necesario ciertos servidores (llamados servidores raíces) que se encarguen del grueso de todo ello, de toda la mayoría de toda la gestión DNS. Es así por tanto que existen 13 servidores raíces esparcidos por todo el mundo, administrados tanto por compañías publicas como privadas, y por supuesto por seguridad, existe réplicas de la mayoría de ellos, para distribuir la carga y para sustitución en caso de fallo, avería o ataque Hacker. Todos ellos se denominan alfabeticamente comenzando por la primera letra: “letra.root-servers.net”, siendo la letra desde la A hasta la M:


Gracias a estos elementos explicados, Internet es posible. En el próximo capítulo veremos los protocolos más importantes que hacen que esto funcione y explicaremos un poco más como es posible que dos puntos cualesquiera del mundo puedan estar conectados en cualquier momento. Todo ello necesario para poder comprender más adelante algunas técnicas ya comentadas, como el Sniffing.

Seguridad: Sniffing. Índice

Bienvenidos al tema de hoy: Sniffing, el arte del espionaje

 

Damos un paso hacia delante, asimilamos la encriptación, los hash… y nos centramos ahora en el flujo de información que sale y entra constantemente de nuestras redes, sea información cifrada o no lo sea. Sniffing, para entendernos, es una técnica que permite tener un ojo en ese flujo de de información, es decir, tener acceso a la información que es enviada o recibida por nuestros adaptador de red, y algunas veces por el de otras personas también. Un Sniffer, utilidad que permite el sniffing, se llama de formalmente analizador de paquetes o analizador de red. Y sobre esto vamos a centrar todo este nuevo volumen:

  • Introducción al modelo OSI y TCP/IP
  • Protocolos IP, TCP, ARP y DNS
  • Introducción a Routers, Switch, Hubs y Bridges
  • Sniffers
  • Envenenamientos ARP y DNS
  • A rellenar…

Posiblemente en una primera versión sean estos elementos los que sean integrados en este volumen, posiblemente la versión final esté estructurada algo diferente, creando un volumen nuevo para temas generales de redes, como IP, DNS, modelos OSI…

Herramientas Utilizadas/Material necesario: (No todo es necesario, dependiendo de la plataforma a usar, de cada sección y de lo que a cada cual le sea más cómodo)

Por supuesto si me está olvidando algo y algún lector quiere expandir el temario… es libre de comentarlo, es más… lo agradecería.

Seguridad: Encriptación y Autentificación. Índice (Actualizado)

Bienvenidos al tema de Hoy: Encriptación y Autentificación, la seguridad ante todo.


Hoy dejamos todo aquello del Spoofing de lado y entramos en el mundo de la encriptación y la autentificación. Dos términos muchas veces parejos, pero muy diferentes. La encriptación es la forma de modificar los datos para que estos esté protegidos, cifrados… la autentificación por el contrario no implica un cifrado, sino un reconocimiento de la identidad, al menos por parte de uno de los implicados, ya sea de un sistema, de un usuario…

En realidad este debería de haber sido el primer artículo, por encima de Spoofing. Todo lo que se vea aquí será aplicado, tratado y mencionado en cualquier otro artículo con casi total seguridad. Aquí hablaremos de las medidas tecnológicas que poseemos para evitar cualquier tipo de inseguridad en la red y por supuesto también de las herramientas disponibles para poner en jaque estas medidas tecnológicas:



Herramientas Utilizadas/Material necesario: (No todo es necesario, dependiendo de la plataforma a usar, de cada sección y de lo que a cada cual le sea más cómodo)

Seguridad: Encriptación y Autentificación. Capítulo Quinto -> Ataques y Vulnerabilidades contra la Criptografía

ATENCION: Los ejemplos que se van a mostrar y “tutoriales” tan solo tienen carácter educativo. En ningún aspecto comparto filosofías de invasión a la intimidad, ataques contra un sistema informático o cuestiones similares. En la medida que sea posible siempre se usarán ejemplos y formas que puedan ser usados por cualquier persona, de forma que pueda verificar los contenidos escritos. No obstante, por motivos más que obvios, materiales como contraseñas, nombres de usuarios o de hosts, serán omitidos o modificado en las capturas de pantallas realizadas (o las lineas escritas). Es decir, los ejemplos serán completamente reales, los datos mostrados a vosotros necesarios para poder pertrechar estos ejemplos no siempre lo serán (Sí lo serán los resultados). Para que esto conste de forma clara, todo material sensible modificado o falso estará resaltado en ROJO. Por motivos de seguridad, todo el material que sea expuesto aquí (exceptuando software propietario o libre, citaciones expresas o código de terceros) tanto texto, imágenes y código son propiedad del autor y está completamente prohibido su reproducción completa o parcial en otros lugares, espero que se comprenda.

 

Ataques y Vulnerabilidades contra la Criptografía

Para acabar con el tema de Encriptación y Autentificación, es obligado mostrar sus vulnerabilidades. Es cierto que muchos de los ataques y vulnerabilidades de la criptografía son simplemente teóricos, se conocen que son efectivos pero no es posible llevarlos a cabo por una u otra razón. No obstante, es una búsqueda constante. En el mundo existen increíbles criptólogos con una formación en matemáticas y en la creación de algoritmos seguros sin igual. Pero como todo en esta vida nada, y repito nada, está exento de posibles ropturas.

En realidad esto es importantísimo, tanto las mentes que son capaces de diseñar algoritmos como los que tenemos como aquellos que pasan horas y horas intentando lograr un ataque exitoso contra un sistema criptográfico. Porque así es la única forma real de poder construir sistemas seguros. Si nadie se dedica a estudiar estos sistemas, es posible que diversos atacantes puedan disponer de herramientas y materiales para poder llevar a cabo un acceso no autorizado a un sistema o la interceptación y descifrado de cualquier mensaje. En cambio, cuando tienes a muchísimas personas que trabajan incluso para ello, para lograr fallos de seguridad en estos sistemas, estos mismos intentos te están garantizando que el sistema es seguro, puesto que aun no se han logrado romper. No hay que olvidar por supuesto los numerosos concursos anuales de criptografía, en los que se están desafiando constantemente a organizaciones y particulares a resolver un problema dado, por ejemplo revertir un cifrado asimétrico o simétrico, revertir un Hash…

Por suerte y por desgracia, no son pocas las herramientas, método o sistemas que existen actualmente para poner en jaque la seguridad de todos los sistemas actuales. Suerte porque permite mejorar los sistemas, desgracia porque estos métodos son usados continuamente por hackers y otros para violar un sistema. Vamos a ver algunos de ellos. Podemos decir que prácticamente cualquier método “seguro” tiene un posible ataque que puede aplicarse para romper dicho sistemas:

  • Colisiones y preimagen
  • Rainbow Tables
  • Brute Force Y Diccionarios
  • Criptoanálisis
  • Ataques Side Channel

El término “Criptoanálisis”, dependiendo de la bibliografía a la que se acuda, puede ser interpretado como un término genérico que englobaría prácticamente a todos los sistemas de ataques contra la criptografía. No obstante, nosotros lo entenderemos como un conjunto de técnicas basadas en el análisis puro y duro de ciertos aspectos del cifrado para poder romperlo.

El término estrella aquí es ¿Qué es un ataque? ¿Qué se considera romper un sistema criptográfico?
Esto se dejó ver en otros capítulos. Un ataque es cualquier intento que tenga como objetivo romper un sistema criptográfico, entendiendo con “roptura” no solamente la obtención de la clave de dicho cifrado o de invertir un hash o… Una roptura criptográfica es un concepto amplio, en el que evidentemente el mejor de los casos e ideal pasa por lograr obtener la clave en caso de un cifrado simétrico o asimétrico, pero como hemos dicho, no solo se interpreta una roptura por ello. Una roptura criptográfica podría implicar:

  • Obtención de la clave simétrica (en caso de un cifrado simétrico)
  • Obtención de la clave pública (en caso de un cifrado asimétrico)
  • Obtención completa o parcial del mensaje original a partir de un mensaje cifrado sin necesidad de la clave.
  • Encontrar algoritmos capaz de rebajar en X magnitudes la probabilidad de tener éxito con fuerza bruta o colisiones.
  • Una colisión en un Hash.
  • Encontrar algoritmos capaz de rebajar en X magnitudes la capacidad de cálculo necesaria para poder solucionar las “matemáticas imposibles”
  • etc…

Esto implica que una roptura puede verse como tal desde un punto de vista práctico o teórico. Así por ejemplo si se encontrase una forma de romper AES-128 en 2100 Operaciones en vez de 2128 , constituiría una roptura desde el punto de vista teórico, pero no desde un punto de vista práctico, puesto que aun así sería “imposible” realizar un ataque para obtener una key en un tiempo razonable. Visto esto podemos comenzar a ver algunos de los ataques más usuales, algunos de los cuales ya se han visto por encima.


Colisiones y Preimage

El concepto de Colisiones fue tratado en parte en el capítulo sobre Hash. Un Hash criptográfico pretende ser una función de un único sentido, siendo por tanto imposible a priori invertirlo. Un hash por otro lado funciona como un sistema de “compresión”, dado que para cualquier tamaño de datos de entrada, la salida siempre se mantendrá con una longitud fija. Por definición propia, si la longitud del Hash es fija existirán infinitos mensajes que puedan resultar en un mismo hash. Simplemente conociendo la longitud del hash, podemos conocer a priori el número de mensajes máximos que podrán emitirse antes de que un mensaje produzca un hash repetido. Esto es una Colisión. Los Hash criptográficos intentan no obstante la imposibilidad de poder crear dos mensajes diferentes que compartan el mismo hash ó crear un mensaje diferente a otro para que compartan el mismo hash. Pero como hemos dicho, se tienen en cuenta a la hora de crear los hash para que en la práctica no sea posible, dado que en la teoría simplemente por estadística esto no es así.

Así mismo, también hablamos del problema que entrañaba la paradoja del cumpleaños, la cual hace posible que existan colisiones entre dos mensajes cuales quiera a una razón mucho menor al número total de mensajes posibles. Es decir, la probabilidad de que un mensaje coincida con otro para MD5, el cual es un hash de 128 bits, sería 1 entre 2128. No obstante, la posibilidad de que dos mensajes cualesquiera puedan producir una colisión, simplemente por la paradoja del cumpleaños, se debe de calcular.

Estadísticamente, tomados X elementos de un todo Y en el cual esos X elementos pueden ser repetidos, se tiene que para la probabilidad P, existen dos elementos de X que son él mismo, según la fórmula:

X(P,Y)= Raiz (2Y Ln (1/1-P))

MD5 = 128 bits = Y
P = 99% = 0.99 = > Nunca se puede garantizar una probabilidad del 100%

X(99%, 2128) = Raiz ( 2129 Ln (100))= Raiz (2129 * 4.6) = 265 Aproximadamente.

Pero la paradoja del cumpleaños tan solo es un reto más al que tienen que enfrentarse cualquier Hash criptográfico. Al margen de este tipo de análisis estadístico, se suele atacar al algoritmo propio, logrando en muchos casos unas reducciones increíbles en la posibilidad de encontrar una Colisión. Por suerte o desgracia, para MD5 “recientemente” se logró reducir el índice de colisión a tan solo 210. Y este índice si deja de ser un índice teórico y pasa a ser una aplicación práctica.

¿Pero que importancia tiene esto?
Si recordamos, la firma digital no es más que el cifrado asimétrico del hash del propio mensaje/certificado…. Si se produjese cualquier cambio en dicho mensaje, al comprobarse la firma el hash no coincidiría, el mensaje sería rechazado. ¿Pero que sucedería si pudiésemos construir dos mensajes diferentes que produjesen el mismo hash?. Podría malignamente enviar un mensaje A al usuario X, y esperar que este me firmase el contenido. Dado que dispongo de un mensaje B (completamente diferente a A) que satisface al mismo Hash, podría copiar la firma del mensaje A y plasmarla en mi mensaje B. Ahora podría usar mi mensaje B como si hubiese sido firmado por el usuario X.

Similarmente, es posible intentar vulnerar un hash por medio de un ataque conocido como “preimage” (preimpagen). Mientras que las colisiones buscan encontrar dos mensajes cuales que produzcan el mismo Hash, una preimagen lo que busca es encontrar un hash o un mensaje concreto. Asi, si se de lo que se pretende es de encontrar un mensaje X que satisfaga un Hash dado estaríamos ante un “Primer Ataque de Preimagen” (Se denomina así). No obstante, si lo que se quiere lograr es encontrar un segundo menseje Y (diferente a X) que satisfaga el hash del mensaje X, estaríamos ante un ataque conocido como “Segundo Ataque de Preimagen“.

En la actualidad no existe ningún ataque de preimagen factible a ningún Hash. Así por ejemplo, el Hash MD4 (128 bits) posee un ataque de preimagen que puede llevarse a cabo en 264, pero aun así, 264 no es computacionalmente factible, teniendo en cuenta que MD4 está prácticamente en desuso. Si es computacionalmente posible realizarlo de cara a que puede ser posible llevarlo a cabo, pero de ninguna manera en un entorno real.

Tanto las Colisiones como los ataques de preimagen, suponen un riesgo continuo a los hash criptográficos. Es la razón por la que los viejos Hash van dejando paso a los nuevos Hash. MD2, MD4… MD5 ya ha comenzado a dejarse de usar en muchos lugares, imponiéndose de forma mayoritaria SHA-1, para el cual lo mejro que se ha logrado es una colisión con u índice de 251, siendo poco práctico su aplicación. A todo ello hay que sumarle que pronto estará disponible SHA-3, que sustituirá definitivamente SHA-1 y SHA-2 (este último posee índices de colisión menores que SHA-1)

 

Rainbow Tables

La idea de las tablas Rainbow es imitar las tablas lookup, es decir, usar espacio en disco para ahorrar tiempo de cálculo. En programación, las tablas lookup son una herramienta fundamental para agilizar muchísimas tareas que de otro modo consumirían muchísimo tiempo de ejecución de un programa. A groso modos, son tablas precalculadas que serán usadas posteriormente, sin que sea necesario realizar el cálculo que llevó el crearlas. El ejemplo más simple quizás sea en de las operaciones trigonométricas.

Si tenemos un programa que tenga que calcular en algún momento alguna operación trigonométrica, simplemente podría ser realizada con la función especifica para ella: Sin(X), Cos(Y).. operación que se realiza en tiempo de ejecución por el procesador, y que son operaciones normalmente costosas. Si nuestro programa debe de realizar una operación trigonométrica de forma aislada no importa, pero imaginar que el programa tiene que ejecutar operaciones trigonométricas a matrices inmensas (por poner un ejemplo). El tiempo invertido en calcular constantemente dichas funciones puede ser solventado usando una tabla. Simplemente, en tiempo de programación, el programador creó una tabla con por ejemplo 360 elementos, y a cada uno de ellos le calculó el Coseno. Dicha tabla estática la implementa en su programa como una constante. Si no requiere una precisión mayor a un grado, el programador cada vez que necesita conocer una razón trigonométrica podría simplemente redondear a la unidad más cercana y usar dicho valor como índice de la tabla. Tendría el valor de la razón trigonométrica al instante sin necesidad de calcularlo.

El concepto de una Tabla Rainbow es el mismo. Por tanto, la tabla Rainbow más simple (e idílica) sería precalcular TODOS los posibles Hash de todas las combinaciones posibles de un alfabeto dado de un número de caracteres dados. Es decir, si nuestro alfabeto son tan solo los números 0-9 y se permite una longitud máxima de 5 elementos, la tabla Rainbow contendría el Hash de 1 millón de elementos, desde el 0 hasa el 999.999. De este modo, si se quisiese conocer en cualquier momento el hash de cualquier número comprendido entre 0-999999 sería instantanio, sin necesidad de calcular el Hash de dicho número. Pero en el caso de los Hash la utilidad es doble. La utilidad es dotar a la función Hash de un camino inverso. En nuestro caso, si sabemos que el dato buscado es un número comprendido entre 0-999.999 no tendríamos que realizar 1 millón de operaciones, tan solo realizar una búsqueda en la tabla para encontrar la equivalencia.

El problema de esta tabla Rainbow de ejemplo es que no es útil. en este caso, para 5 elementos y un alfabeto de 10 elementos (0,1,2,3,4,5,6,7,8,9) tendríamos una tabla con un millón de elementos. Si por ejemplo el Hash calculado fuese MD5, sería 128 bits por hash, es decir, el Hash ocuparía 16 Bytes por cada celda del array (de la tabla). En el mejor de los casos (en este caso concreto), podríamos usar el mismo número buscado como índice de la tabla, con lo que no sería necesario otra celda de al menos 4 Bytes. Es decir, en este casi tan simple tendríamos: 1 millón de elementos * 16 Bytes = 15.26MB aprox. Es decir, en este caso tan simple sería necesaria la friolera de 15MB de espacio en disco. Esto es una cantidad irrisoria en los días de hoy, pero también es cierto que los elementos y el alfabeto seleccionado es de lo más trivial. Si pensásemos en un alfabeto comprendido entre 0-9, a-z (sin contar carácteres en mayúscula) y con una longitud de 8 elementos tendríamos la nada despreciable cantidad de 2.821.109.907.456 posibilidades, o lo que es lo mismo, aproximadamente una tabla de 328 TeraBytes. Es evidente que no es factible.

La solución a este problema llega con “Divide y Vencerás”. Se crean tablas muy grandes, pero para salvaguardar tamaños tan extensos se aplican diferentes técnicas que logran reducir el tamaño a costa evidentemente de tener que realizar ciertas operaciones. El problema siempre será el mismo, llegar a un compromiso entre velocidad-espacio en disco. A tablas más grandes, el tiempo necesario para localizar el elemento será menor, a tablas más pequeñas el tiempo empleado será mayor.

Las tablas Rainbow para lograr este compromiso, lo que realizan es aplicar una serie de transformaciones a los datos de entrada, formando una cadena desde estos (el dato de entrada) hasta un dato final. Al finalizar el proceso, la tabla tan solo contiene el elemento inicial y el final de la cadena. Para verificar si un hash se encuentra en la tabla, lo primero que se le realizará a dicho Hash es aplicar la última transformación (de reducción) que se aplicó en la cadena de la tabla hash. El resultado será buscado en los elementos finales de la tabla Hash. Si el elemento se encuentra, se partirá del elemento parejo de la tabla, al cual se le realizarán las transformaciones pertinentes que se aplicaron a la tabla originalmente, hasta encontrar en la cadena el elemento deseado. Si no se encuentra en la tabla al realizar la última transformación, se partirá de la penúltima transformación y posteriormente la última. Al terminar se vuelve a comprar si se encuentra como elemento final. Estas transformaciones se tratan fundamentalmente en partir de un texto plano cualquiera, por ejemplo la cadena “aaaaaa”. A dicha cadena se le calcula el Hash. Al Hash resultado se le aplica una función de reducción que hace que el hash sea transformado en un texto de nuevo (aunque esta función de reducción no es la función inversa del Hash). Al texto obtenido se le calcula de nuevo el hash y así continuamente, según el número de reducciones que se estén aplicando. A más reducciones menor es la tabla necesaria y más tiempo se requiere para generarlas y utilizarlas. Un ejemplo sencillo de como se construiría una tabla hash y cual sería la tabla Hash resultante final:

Texto PlanoHash OriginalReducción 1Hash 1Reducción 2Hash 2Reducción 3Texto PlanoReducción Final
aaaaaa0B4E7A0E5FE80B4E7AEBC4C39A693EEBC4C3D54E764C3A8AD54E76aaaaaaD54E76
bbbbbb875F26FDB1CE875F26B0A1E4DDF443B0A1E48B701D6DA9228B701Dbbbbbb8B701D
Administrador2A2E9A5810272A2E9ABC291090759ABC2910D605381C2106D60538AdministradorD60538
ContraseñaB489B4014A83B489B46BA499D1C52C6BA499A996250124DDA99625ContraseñaA99625

Las 7 primeras columnas de la tabla serían datos procesados para la creación de la Rainbow table. En este sencillo ejemplo se usarían solo 3 reducciones. Al texto de entrada se le aplica el hash deseado, en el ejemplo un hash MD5 truncado a los 6 primeros bytes. Una vez se ha calculado el hash este es convertido por una función de reducción a “texto plano”, en este caso la función de reducción no es más que tomar del hash los primeros 3 bytes (de ahí lo de divide y vencerás). Una vez finalizada la primera reducción se vuelve a empezar, es decir, se calcula de nuevo el hash al nuevo “texto plano” y otra reducción, después se le calcula el hash y de nuevo otra reducción. En este caso 3 reducciones, y las 3 actúan del mismo modo. La tabla Hash es constituida por tanto tan solo con los registros iniciales (el texto de inicio) y el resultado de la reducción final, formando una tabla tan solo de dos columnas.

Si un usuario quisiese atacar un hash MD5 con el ejemplo anterior, tan solo tendría que llevar a cabo una serie de comprobaciones:

a) Dado el Hash “H” de entrada se le aplica la última función de reducción. En este caso las 3 son iguales -> R (H)
b) Se realiza una búsqueda del resultado obtenido en el apartado anterior en la segunda columna. Llegados a este punto pueden suceder dos cosas. Hay una coincidencia (Saltar al paso E), no hay coincidencia (pasar al paso C)
c) De no obtener resultado, se iran realizando en cada paso una reducción anterior más, con su cálculo de Hash, de este modo, a cada paso se va recorriendo más la tabla hacia atrás. En el peor de los casos, se tendría que aplicar la reducción primera al hash H, calcular el hash a la reducción, volver a reducir, volver a calcular hash y volver a reducir.
d) De no lograr una coincidencia, la tabla rainbow a fallado y el ataque se da por fallido.
e) Si se encuentra la coincidencia, se tomará el elemento de la primera columna y se comenzará a realizar la cadena hasta que se localice la reducción que produce dicho hash. El resultado por tanto será la reducción.

Veamos esto. Imaginar que tenemos el nombre de usuario y contraseña de un usuario en este MD5 inventado, y que dichos hash son:

Usuario (U)= 2A2E9A581027
Contraseña (C)= EBC4C39A693E

2A2E9A581027 -> Red. 3 (U) = 2A2E9A -> Búsqueda en 2º columna de Tabla -> Fracaso
2A2E9A581027 -> Red. 2 (U) = 2A2E9A -> Hash = BC291090759A -> Red. 3 (Hash) = BC2910 -> Búsqueda en tabla -> Fracaso
2A2E9A581027 -> Red. 1 (U) = 2A2E9A -> Hash = BC291090759A -> Red. 2 (Hash) = BC2910 -> Hash = D605381C2106 -> Red. 3 (Hash) = D60538 -> Búsqueda en tabla -> Éxito!
Registro asociado a D60538 = Administrador
Hash (Administrador) = 2A2E9A581027 -> ¿2A2E9A581027 = 2A2E9A581027? -> Usuario (U) = Administrador

EBC4C39A693E -> Red. 3 (C) = EBC4C3 -> Búsqueda en 2º columna de Tabla -> Fracaso
EBC4C39A693E -> Red. 2 (C) = EBC4C3 -> Hash = D54E764C3A8A -> Red. 3 (Hash) = D54E76 -> Búsqueda en tabla -> Éxito!
Registro asociado a D54E76 = aaaaaa
Hash (aaaaaa) = 0B4E7A0E5FE8 -> ¿0B4E7A0E5FE8 = EBC4C39A693E? -> Fracaso
Hash (aaaaaa) = 0B4E7A0E5FE8 -> Red. 1 (Hash) = 0B4E7A -> Hash = EBC4C39A693E -> ¿EBC4C39A693E = EBC4C39A693E? -> Contraseña (C) = 0B4E7A

En este caso, todas las reducciones son iguales, pero esto normalmente no es así, y cada reducción es una función diferente. Si se recorre la tabla hash completa y se realizan todas las iteraciones sin encontrar coincidencia, la tabla Rainbow ha fallado, y con ella el ataque efectuado a dicho hash.

Este sistema es increíblemente efectivo y rápido para ser capaz cualquier atacante a revertir cualquier hash “simple”, de modo que un atacante pueda normalmente obtener el usuario o contraseña que originó dicho hash. No obstante las tablas Rainbow tiene una utilidad relativa. Primero, computar una tabla hash relativamente completa requiere de muchísimo tiempo, es por ello por lo que no es raro encontrar tablas “pequeñas” que cubren tan solo un espacio relativo, por ejemplo una tabla Rainbow que sea capaz de revertir cualquier Hash MD5 con un diccionario de a-z, A-Z de hasta 7 caracteres. Y ya no solo es el tiempo necesario para computarla, sino el espacio en disco. Dado que tanto el espacio para calcular las tablas hash, así como su tamaño en disco depende prácticamente tan solo del tamaño del diccionario, algo que tendría que tener siempre en cuenta el usuario es escoger contraseñas o nombres de usuario de una longitud relativamente larga (al menos 8 caracteres para contraseñas) y usando combinaciones de letras mayúsculas, números y signos. Esto lo comprenderemos mejor en los ataques de fuerza bruta. La idea es que aunque se requiera de un tiempo ingente necesario para precalcular las tablas Rainbow, una vez creadas estas pueden ser reutilizadas una y otra vez. Existen multitud de lugares que venden tablas rainbow ya creadas.

Otra alternativa altamente eficaz, es usar Salt. Esto es algo que ya se comentó en su momento. Salt suele ser un número determinado de bits que se añade al mensaje de entrada para conformar un hash mucho más seguro. De este modo entre otras cosas, hace que las tablas rainbow sesan completamente ineficaces. La única forma sería constituir nuevas tablas rainbow computando todas las alternativas posibles con el Salt. Dado que el Salt puede ser modificado en cualquier momento, las tablas Rainbow tendrían que ser reconstruidas cada vez. Salt suele ser un dato conocido, pero no por que sea conocido implica que el sistema sea menos eficaz. Según lo explicado con anterioridad, si se añadiese un número indeterminado de bits a nuestro mensaje original, este no podría ser revertido por la tabla hash, puesto que jamás se encontraría en ella. Normalmente se usa algo como lo siguiente:

Contraseña: Perico -> Hash (Contraseña) = 5E48C54D938DC613366C1212E5FA7349
Salt: 0A1B2C3D4E5F
Hash Seguro = Hash (Contraseña.Salt) -> Hash Seguro = Hash (Perico.0A1B2C3D4E5F) = 21208C690B7ECCF92518D8055E9B361D

El segundo Hash no sería jamás encontrado en una tabla Rainbow, a menos que se hubiese generado para tal efecto, cosa muy poco probable. Dado que la Salt suele cambiar, lo normal es que el mismo hash es transmitido con la salt, para que se sepa que Salt se ha usado, y se tenga en cuenta a la hora de verificar el usuario o la contraseña. Por ello podría enviarse la contraseña mediante un Hash con Salt como:

21208C690B7ECCF92518D8055E9B361D.0A1B2C3D4E5F

Es decir, se adjunta la Salt.

Actualmente no obstante las tablas rainbow continuan siendo bastante útiles. Por ejemplo, pensar en los nombres de usuarios y contraseñas de Windows, los cuales son almacenados con un hash conocido como Hash NT. Use o no use Salt dicho hash, ya existen tablas precomputadas increiblemente eficaces capaces de revertir casi cualquier contraseña menor a 13 caracteres, use los caracteres que use.

Para acabar, vamos a ver como es posible revertir un Hash gracias a estas tablas. Vamos a ver lo “simple” que puede ser revertir un Hash MD5 que se ha enviado desde un PC cliente a un servidor para la autentificación en un foro o a un correo electrónico. Dado el tiempo necesario para precalcular una tabla hash “completa”, vamos a crear una tabla rainbow muy pequeña. En este caso he usado el software del proyecto RainbowCrack:

Caracteres: Letras minúsculas, es decir, de ‘a’ a la ‘z’
Longitud Mínima: 1
Longitud Máxima: 7
Indice de éxito: 98% de acierto
Cantidad de Cadenas por tabla: 4.000.000
Longitud de cada Cadena: 2.400
Tablas necesarias: 6
Tiempo de cómputo de las tablas: 6 Tablas *5 minutos por tabla = 25 min
Tamaño Total de las tablas: 366 MB, 61 MB por tabla

Línea de Comando usada:

C:\Users\Theliel\Desktop\rtgen md5 loweralpha 1 7 0 2400 4000000 0
C:\Users\Theliel\Desktop\rtgen md5 loweralpha 1 7 1 2400 4000000 0
C:\Users\Theliel\Desktop\rtgen md5 loweralpha 1 7 2 2400 4000000 0
C:\Users\Theliel\Desktop\rtgen md5 loweralpha 1 7 3 2400 4000000 0
C:\Users\Theliel\Desktop\rtgen md5 loweralpha 1 7 4 2400 4000000 0
C:\Users\Theliel\Desktop\rtgen md5 loweralpha 1 7 5 2400 4000000 0

Una vez las tablas han sido creadas y preparadas, tan solo es necesario introducir el hash que se desea invertir. La utilidad de dividir una tabla rainbow en trozos no es otro que evitar generar un solo archivo monstruoso, de esta forma es facil crear tablas rainbow con la ayuda de muchos voluntarios, cada uno por ejemplo podría generar una sola tabla. Con las tablas generadas, deberíamos de ser capaces de invertir con un 98% de acierto cualquier hash que venga de un nombre de usuario, contrasaeña… que contenga menos de 8 caracteres y esté en minúsculas sin números ni signos. Veamos ejemplos:

Usuario: 664DA32C1BA6F93F2899FE82C73DBFAF
Contraseña: B67885AB956F9D8F8946768F2E362E92

C:\Users\Theliel\rcrack *.rt -h 664DA32C1BA6F93F2899FE82C73DBFAF
traversing rt group #0 for 1 hash (remain = 0, traversed = 0, skipped = 0)
traversing rt group #1 for 1 hash (remain = 0, traversed = 0, skipped = 0)
disk: md5_loweralpha#1-7_0_2400x4000000_0.rt: 64000000 bytes read
searching for 1 hash…
disk: md5_loweralpha#1-7_1_2400x4000000_0.rt: 64000000 bytes read
searching for 1 hash…
plaintext of 664da32c1ba6f93f2899fe82c73dbfaf is theliel
disk: thread aborted

statistics
——————————————————-
plaintext found: 1 of 1
total time: 1.78 s
time of chain traverse: 0.41 s
time of alarm check: 0.11 s
time of wait: 1.15 s
time of other operation: 0.11 s
time of disk read: 1.67 s
hash & reduce calculation of chain traverse: 5752802
hash & reduce calculation of alarm check: 1171435
number of alarm: 1662
speed of chain traverse: 14.17 million/s
speed of alarm check: 10.65 million/s

result
——————————————————-
664da32c1ba6f93f2899fe82c73dbfaf theliel hex:7468656c69656c

C:\Users\Theliel\Desktop\rcrack *.rt -h B67885AB956F9D8F8946768F2E362E92
traversing rt group #0 for 1 hash (remain = 0, traversed = 0, skipped = 0)
disk: md5_loweralpha#1-7_0_2400x4000000_0.rt: 64000000 bytes read
disk: md5_loweralpha#1-7_1_2400x4000000_0.rt: 64000000 bytes read
searching for 1 hash…
traversing rt group #1 for 1 hash (remain = 0, traversed = 0, skipped = 0)
searching for 1 hash…
plaintext of b67885ab956f9d8f8946768f2e362e92 is talento
disk: md5_loweralpha#1-7_2_2400x4000000_0.rt: 64000000 bytes read
disk: thread aborted

statistics
——————————————————-
plaintext found: 1 of 1
total time: 0.76 s
time of chain traverse: 0.45 s
time of alarm check: 0.08 s
time of wait: 0.22 s
time of other operation: 0.02 s
time of disk read: 0.75 s
hash & reduce calculation of chain traverse: 5752802
hash & reduce calculation of alarm check: 1124940
number of alarm: 1624
speed of chain traverse: 12.73 million/s
speed of alarm check: 14.42 million/s

result
——————————————————-
b67885ab956f9d8f8946768f2e362e92 talento hex:74616c656e746f

 

Increíble, ¿cierto? En un par de segundos el hash ha sido invertido. Estas tablas podrían ser reutilizadas cada vez que se necesitase, aunque es evidente que las tablas creadas son limitadas. Imaginar el proceso con tablas mucho más completas. A día de hoy es posible invertir cualquier hash cuyo mensaje original sea menor a a unos 13 caracteres simples. Queda una incógnita por cubrir… en realidad infinitos mensajes de entrada pueden producir el mismo hash en la salida. Esto implica que en una misma tabla hash podrían ocurrir colisiones, en las que dos mensajes tienen el mismo hash. Lo normal en estos casos sería listar todas las posibilidades encontradas, el sentido común haría el resto.

¿Conclusión? Usar siempre contraseñas seguras, contraseñas de longitud nunca menor a 8 caracteres y usando combinaciones de letras mayusculas y minusculas, números y símbolos. De cara a un programador, jamás usar Hash sin salt. Las tablas Rainbow son un recurso poderosísimo como hemos podido ver, capaz de romper casi al instante un hash. La siguiente pregunta podría ser como puede un atacante obtener un hash, pero esto está indicado en el tema sobre Sniffing.

 

Brute Force y Diccionarios

Hasta ahora todo lo que hemos visto es como atacar a un Hash. Ahora veremos un par de sistemas que podrían ser usados prácticamente para atacar cualquier sistema criptográfico, ya sea un cifrado simétrico, asimétrico o un hash.

Brute Force es un término coloquial para designar un tipo de ataques que se versa simplemente en el poder computacional de los sistemas modernos. Brute Force (Fuerza bruta) básicamente lo que realiza es probar una a una todas las combinaciones posibles de una posible key (en caso de un cifrado) o posibles hash en caso de un hash. De echo, las tablas Rainbow serían algo así como unas tablas precomputadas brute force para los hash, ya que lo que contienen no es más que todas las posibles de la entrada. Las técnicas de fuerza bruta no obstante suelen quedarse como última solución, ya que su éxito o fracaso tan solo está directamente relacionado con la complejidad de la contraseña, y como hemos dicho ya por complejidad nos referimos al set de caracteres usado, así como a la longitud de esta.

La fuerza bruta clásica es simple de comprender. Imaginar que se tiene un maletín con apertura con combinación con 3 ruletas de números, que van entre 0-9 y cuya key hemos olvidado. Podríamos probar todas las opciones posible para tratar de adivinar cual es: “000, 001, 002, 003, 004… 997, 998, 999″. Serían unas 1000 combinaciones. Esto hacerlo a mano podría ser incluso factible, pero tan solo estamos hablando de 3 cifras (caracteres). Si transladamos esto a un algoritmo como AES cucya Key se desconoce, es exactamente lo mismo, serían necesarias unas 1000 combinaciones (Siempre hablando en el peor de los casos) para lograr la key. Pero que sucede si aumentamos ese “Set de caracteres”?

Actualmente la capacidad de cálculo de un procesador es impresionante, y si incluimos la posibilidad de poder usar nuestra tarjeta de vídeo para dicho propósito, podemos multiplicar incluso por x100 o x1000 el rendimiento!! Pero aun así, ¿hasta que punto es posible atacar con fuerza bruta un sistema? Primero tendríamos que presuponer una capacidad de cálculo estimada de nuestros sistemas, y a partir de ahí hacer suposiciones y aproximaciones de hasta que complejidad es viable atacar una key por fuerza bruta. El problema es que el tiempo para poder verificar una key u otra varía del algoritmo usado. Veamos algunos ejemplos sobre la capacidad de cómputo de un PC, las mostradas corresponden aproximadamente al PC usado en la redacción de este artículo:

Algoritmo CryptoZip: 50 Millones de contraseñas por segundo -> Clásico cifrado usado en archivos ZIP
Algoritmo AES-256: 1000 contraseñas por segundo -> Cifrado simétrico actual usado en archivos ZIP

Como podemos ver, hay más que ligeras diferencias. Con esos datos, podríamos por tanto esclarecer aproximadamente la viabilidad de poder romper una key en un tiempo razonable. Según esos datos, vamos a ver el tiempo estimado (máximo) necesario para romper diferentes ejemplos:

Key numérica CryptoZip de 13 caracteres de longitud: 67 horas -> viable
Key numérica CryptoZip de 17 caracteres de longitud: 257 días -> “viable”
Key minúscula CryptoZip de 11 caracteres de longitud: 884 días -> no viable
Key minúscula CryptoZip de 8 caracteres de longitud: 1.2 horas -> viable
Key minúscula+numérica CryptoZip de 11 caracteres de longitud: 86 años ->no viable
Key minúscula+numérica CryptoZip de 8 caracteres de longitud: 16 horas ->viable
Key minúscula+numérica+mayúscula CryptoZip de 9 caracteres de longitud: 9 años -> no viable
Key minúscula+numérica+mayúscula CryptoZip de 8 caracteres de longitud: 51 días -> “viable”
Key minúscula+numérica+mayúscula+símbolos CryptoZip de 8 caracteres de longitud: 3 años -> no viable
Key minúscula+numérica+mayúscula+símbolos CryptoZip de 6 caracteres de longitud: 3.2 horas -> viable

Key numérica AES-256 de 9 caracteres de longitud: 9 días -> “viable”
Key minúscula AES-256 de 7 caracteres de longitud: 97 días -> “no viable”
Key minúscula+numérica AES-256 de 6 caracteres de longitud: 26 días -> “viable”
Key minúscula+numérica+mayúscula AES-256 de 5 caracteres de longitud: 10.7 días -> viable
Key minúscula+numérica+mayúscula+símbolos AES-256 de 4 caracteres de longitud: 19.2 horas -> viable

De todos estos datos podemos sacar ciertas conclusiones. Cuando se está usando un algoritmo antiguo o relativamente rápido de verificar, sería posible recuperar keys de hasta 15 caracteres aproximadamente si es solo numérica, de unos 8-9 si contiene tan solo letras minúsculas y números, pero no más de 6-7 caracteres para keys que son complejas.

En caso de AES-256 es aun peor. En el mejor de los casos, tan solo podríamos intentar romper keys de hasta 9 caracteres de longitud si fuesen tan solo numéricas. Para el resto de los casos, contraseñas mayores de 4-6 caracteres que fuesen complejas serían imposible de romper por fuerza bruta al estilo más clásico.

No obstante existen multitud de técnicas basadas en fuerza bruta para mejorar en mucho estas cifras. Por supuesto, en el momento que sales del método tradicional, abandonas la posibilidad de lograr la recuperación al 100%. La idea es intentar mantener el mayor índice de porcentaje posible reduciendo al máximo el número de combinaciones posibles. El problema de este método es que suelen estar basados en la estadística y otras técnicas, en la suposición, en lo que podemos llamar “común”:

  • Diccionarios: Se presupone que la key/contraseña escogida pertenece a una palabra que existe en un diccionario previamente creado o calculado. La idea nace de que lo normal es que las personas usen nombres comunes para sus claves y contraseñas. No obstante los diccionarios más sofisticados no solo incluyen aquellas palabras que existen en un lenguaje u otro, sino posibles alternativas a ellas. El diccionario contendrá aun así cientos o miles de millones de posibles opciones, pero siempre serán exponencialmente menos que combinaciones posibles por fuerza bruta.
    Dado los múltiples problemas de esta técnica, suele usarse conjuntamente con métodos híbridos. Por ejemplo a la lista de entrada se le realizan modificaciones a todas sus letras de modo que se verifiquen todas las combinaciones posibles de cada entrada con letras mayúsculas o minúsculas. Así por ejemplo si tenemos la entrada “casa”, se probarán diferentes versiones de esta: “casa, Casa, cAsa, caSa, casA, CAsa, CaSa… CASA”. Esto hace aumentar enormemente el espacio de claves a probar, pero continuaría siendo exponencialmente menor a un ataque de fuerza bruta clásico.
    Otra posible “optimización” a un ataque de diccionario es la combinación. Es una cuestión de conocer como piensan los usuarios. Si bien es cierto que existe un porcentaje alto de usuarios que usan palabras “naturales” para sus contraseñas/keys, también existe un porcentaje alto que cree que una combinación de estas dos palabras resulta en una contraseña más segura. Por ello, otra mejora habitual en los ataques por contraseña es permitir la combinación de dos, o incluso tres, palabras que se encuentran en el mismo diccionario. De este modo si en el diccionario tenemos las palabras: “casa” y “antonio”, nuestro ataque comprobaría: “casa, antonio, casaantonio, antoniocasa”.
    Los ataques de diccionario son increíblemente rápidos, pero en contrapartida son completamente ineficaces cuando la contraseña/key usada no se encuentra en ellos, lo cual es facil si se crea esta sin ser una “palabra” con “sentido”.
  • Fuerza bruta “inteligente”: La idea ha sido siempre reducir al máximo las combinaciones posibles. El diccionario es una técnica realmente eficaz, pero depende enormemente del diccionario, del lenguaje… y por supuesto del usuario y la contraseña que haya podido establecer. La fuerza bruta establece que cualquier combinación es posible (y realmente es así), en cambio esto no es cierto si se atienden a las estadísticas de los usuarios, contraseñas comunes, palabras empleadas, frases empleadas… lo cual lleva a replantearse la fuerza bruta. ¿Es posible eliminar combinaciones (estadísticamente hablando) por ejemplo si tenemos una key de hasta 8 caracteres en minúsculas? La estadística dice que existen combinaciones de letras que jamás se darán. Por ejemplo, no existen palabras en español que estén constituida por dos letras seguidas, excluyendo la “erre” y la “ele” (quizás exista alguna, pero el ejemplo es claro). Esto hace eliminar de un plumazo una cantidad considerable de combinaciones. Esto crea una serie de normas que van eliminando combinaciones y más combinaciones al ataque de fuerza bruta clásico, por ejemplo interpretando las letras que pueden ser usadas al inicio o al final, letras que suelen ir juntas o letras que no…
    Este tipo de fuerza bruta decrementa enormemente las posibles combinaciones, lo que hace que el ataque pueda ser llevado a cabo mucho más rapido. En contra partida de nuevo tenemos que un usuario podría siempre crear una key/contraseña que se saltase estas medidas. Por ejemplo la contraseña: “tYb,3hI?” sería imposible de detectar por ningún sistema casi con toda seguridad, tan solo por fuerza bruta clásica.
  • Plantillas: Con plantillas nos referimos a la posibilidad de poder acotar la búsqueda de una key por fuerza bruta basándonos en ciertas reglas que nosotros mismos especificamos. Por ejemplo una plantilla podría ser simplemente especificar los primeros 4 caracteres de la contraseña, dejando para la fuerza bruta tan solo otros 4. O por ejemplo una plantilla podría ser igualmente especificar una palabra que estamos seguro que la clave contiene, dejando a la fuerza bruta que compruebe todas las posibilidades teniendo en cuenta que existen por ejemplo 4 caracteres que siempre estarán juntos, estén al inicio, en medio, al final…
    El problema con las plantillas es que dependen casi en su totalidad en lo que se pueda conocer a la víctima y que tipo de palabras ha podido usar. Pensar por ejemplo en fechas de cumpleaños, aniversarios… podríamos especificar por ejemplo que se verificasen todas las combinaciones posibles de hasta 12 caracteres que contengan la fecha “22051950″. Dado que son 8 caracteres, tan solo serían 5 caracteres por combinar, es decir, los 4 caracteres restantes que completarían los 12 caracteres más la fecha en sí, que sería tratado como un carácter más.
    De nuevo la eficacia dependerá de factores externos, como lo bien o mal que se conozca a quien puso la contraseña, a la suerte, a la perseverancia…

Posiblemente, uno de los “crackers” más famosos fue siempre John The Ripper, que fue creado originalmente para lograr obtener las contraseñas de Unix, almacenadas todas ellas tradicionalmente en un hash basado en DES (cifrado simétrico). Con el tiempo, el soporte para este “crackeador” de contraseñas fue ampliándose, soportando otros hash como los que usa Windows para almacenar sus claves de sesión. Esto puede hacernos pensar que el uso de la fuerza bruta ha ido cada vez más relegándose a un segundo plano, dada la complejidad del calculo necesario para poder computar contraseñas/key actuales. En cambio, la fuerza bruta posee dos cualidades únicas que hacen que posiblemente siempre sea una opción viable a considerar. Esto es así por dos motivos:

El primero, la fuerza bruta tiene un índice de probabilidad del 100% y teóricamente “siempre” podrán realizarse (en realidad existen métodos criptográficos en los que la fuerza bruta no es posible realizarse), solo es cuestión de tiempo, ya sean 1000 años o dos segundos.
La segunda característica, es que aunque sea necesario un mayor tiempo de cómputo o se usen cada vez keys más largas y complejas, la capacidad de cálculo actual se va incrementando de igual modo. Lo que actualmente un PC puede llevar a cabo en un año, simplemente por tener una tarjeta de video por ejemplo con soporte para CUDA, puede ser suficiente para reducir ese año a simplemente algunos segundos. Esto es posible a que la capacidad de cálculo en paralelo de una tarjeta de vídeo es muy superior a un procesador tradicional. Por ejemplo, es posible que la nueva generación de tarjetas de nVidia, la esperada familia basada en Fermi, pueda incrementar en un x10000 la velocidad de cómputo de contraseñas AES-256 especificadas anteriormente, eso hace que de 1000 contraseñas por segundo se pase a lo mejor a 10.000.000 de contraseñas por segundo. Es decir, no hay que perder de vista jamás que las capacidades de cálculo son mejoradas cada día, tanto tarjetas de vídeo como procesadores. Lo que hoy no es viable, mañana puede ser completamente viable.

El mejor ejemplo de esto es RSA. Es imposible factorizar en tiempo factible una key RSA-1024… pero esto tan solo es cierto a medias. Quizás fuese imposible hace unos años, quizás es imposible actualmente… pero cada día que pasa es más posible. Eso hace que actualmente RSA-1024 esté siendo sustituido casi en su totalidad a RSA-2048, es casi seguro que que vivamos para ver que RSA-4096 es lo mínimo para mantener el sistema seguro. Es decir… Brute Force será posiblemente siempre una técnica usada y que tendrá siempre una efectividad decente.

Para acabar, vamos a ver lo simple que es usar John The Ripper para extraer las contraseñas de usuario de un iPod/iPhone. Todos sabemos que cuando se le realiza JB es posible acceder a él por medio de SSH. También sabemos que posee dos usuarios: “root” y “mobile”, y que en ambos la contraseña es “alpine”. ¿Pero como se ha llegado a esta disertación? ¿A caso Apple ha filtrado estas contraseñas? Vamos a extraerlas.

Lo primero que necesitamos es conocer en un sistema Unix en que archivos se almacenan las contraseñas. Esto se hace normalmente en uno o en dos, dependiendo si se está usando un ocultador o no. Si no se está usando, lo normal es que estas contraseñas y usuarios se encuentren en un archivo llamado passwd, que contiene los nombres de usuarios y las contraseñas en un hash-cifrado basado en DES llamado shadow. Dichos archivos en el iPod/iPhone se llaman “passwd” y “master.passwd”.

Una vez se obtienen ambos archivos, se debe de generar un archivo único que integra ambos archivos (esto es así por el propio sistema que usa UNIX para ello). Una vez obtenido este archivo único se realizaría un ataque de fuerza bruta. Dado que UNIX usa un hash muy débil (basado en DES), es fácil romperlo:

C:\Users\Theliel\Desktop\>unshadow passwd master.passwd > contra
“contra” es el archivo “unificado”

C:\Users\Theliel\Desktop\>john contra
Loaded 2 password hashes with 2 different salts (Traditional DES [64/64 BS MMX])
alpine (mobile)
testtest (root)

guesses: 2 time: 0:00:10:47 (3) c/s: 2134K trying: testtart – testzirz

Para esta prueba, la contraseña de la cuenta mobile fue establecida de nuevo a su contraseña origen, y la contraseña root fue establecida a “testtest” para tener una contraseña con longitud de 8 caracteres. Hay que tener en cuenta que iPod/iPhone no soporta contraseñas mayores de 8 caracteres. Se puede observar como el ataque tubo éxito, siendo necesario tan solo unos 11 minutos en llevarse acabo. Este ataque de fuerza bruta difiere quizás un tanto del clásico ataque de fuerza bruta, dado que va dirigido a un Hash y no a un cifrado, pero básicamente es exactamente igual.

Si las tablas rainbow nos enseñaron a la necesidad de crear siempre los hash con salt, la fuerza bruta y todas sus variantes nos enseñan que la mejor protección ante este tipo de ataques no es solo un buen sistema de cifrado, sino una key, contraseña, clave de paso… que sea segura, con una longitud decente, que no sea personal, que… cuando se toman las medidas oportunas, este tipo de ataques está evocado al fracaso.

 

Criptoanálisis

El término Criptoanálisis es un poco ambiguo en la medida que podríamos considerar como “criptoanálisis” prácticamente cualquier ataque que queramos realizar contra la criptografía. En cambio podríamos, como ya dije en su momento tomar por criptoanálisis tan solo aquellas técnicas, generalmente estadísticas en combinación (o no) con otras, para lograr el resultado deseado, que puede ser desde la roptura completa de un sistema obteniendo una key, accediendo simplemente a la información cifrada o… así por ejemplo, la paradoja del cumpleaños aunque es usada para crear colisiones en los hash, podría interpretarse como tal como un sistema de criptoanálisis.

Esto no es un método nuevo creado en el siglo XXI, sino bastante antiguo. La idea de estudiar un manuscrito e intentar descifrarlo la conocemos desde los mismos jeroglíficos a notaciones musicales o muchos lenguajes ya desaparecidos. ¿Por qué? Es fácil, la mejor forma de “traducir” (aquí usamos el término descifrar) algo que se desconoce es buscar patrones en común, palabras que se repitan constantemente, distribución de los caracteres a lo largo del escrito… todo ello ayuda sobremaneramente para lograr una “traducción” de algo desconocido. En el caso de la criptografía en realidad es muy similar. Un ejemplo claro de criptografía lo encontramos cuando se habló de los diferentes modos de cifrado de los bloques de criptografía simétrica, en el que se sometió el cifrado CBC a un test sobre una imagen para verificar su fortaleza. En realidad, ese test lo que hace es mostrar gráficamente una serie de patrones repetidos por toda la imagen.

Entre los ataques de criptoanálisis más comunes podemos encontrar:

  • Análisis de Frecuencias
  • “Texto codificado” conocido
  • “Texto plano” conocido
  • Texto plano/codificado escogido

El análisis de frecuencias pudimos ya comprobarlo cuando vimos el método de codificación por bloques CBC. Pero puede ilustrarse de un modo aun más simple. Imaginar por ejemplo el cifrado de sustitución más simple, en el que cada letra del abecedario se mapea a otra letra de este. La key por tanto sería tan solo este mapeo. Es decir, si la Key fuese:

ZYXW….

Significaría que la A sería sustituída por la Z, la B pro la Y, la C por la X… para descifrar un texto de esta forma, tan solo tendría que tener la otra parte la mismaplantilla. Al leer Z la sustituiría por una A, las Y por B… este tipo de cifrado aunque pueda parecer trivial ha sido muy usado en la antigüedad. Hay que tener en cuenta que las matemáticas modernas, así como los dispositivos de computación que tenemos a día de hoy no se encontraban disponibles muchos años atrás, y que un cifrado tan aparentemente simple como el explicado podía ser suficiente para que, por ejemplo, dos amantes compartiesen cartas comprometidas, sin que ninguna tercera persona lograse descifrarlas.

Es cierto que con los sistemas modernos de codificaciones por bloque, los análisis de frecuencias van teniendo cada vez menos interés como método directo para estudiar un cifrado, no obstante continúa siendo usado tanto para verificar la resistencia de un buen cifrado como en la búsqueda de otros sistemas mucho más sofisticas en combinación con estos.

Estos análisis de frecuencias han sido muy usados durante muchos años, y a día de hoy constituyen siempre un comienzo a la hora de estudiar un cifrado concreto. Podríamos destacar igualmente el método de Kasiski, similar al que vamos a ver a continuación, pero orientado a conocer la longitud de las palabras, o extender el análisis de frecuencia al índice de coincidencia. Dependiendo de que tipo de cifrado sea, quizás sea mejor usar un método u otro. Para quien quiera jugar con todo esto, les recomiendo una vez más Cryptool.

Vamos a crea un ejemplo con el cifrado más básico de sustitución y verificar que con un ataque de análisis de frecuencia es posible recuperar el texto original. Gracias a ello, se podrá ir recuperando al mismo tiempo la “key” usada en el cifrado de dicho mensaje. Para llevar esta labor a cabo, tendremos que partir de un texto cifrado por sustitución, e intentar obtener el mensaje original a partir de este. Para este ejemplo he partido de un pequeño fragmento de “El Zahir”, un libro de Paulo Coelho (gran escritor, el libro es mu interesante igualmente). Dicho fragmento ha sido procesado con CryptoTool para generar un texto cifrado por sustitución usando una key aleatoría. Recordar que la key no es más que un mapeo de un carácter a otro, en el que ningun caractar en este caso está repetido, es decir, la asociación es 1 <– >1:

piczyiugwtxhzrxibkziqejiywxbikkziynwiqngsijmnifgypzjwzeirwjpigbaztxjugin
ikkitiyczypzikkzugiikkznirwfznwjzbrxnizkxyxsxykzjzvxbexjkzugiyiagiyxkxibp
xbhiynikwljzjirinwvzcwjibhzyxhxbpjzjwxeibyzjirwzmbxhcibxhcimrwzjihxjrzb
rxbgiypjzcwypxjwzhwibpxynwkiyritihiywbpibpzbrxriyhgljwjiknxnibpxibikugi
niiugwtxugimbgiypjxyhznwbxyineivzjxbzrwypzbhwzjyi

Al texto superior se le han eliminado tanto signos de puntuación como espacios, para que no sea posible percibir inicios o fin de palabras. Podemos ver el esquema que se ha usado para realizar esto:

Un texto original se cifra por medio de sustitución con una “key” que descnonocemos. Después de realizar la operación de cifrado, enviamos como texto plano el resultado para poder visualizarlo: “Texto cifrado”. Al mismo tiempo, la salida cifrada se pasa de nuevo por el descifrador que debería de devolvernos el texto original reconstruido: “Texto Reconstruido”. Dado que no hemos comenzado a aplicar el análisis de frecuencia, actualmente el texto Reconstruido es exactamente igual al texto cifrado. Por último se puede observar como a la salica cifrada se le ha aplicado un pequeño analizador de frecuencia, el cual nos devielve el porcentaje de aparición de cada letra. Visto de una manera más gráfica tenemos:


Frecuencia de caracteres del Texto Cifrado


Con estos datos, podemos comenzar por tanto un sistema de deducción basado en la estadística. Según la gráfica superior, el 16,37% de todos los caracteres son “I”, el 9.82% “Z”… ¿Como nos vale esto? Recurriendo ni más ni menos que a la estadística. Estos son los datos obtenidos de nuestro texto cifrado. ¿Pero que dicen las estadísticas del lenguaje castellano de forma general? Es decir, si conociésemos la frecuencia “global” media de las letras escritas de nuestro lenguaje, podríamos comenzar a deducir y reemplazar. En mi caso he usado como referencia la frecuencia de caracteres de “El Quijote”. Con cerca de medio millón de palabras, puede servir a groso modo como dato “fiable”. Lo ideal sería establecer una frecuencia basada en diferentes tipos de textos, a poder ser mucho más largos. Pero a modo de ejemplo es suficiente:


Frecuencia de Caracteres de "El Quijote"


Con este patrón que creemos “fiable” podemos por tanto comenzar a conjeturar. Según la frecuencia basada en “El Quijote”, las vocales ‘E’ ‘A’ y ‘O’ serían las letras con mayor frecuencia y en dicho orden. Si estableciésemos una correspondencia directa entre ambos análisis, tan solo tendríamos que sustituir las vocales citadas por aquellos caracteres con mayor frecuencia en el texto cifrado, que serían en el mismo orden: ‘I’ ‘Z’ y ‘X’. Si volvemos a CryptoTool y añadimos dichas letras en las posiciones adecuadas, comenzaremos a tener una primera versión de texto reconstruido, siempre y cuando la hipótesis aplicada de frecuencias sea correcta: ‘I = ‘E’, ‘Z’ = ‘A’, ‘X’ = ‘O’

pecayeugwtoharoebkaeqejeywobekkaeynweqngsejmnefgypajwaeerwjpegbaatojugen
ekketeycaypaekkaugeekkanerwfanwjabroneakoyosoykajavobeojkaugeyeageyokoebp
obheynekwljajerenwvacwjebhayohobpjajwoeebyajerwambohcebohcemrwajehojrab
robgeypjacwypojwahwebpoynwkeyreteheywbpebpabroreyhgljwjeknonebpoebekuge
neeugwtougembgeypjoyhanwboyeneevajobarwypabhwajye

Aun con 3 posible letras descodificadas, es imposible tener algo legible. Eso sí, hay que tener en cuenta que cada letra que es sustituídas y dado que es una sustitución 1 <–> 1, implica que para el resto de los caracteres las posibilidades van decreciendo igualmente. Podríamos continuar con las dos siguientes, pero si contemplamos las estadísticas de nuestro texto cifrado, tanto la ‘B’ como la ‘Y’ poseerían un porcentaje igual. En cambio si acudimos a las frecuencias de nuestros datos muestra, tenemos que las dos siguientes letras corresponderían a la ‘S’ y la ‘N’ en dicho orden. No obstante, podemos acudir a la frecuencia de repetición de dos caracteres juntos iguales. Si lo hacemos, obtenemos que los caracteres más repetidos (en parejas) correspondiente a nuestro texto cifrado son:

II: -> 2 apariciones, 0,59% del total
KK -> 4 apariciones, 1,18% del total

Y del mismo modo para nuestro texto de muestra:

LL:9258:0,00467523338292373
RR:2378:0,00120087545739821

De forma aplastante, LL es el carácter más repetido estadísticamente en nuestros datos de muestra. Si observamos los caracteres repetidos en nuestro texto cifrado tan solo tenemos dos, II y KK. No obstante, ‘I’ =’E', luego podríamos asumir sin duda alguna que ‘K’ = ‘L’. Al ser un texto pequeño, no disponemos de otros caracteres dobles que podamos sustituir por ‘R’. Pero al igual que tenemos carácteres dobles ampliamente usados en nuestro lenguaje, también tenemos combinaciones de 3 caracteres que prevalecen sobre las demas, como es el caso de ‘QUE’. Estadísticamente es la asociación de tres letras más repetida con muchísima diferencia. Si examinamos las agrupaciones de 3 caracteres en nuestro texto cifrado, existe curiosamente una asociación de 3 caracteres con un 1.46% de aparición, que corresponde a las letras ‘UGI’, si tenemos en cuenta además que la ‘I’ es una ‘E’, es evidente que U = Q y G = U

pecayequwtoharoeblaeqejeywobellaeynweqnusejmnefuypajwaeerwjpeubaatojquen
elleteycaypaellaqueellanerwfanwjabronealoyosoylajavobeojlaqueyeaueyoloebp
obheynelwljajerenwvacwjebhayohobpjajwoeebyajerwambohcebohcemrwajehojrab
robueypjacwypojwahwebpoynwleyreteheywbpebpabroreyhuljwjelnonebpoebelque
neequwtoquembueypjoyhanwboyeneevajobarwypabhwajye

Con el trabajo realizado por ahora, es posible ir dividiendo ya algunas de las palabras que van apareciendo, y sustituir también la ‘W’ = ‘I’, dado que es la vocal que nos resta, y después de QU -> es evidente que si no es una ‘E’, será una ‘I’. Con todas las vocales despejadas, y aun sin conocer cuales corresponderían estadísticamente a la ‘N’ y la ‘S’, si nos restaría con una probabilidad de 6.85% la ‘J’ de nuestro texto cifrado, que equivaldría a ‘J’ = ‘R’ en nuestros datos de muestra. Podemos por tanto agregarlo todo:

pecay equitoharoeblaeqereyiobellaeynieqnusermnefuypariaeerirpeubaatorquen
elleteycaypaella que ella nerifanirabronealoyosoylaravobeorlaqueyeaueyoloebp
obheynelilrarerenivacirebhayohobprarioeebyareriambohcebohcemriarehorrab
robueypraciyporiahiebpoynileyreteheyibpebpabroreyhulrirelnonebpoebelque
ne equitoquembueyproyhaniboyeneevarobariypabhiarye

Con ello podemos deducir sin mucho trabajo, ahora sí: ‘bueyproy’ que ‘B’ = ‘N’ e ‘Y’ = ‘S’, no hay más remedio, y poder formar así ‘NUESXRO/S’, con lo que además obtenemos también ‘P’ = ‘T’:

te cas equitoharo en la eqeresion ella esnieqnuserm ne fustaria eerirte unaatorquen
elletescastaella que ella nerifaniranronealosososlaravoneorla que se auesoloent
onhesnelilrarerenivacirenhaso hontrario eensare riamnohcenohcemriarehorranro
n
uestra cistoria hientosnilesretehes intentanroreshulrirel nonento en el que
ne equitoque m nuestros haninos eneevaronaristanhiarse

Lo cual nos hace resolver del todo el texto cifrado. Si sustituimos la ‘H’ = ‘C’, ‘N’ = ‘M’, ‘M’ = ‘Y’, ‘F’ = ‘G’, ‘E’ = ‘P’, ‘R’ = ‘D’

te has equitohado en la eqpresion. ella es mi eqmuser y me gustaria pedirte un aatorque
me lletes hasta ella, que ella me diga mirandome a los osos la ravon por la que se aue solo entonhes
melilrare de mi vacir en caso contrario pensare ria y noche noche y ria recordando
n
uestra historia cientos miles de teces intentando desculrir el momento en el que
me equitoque y nuestros caminos empevaron a distanciarse

Por último, solo nos queda terminar de colocar las pocas letras que nos quedan, añadir los espacios que nos restan y en todo casi si queremos añadir acentos, comas y otros para que el texto tenga mayor sentido. El texto descifrado correspondería a:

“Te has equivocado en la expresión. Ella es mi ex-mujer y me gustaría pedirte un favor: Que me lleves hasta ella, que ella me diga mirándome a los ojos la razón por la que se fue. Solo entonces me libraré de mi Zahir. En caso contrario pensaré día y noche, noche y día… recordando nuestra historia, cientos, miles de veces, intentando descubrir el momento en el que me equivoqué y nuestros caminos empezaron a distanciarse”

 

Texto codificado conocido puede parecer una perogrullada, parece evidente que siempre tendremos acceso al texto codificado, máxime cuando precisamente lo que se quiere realizar es desencriptarlo. Pero se especifica para indicar que tan solo tenemos acceso a dichos mensajes codificados. Un ataque de estas características implicaría estudiar tan solo los mensajes cifrados, y a partir de ellos lograr de alguna forma invertir el cifrado de estos, recuperar la key o lo que sea posible. Parece imposible a simple vista que simplemente por el estudio de estos mensajes cifrados se pueda llevar a alguna conclusión, en cambio ya vimos por ejemplo con el análisis de frecuencia (que realmente se aplica a un mensaje ya cifrado) que esto es posible.

Un ejemplo muy interesante sobre esto es una de las muchas vulnerabilidades de WEP, ese “sistema de seguridad” WIFI que aun está implantado en más de un 50% de los hogares, me atrevo a decir. WEP usa como vimos en su momento un sistema de cifrado simétrico basado en flujo, en concreto el algoritmo se conoce como RC4, y básicamente lo que hace es generar un flujo constante de bits que hacen de key para los datos que se van enviando/recibiendo, y dicho flujo es al mismo tiempo generado en el otro punto de la comunicación. La forma en la que se cifran los datos en RC4 dijimos que era realizando una operación lógica XOR entre el mensaje original y la key del stream (del flujo). El problema aparece cuando dos mensajes diferentes son encriptados con la misma key-stream. ¿Como es esto posible? es simple, si la key maestra no se modifica, la key-stream generada no será modificada tampoco. Para evitar que la key-stream se pueda repetir, se usa un vector de inicialización que se concatena con la key maestra, y a partir de dicha asociación se genera el stream necesario. Cada paquete enviado incluirá un vector de inicialización diferente, generado aleatoriamente, y que será transmitido al medio sin cifrar conjuntamente con el paquete cifrado, para que de este modo, los destinos puedan conoce el IV usado, concatenar el IV (vector de inicialización) con la key maestra que tienen y con ello generar el key-stream del paquete para poder desencriptar el contenido.

En teoría podría parecer un sistema seguro, el key-stream es diferente en cada paquete, con lo que no hay duplicación de key-stream. El problema es que el vector de inicialización de WEP es de 24 bits, es decir… es muy pequeño. ¿Que probabilidad existe de que se produzca una colisión? Es decir… ¿que se generen dos IVs iguales? podríamos decir que 224 pero como quedó ya constante, por la paradoja del cumpleaños esto no es así:

X(P,Y)= Raiz (2Y Ln (1/1-P))

Para una probabilidad de 0.99 (99%) necesitaríamso en el peor de los casos 12.431 paquetes aproximadamente. Es decir, cada trece mil paquetes wep, al menos dos estarán usando la misma key.

Ahor abien… ¿como influye esto? Tan solo hay que saber que la operación lógica XOR posee la propiedad conmutativa (y por supuesto su tabla de verdad). Imaginar por tanto que tenemos en nuesras manos 2 mensajes diferentes cifrados con la misma key-stream:

A y B son los mensajes, Cifrado (A) y Cifrado (B) los mensajes que hemos capturado, los cuales comparten la misma key. K es la key del paquete, es decir, la concatenación de la Master Key y el IV. Sk (K) sería por tanto la key-stream

Cifrado (A) = A XOR Sk (K) -> El cifrado de A se forma mediante el mensaje original y XOR key-stream
Cifrado (B) = B XOR Sk (K) -> El cifrado de B se forma mediante el mensaje original y XOR key-stream

Cifrado (A) XOR Cifrado (B) -> Por la propiedad conmutativa y con las ecuaciones superiores tenemos que:
(A XOR Sk (K)) XOR ((B XOR Sk (K)) = A XOR B XOR Sk (K) XOR Sk (K) -> Sk (K) XOR Sk (K) = 0 por definición
Cifrado (A) XOR Cifrado (B) = A XOR B

Es decir, si se realiza la operación XOR entre ambos mensajes encriptados, el resultado es el mismo que si se realiza la operación XOR a los mensajes no cifrados. La utilidad es inmediata, dado que sería posible descifrar el contenido de los mensajes originales, en el peor de los casos haciando un poco de fuerza bruta. Un ejemplo:

k 1= IV | MK
ks = RC4(k1)

A= 01011
B= 01101
ks= 11011

Cifrado (A) = 10000
Cifrado (B) = 10110

Cifrado (A) XOR Cifrado (B) = 00110 = A XOR B -> Se cumple!!

Se podría pasar a usar ahora por ejemplo fuerza bruta para intentar descubrir los posibles mensajes originales. Es cuestión de analizar las probabilidades que existen de encontrar el mensaje original, e ir probando. En el momento además que se obtenga uno de los mensajes, el otro es encontrado de forma automática también.

Acabamos de ver lo que entendíamos por la técnica de “texto cifrado conocido”, del mismo modo tenemos también la técnica conocida como “texto plano conocido“, en la que ahora no solo disponemos del texto cifrado, sino que también disponemos de todo o parte del contenido original. Es evidente que en este caso lo deseado no es obtener algo que ya tenemos. La idea es recuperar el resto del mensaje cifrado en caso de que tan solo tengamos el mensaje parcial o por el contrario ser capaces de recuperar la key original por medio de esta técnica.

Posiblemente el mejor ejemplo de “texto plano conocido” que podemos encontrar sea el sistema usado por el compresor ZIP. Esta técnica permitía extraer todos los archivos cifrados de un ZIP, sin necesidad de contraseña, simplemente poseyendo un archivo sin cifrar que estuviese ya dentro de dicho ZIP. Es decir, imaginar un archivo ZIP encriptado con una contraseña con las fotos más comprometidas de nuestros hermanos. Imaginar que tenemos alguna foto que el nos ha enseñado sin encriptar, fuera del ZIP. Podríamos recuperar todo el contenido.

Otro ejemplo podría ser también un cifrado como el que hemos hablado antes, de sustitución. Con saber una letra o un par de ellas del mensaje original, podría ser suficiente con suerte para llegar a deducir el resto. No hablo solo al cifrado de sustitución que ya mostré, sino alguno que pueda ser más complejo. De todos modos, es un sistema relativamente poco efectivo en los métodos de codificación modernos, siendo realmente vulnerabilidades de las propias implementaciones las que hacen posible este tipo de ataques y no el cifrado en sí.

Por último, podríamos disponer ya no solo material cifrado o sin cifrar como el que hemos visto, sino que material cifrado o sin cifrar que nosotros escogemos a conciencia para poder realizar nuestro criptoanálisis. Se conoce como “texto escogido”. Normalmente esta no es una opción viable, dado que es complicado poder disponer de un material cifrado o sin cifrar que hemos seleccionado previamente. No podemos decirle a una persona a la cual le interceptamos un mensaje que nos envíe otro mensaje tal y como nosotros lo queremos. Es decir, esta técnica queda reservada a un “pequeño” grupo, no de manera generalizada.

Por un lado tenemos los cifrados asimétricos, en los cuales en cualquier momento si que podemos disponer de cualquier material cifrado y sin cifrar que provenga de la clave pública del objetivo. Es cierto que no podremos disponer de texto escogido cifrado que provenga de su clave privada, pero al menos ya es algo. Es más, muchos de los ataques que se han realizado a sistemas RSA, han estado basados en textos escogidos para poder lograr (o no) la key privada. Aunque normalmente, estas vulnerabilidades suelen ser más propias de las implementaciones. Por ejemplo, sería muy interesante ver el comportamiento de una implementación SSL/TLS frente a lo mejor un mensaje creado a propósito que tan solo contiene una cadena inmensa de contenido vacío (0×00), o variar la longitud a voluntad para ver que tipo de Padding se está usando, o intentar… es decir que las opciones son múltiples. Es una herramienta muy poderosa, pero como hemos dicho reservada tan solo a escenarios bastante concretos.

Por otro lado podríamos tener aquellos sistemas en los que pudiésemos “obligar” a un cliente a enviarnos material específico. Esta por ejemplo es otra vulnerabilidad de nuestro ya más que hablado WEP, y es además como la mayoría de los atacantes logran recuperar las contraseñas WEP de los usuarios que aun las usan. Este ataque está basado por ejemplo en el reenvío masivo de paquetes ARP (ARP no será tratado en estas líneas). WEP no modifica en modo alguno la longitud de los paquetes, recordar que usa XOR para cifrarlos. ARP por otro lado son paquetes con una longitud determinada y que son fácilmente reconocidos por cualquiera, incluso estando cifrados. Estos paquetes ARP que son ampliamente conocidos, tienen una cabecera de 16 bytes que es común a todos ellos!. Es decir, los primeros 16 bytes de un paquete ARP son siempre los mismos, exactamente:

AA AA 03 00 00 00 08 06 -> Los primeros 8 Bytes de un paquete ARP
00 01 08 00 06 04 00 01 -> Los 8 Bytes siguientes de un paquete ARP

El último byte no obstante varía entre 01 y 02 si el paquete ARP es un “response” o un “request”. Por otro lado, dado que la MAC del frame no es cifrada por WEP, conocer si el paquete es un ARP response o un ARP request es sencillo (mirando el destino de la MAC o el origen de ella).

En ese momento ya conoceremos los primeros 16 bytes cifrados de u paquete ARP (enviados por el AP) y los 16 primeros bytes del paquete ARP sin cifrar (deducidos). Dado que los datos son cifrados por medio de XOR, si se realiza un XOR a los datos cifrados con los datos sin cifrar da exactamente la key usada para cifrarlos. Es decir, fácilmente podemos recuperar desde un paquete ARP 16 bytes de la key-stream, y dado que el IV se envía también sin encriptar, también se dispondrá del IV empleado para concatenar la master key que se usó para generar el key-stream

Para poder realizar un ataque completo a WEP es necesario la recolección de cierta cantidad de key-stream, cuando se obtiene dicha cantidad, por medios probabilísticos y un poco de fuerza bruta es posible la obtención de la key:

 

Side Channel

Por último, vamos a hablar del último grupo de posibles ataques a sistemas cifrados que podemos encontrar. Se llaman métodos Side Channel, es decir, métodos “paralelos”, realmente no buscan encontrar vulnerabilidades en el propio cifrado, sino que normalmente en el sistema en el que están implementados o en el medio por el que circulan dichos datos. Ojo!! no a la implementación de ellos!! sino en el sistema que son implementados. Para ello se estudia el comportamiento de dichos sistemas ante un cifrado o un descifrado.

Posiblemente a día de hoy sea el mayor riesgo para los cifrados. Dado que todos estos sistemas están siendo utilizados de un modo u otro en un hardware, este hardware se comportará siempre de manera diferente dependiendo de los datos que circulen por él. Por ejemplo, cuando se está descifrando un código en un PC, algún lugar de este se está procesando dicha Key. Por muy seguro que sea el cifrado si la key se encuentra en dicho momento en memoria, un atacante con acceso a dicho sistema podría intentar recuperar dicha key de la memoria del sistema. O quizás más famosos aun son los ataques de tiempos, que estudian el tiempo que requiere el procesador, la memoroa, la caché… en procesar el encriptado/desencriptado de los datos. En definitiva, la idea es estudiar el entorno y conocer como se comporta este ante diferentes tareas en el cifrado. Esto puede parecer ciencia ficción, pero realmente funciona, y supone u verdadero riesgo para los cifrados simétricos o asimétricos, así como a todas las comunicaciones a día de hoy.

Posiblemente los Side Channel más conocidos sean:

  • Arranque en frío e inicio alternativo
  • Monitorización del hardware
  • Extracción directa
  • Análisis Electromagnético
  • Análisis de consumo y de estados
  • Ataques de tiempo

Cold Boot o arranque en frío es una técnica destinada a la extracción de keys que son usadas por un sistema que aun estén residiendo en la memoria de este. Para que un sistema (ya sea un PC, un procesador criptográfico, un dispositivo portátil…) pueda utilizar una key, esta debe de pasar antes a su propia memoria RAM. La memoria RAM de estos dispositivos suele ser volátil, es decir, su información se pierde (se va degradando paulatinamente) inmediatamente después de que el suministro energético ha sido retirado. Es decir, mientras el sistma está arrancado, es normal que por ejemplo los módulos TPM de los que ya hemos hablado mantengan las Keys en la RAM de estos, que el PC arrancado en Windows tenga las Key de BitLocker o EFS en la memoria del sistema, que la key privada de nuestra smartcard esté en la RAM de este cuando se está usando… etc etc. Lo que sucede es que mientras el sistema está arrancado o en funcionamiento, estas keys pueden estar residiendo en la memoria si se están usando, pero tan solo mientras el sistema está conectado. Al cerrar el sistema y la alimentación se corta, la RAM deja de tener coherencia y los datos simplemente se desvanecen.Es por ello que la memoria necesita lo que se denominan ciclos de refresco, en los que la información de esta es reescrita de nuevo en ellos para que esta pueda mantener su información intacta. Al cortar la energía no se refrescará, con lo que la información se pierde. Esto lo observamos por ejemplo cuando un equipo está en suspensión. Un PC en suspensión en modo S3, deshabilita prácticamente todo el hardware del sistema… menos la RAM, la RAM continuará estando alimentada, refrescándose cuando sea necesario para poder mantener los datos.

Lo que sucede realmente es que esto no es algo inmediato. La información en la RAM no se desvanece de forma inmediata nada más apagar el sistema ni mucho menos, tiene un período de tiempo estimado, en el que a partir de dicho tiempo es una cuestión de probabilidad, hasta que hayan desaparecido del todo. ¿Cuanto es este tiempo? Depende de mil factores, lo que es seguro es que si la RAM se vuelve refrescar, los datos de esta se fijarán. Imaginemos ahora que tenemos ante nosotros un PC en suspensión S3, el cual sabemos que usa BitLocker o EFS para proteger su equipo. Nosotros sabemos que casi con toda seguridad en algún lugar de la memoria se encuentran las keys necesarias para poder acceder al sistema, dado que el propio sistema está arrancado y funcionando. Y aquí es donde aparece el Arranque en frío. Imaginar que durante unos instantes cortamos la energía al sistema, pero la volvemos a restablecer de forma que intentemos mantener intacta la mayor parte de la RAM posible. Al arrancarlo, dado que la RAM es posible que aun mantenga las keys en memoria, podríamos intentar a través de algún inicio alternativo al del sistema para volcar todo el contenido de la memoria en disco, para analizarlo con detenimiento con posterioridad. Quizás no podamos acceder a primera instancia al sistema, pero si podemos iniciar un segundo sistema operativo o alguna herramienta que nos permita realizar la tarea de volcar la memoria, es posible que en la memoria volcada esté aun residente algunas de las keys buscadas.

Se podría proteger así mismo el sistema para evitar incluso el acceso a un inicio alternativo por medio de un HDD externo, USB… pero aun así no sería algo definitivo, dado que siempre se podrían extraer físicamente (cuando sea posible claro) la RAM del sistema e implantarla en otro equipo o analizador para poder volcar su contenido.

Las únicas defensas ante este tipo de ataques es tomar las precauciones necesarias, por ejemplo jamás dejar un sistema que sea crítico conectado a la alimentación si no se está usando, usar hardware específico para almacenar las keys como por ejemplo tarjetas personales, obligar a usar PINs para proteger las keys… en fin. Aunque ningún método es fiable al 100%, al menos siempre se puede complicar la obtención. No pensar solo en un PC cuando se habla de criptografía, un movil, una PDA, una tarjeta inteligente… a fin de cuentas todos los dispositivos electrónicos funcionan de una forma muy similar: Memoria, uno o varios procesadores, registros, puertos de entrada/salida… por eso cualquier sistema que se requiera seguridad, podría implementar medidas para garantizar que cuando el sistema sea apagado las keys ya no residan de modo alguno en memoria, por ejemplo forzando el desmontaje de las unidades cifradas cuando no están en uso y técnicas similares, aunque como se ha dicho, lo mejor es simplemente no usar sistemas de suspensión S3 o de hibernación S4 en sistemas que deseamos que dispongan del mayor grado de seguridad.

Continuando con el estudio del hardware y el arranque en frío, nos topamos con la monitorización del hardware. Es evidente que cuando hablamos de Side Channel lo normal es mezclar la informática con la electrónica al más puro estilo. Dado que podemos conocer el funcionamiento exacto de un hardware o de un módulo TPM, de la memoria, del procesador… podríamos estudiar su funcionamiento electrónico en determinadas tareas, con herramientas como los osciladores, los analizadores lógicos, sensores de temperatura… es evidente que para todo ello es necesario tener acceso al hardware del sistema, tiempo y instrumentación.

Pensar en un sistema en el que las Keys sean almacenadas en un procesador criptográfico tipo TPM, y que este cuando lo cree oportuno carga la key en su propia memoria interna para ser utilizada. Imaginar que disponemos de instrumentación necesaria para “abrir” ese procesador criptográfico, que será un chip encapsulado en plástico, y conectar sus buses de datos a un analizador lógico. Una vez todo el sistema conectado y preparado, se realizará un arranque normal, pero a la par se estaría analizando toda la información que circularía por los buses de datos del módulo TPM. Si en algún momento la key viaja por los buses de datos de este, el analizador lógico será capaz de leerla. Esto mismo es aplicable a un PC, se podría conectar un analizador lógico a los buses de un PC e intentar buscar por ellos el dato deseado. La premisa es la misma, es buscar la key allí donde pueda circular.

Un método más agresivo a la monitorización del hardware sería el intentar la extracción directa. Las keys que son usadas para cualquier tipo de cifrado asimétrico suelen estar almacenadas, es lógico. Lo normal es que estén almacenadas en algún soporte extraible como una tarjeta criptográfica o en algún hardware especializado, tipo TPM. Da igual que estas estén protegidas o no por contraseña, ya que los PIN realmente lo que nos da es la llave para acceder a ella, pero de cualquier forma las keys están en dichos soportes de forma física. Si las keys están en ellas de forma física, en algún lugar de esa electrónica existirá un registro, una pequeña memoria (ya sea Flash, ROM, EEPROM…) que contiene dichos datos sensibles. Visto un todo desde fuera parece simplemente algo absurdo poder mirar ahí, pero desde un punto de vista electrónico es la mejor opción. Hay que tener en cuenta que la mayoría de las memorias ROM, EEPROM, FLash… se acceden de una forma “estandar”. Lo que sucede es que es la misma electrónica y procesadores que están en los circuitos los que es´tan diseñados para que el sistema no pueda acceder a ellos, pero no implica que no se pueda acceder a ellos manualmente. Podría ser por tanto posible acceder a los elementos hardware de dicha tarjeta criptográfica, hardware TPM… de forma que pudiésemos tener acceso a dichas memorias, y que por medio de algunos cables conectados en los puntos exactos y enviando las señales correctas a dicho hardware, este nos devolvería su contenido, revelando así los datos deseados. Es evidente que esto es tan solo la teoría, la práctica es mucha más compleja, se requiere de material especializado para ello y ni siquiera se puede decir que tenga un éxito rotundo, ya que dependerá de la electrónica, de la complejidad, de la seguridad… con la que fue dicho dispositivo creado. A fin de cuenta este tipo de Side Channel tan solo podremos verlo nosotros como teórico, aunque por supuesto es usado de forma práctica. Pensar en espionaje industrial, gobiernos, mafias…

Dejando de momento un poco el hardware concreto, ha existido una técnica sorprendente, yo la llamo análisis electromagnético. En física, cualquier paso de electrones es por un cable produce un campo eléctrico y por tanto un campo electromagnético. Ahora bien, pensemos por ejemplo en un cable de red Ethernet por el cual circula toda nuestra información. Ese flujo de información está produciendo que dicho cable ethernet esté emitiendo constantemente radiaciones electromagnéticas que podrían ser estudiadas, y a través de ellas ser capaces de conocer la información que viaja por ellos. Esta tecnología existe a día de hoy. Si bien es cierto que esto no afecta directamente a los sistemas de encriptación tal y como estamos explicando, estas técnicas podrían ser usadas de igual forma para estudiar las radiaciones electromagnéticas que proceden por ejemplo de una tarjeta criptográfica en funcionamiento, o un módulo TPM, y de este modo, como si de un analizador lógico se tratase, lograr el cometido deseado.

Por otro lado podríamos realizar un estudio analítico del consumo y el estado del hardware en las tareas de codificación/descondificación. Un procesador criptográfico o una CPU no requiere el mismo consumo energético para computar por ejemplo una key de 128 bits que para una de 192 bits. Todo este tipo de información es activamente utilizada en conjunción a otros ataques para poder lograr el fin deseado. Del mismo modo, se pueden monitorizar los estados que ocurren en el procesador, como por ejemplo si el procesador ha pasado a un estado de inactividad C6, si se ha introducido un error controlado en los datos para estudiar como se comporta el sistema… es decir, cualquier “trampa” que podamos imaginar para poder extraer cuantos más datos sea posible sobre el sistema, y con ello lograr descubrir que está circulando realmente por sus interiores, o si la key tiene que tener 4 o 5 caracteres o…

Por último, los análisis de tiempos podemos decir que son similares a los análisis de consumos, solo que en este caso se estudia sobre todo el tiempo de computación. Del mismo modo que el procesador tendrá un consumo mayor para computar una key mayor, también requerirá de más tiempo para dicha labor. Pero es más, es posible incluso que el tiempo que requiera un procesador para cifrar una key, por ejemplo: “101010″ sea diferente a la que se requiera para la key: “101011″ (se ha modificado un bit).

Se podrían estudiar estos tiempos o estados a lo mejor para ser capaz de aplicar correcciones estadísticas a ciertos algoritmos para la obtención de una clave privada desde una clave pública. Si el problema de esta es la imposibilidad de obtener la factorización, por medio de optimizaciones, cribas y otros gracias a estas técnicas, se podría diseñar para un sistema concreto un algoritmo que fuese capaz de factorizar la clave pública en un timpo razonable.

Otro posible uso sería estudiar el tiempo de la latencia de la red, de los sistemas de dos extremos que usen una conexión SSL/TLS y con ello realizar un estudio que pudiera indicarnos cual es la key privada que se está usando, dado que los tiempos, las latencias, los retrasos… todo ello puede verse afectado dependiendo de cada bit que pueda poseer la clave privada.

En Side Channel se estudian todas las posibilidades que puedan brindarnos un mayor grado de información de un sistema. Cuanta más información se pueda extraer de dicho sistema, más fácil o posible será poder atacarlo.

 

Para acabar, Actualmente existen técnicas para poner en jaque prácticamente cualquier tipo de cifrado o sistema de autentificación. Esto no implica que en la actualidad no exista nada seguro, simplemente no existe nada seguro al 100%, aunque si al 99.99%. Con una buena praxis y una buena educación en seguridad, un sistema informático o electrónico puede ser una bastión en toda regla frente a ataques externos.

Seguridad: Encriptación y Autentificación. Capítulo Cuarto -> Aplicaciones Prácticas

ATENCION: Los ejemplos que se van a mostrar y “tutoriales” tan solo tienen carácter educativo. En ningún aspecto comparto filosofías de invasión a la intimidad, ataques contra un sistema informático o cuestiones similares. En la medida que sea posible siempre se usarán ejemplos y formas que puedan ser usados por cualquier persona, de forma que pueda verificar los contenidos escritos. No obstante, por motivos más que obvios, materiales como contraseñas, nombres de usuarios o de hosts, serán omitidos o modificado en las capturas de pantallas realizadas (o las lineas escritas). Es decir, los ejemplos serán completamente reales, los datos mostrados a vosotros necesarios para poder pertrechar estos ejemplos no siempre lo serán (Sí lo serán los resultados). Para que esto conste de forma clara, todo material sensible modificado o falso estará resaltado en ROJO. Por motivos de seguridad, todo el material que sea expuesto aquí (exceptuando software propietario o libre, citaciones expresas o código de terceros) tanto texto, imágenes y código son propiedad del autor y está completamente prohibido su reproducción completa o parcial en otros lugares, espero que se comprenda.

 

Aplicaciones prácticas de la Criptografía y la Autentificación

Todo lo que hemos explicado anteriormente tiene un fin: Usarlo. Hasta ahora tan solo hemos visto la teoría que se esconde detrás de un algoritmo de cifrado de datos o un hash, que es un certificado o una firma digital. Comprendo que no es una parte muy lúdica para aquellos que les gusta la acción, pero en cambio es necesario la comprensión de este tipo de conceptos para poder usarlos. Y es que no son pocas las aplicaciones prácticas de todo lo que se ha explicado, de echo la seguridad actual de la red depende de ello. Así que vamos a ver como usamos realmente todo esto:

  • Encriptación de archivos en disco: Simple, Unidad completa, TPM, EFS, BitLocker.
  • SSL/TLS
  • OpenPGP/GPG
  • Correo Electrónico: S/MIME y GPG
  • Firmas

 

La idea es evidente, usar todo lo citado anteriormente para efectivamente cifrar y asegurar nuestros datos o nuestras comunicaciones. Aunque la idea principal es la misma siempre: “proteger”, cada elemento que deseemos proteger o autentificar empleará posiblemente un sistema diferente.

 

Encriptación de archivos en disco

Así, el punto de partida casi con toda seguridad sería la encriptación de archivos en nuestro propio disco duro. Es evidente que si tenemos información sensible en nuestro equipo, podemos desear que esta esté cifrada para que sea imposible su lectura. Imaginar equipos compartidos, o en entornos mucho más clásicos como el cifrado de datos de material secreto en empresas y similar. Evidentemente si nos referimos ya a la información sensible que puedan tener gobiernos, instituciones o grandes empresas, el uso es ya obligado, nadie quiere que alguien pueda acceder al sistema y robe información que esté desprotegida. Es mucho más eficiente tener la información sensible a buen recaudo.

Visto esto, no todos los modelos de cifrado de dato pueden ser deseables. Lo primero que habría que pensar sería que tipo de archivos se desea encriptar, y si se desea hacerlo de forma simétrica o asimétrica. La filosofía de nuevo difiere en lo que deseemos.

El uso más básico por ello sería el cifrado de archivos individuales. Si aplicamos la lógica de lo visto anteriormente, ¿que tipo de cifrado parecería más lógico aplicar aquí? Posiblemente el Cifrado simétrico. En estos entornos, no solemos necesitar que dicho archivo sea accedido por un millón de personas, todo lo contrario!! En el caso más simple tan solo nosotros deseamos tener acceso al original, luego el cifrado simétrico no parece ser una desventaja. Por otro lado el cifrado simétrico es mucho más rápido, y posiblemente en este caso los archivos a cifrar sean desde pequeños archivos a grandes archivos.

Si optamos por tanto por un sistema de cifrado simétrico podríamos pensar ahora mismo en AES-128 por ejemplo (o AES-192, AES-256). Como dijimos en su momento, no solo es importante seleccionar el algoritmo de cifrado, sino que en el caso del cifrado simétrico es imprescindible la elección de un modo de tratamiento de bloques efectivo, para evitar lo sucedido. entre otras cosas. lo que se pudo observar con las imágenes. De este modo poco a poco podemos ir haciendo una idea de lo que necesitamos, AES-192 y CBC. Esto no significa que no pudiese hacerse de otro modo. Se podría cifrar perfectamente un archivo con cifrado asimétrico o usar otros algoritmos de cifrado simétrico.

Una vez tenemos claras las necesidades tan solo nos restaría tener un software para realizar el cifrado y el descifrado. Actualmente existen cientos de miles de programas para ello, de pago y gratuitos. Algunos soportan un gran rango de algoritmos, otros son más restrictivos.

En nuestro caso vamos a usar de forma didáctica CrypTool. Amén de ver los diferentes resultados, el texto de este archivo y de todos los ejemplos que vamos a ver será siempre el mismo, con un tamaño de 161 bytes:

“Esto es un archivo de ejemplo para encriptar. Podría no ser un archivo de texto y ser un archivo binario, no hay límites en el contenido a cifrar ni en su tamaño”

Usando CrypTool, sería necesario crear primero u esquema de cifrado, después configurarlo y después aplicarlo:

Como vimos en otro capítulo, comenzando por un archivo de texto plano con el texto especificado, se pasa por un cifrado AES-192 CBC. En este punto el destino se guarda en un archivo llamado Cifrado.txt (que pertenece al módulo “Cifrado”) y otra salida se vuelve a pasar por AES-192 CBC (en este caso para desencriptar), obteniendo a la salida un archivo llamado Descifrado.txt. En teoría si el cifrado y descifrado es correcto, el archivo original llamado “A cifrar.txt” con el texto antes especificado, debería de coincidir con el archivo Descifrado.txt byte a byte. Antes de mostrar la salida de los datos, me gustaría explicar brevemente BASE64:

BASE64 es un sistema de codificación ampliamente usado sobre todo en la transmisión de datos. La idea es poder convertir cualquier tipo de dato en un texto plano. De este modo se puede dar una interpretación “escrita” de cualquier archivo binario si se desea. Básicamente 3 bytes binarios se convierte a 4 Bytes en BASE64. Se sacrifica tamaño, pero se gana en facilidad de manejo de los datos, dado que de este modo pueden tratarse como simples cadenas de texto. Quizás no sea la primera vez que lo exponemos aquí, pero sí que será usado. Si quiero mostrar el resultado encriptado del ejemplo anterior, me vería obligado a mostrarlo en hexadecimal, dado que no todos los valores hexadecimales tienen una correspondencia a carácter escrito. No obstante, si puedo convertir el archivo encriptado o el archivo desencriptado a Base64 y mostrar el contenido, contenido que puede posteriormente si se desea revertirlo a binario.

Terminado este paréntesis, en este ejemplo cabe destacar dos cosas. La primera es comprobar si el archivo de origen es igual al archivo final desencriptado. Si no fuese igual el cifrado no sirve. No obstante si verificamos el contenido del archivo “Descifrado.txt” se puede leer el mismo texto… aunque este no tiene 161 Bytes de tamaño, sino 176 Bytes, es decir 15 bytes más. ¿Que ha pasado?. Si comprobamos el archivo Desencriptado.txt en un editor hexadecimal, comprobamos que por una extraña razón, al final del archivo se le ha añadido 15 Bytes con el contenido ox00:

Como podemos ver, parece ser que no ha sido desencriptado correctamente. Si acudimos al archivo cifrado vemos que Cifrado.txt tiene una longitud también de 176 Bytes, luego el problema parece encontrarse en la codificación. ¿Que ha sucedido? El Padding. Recordemos que enun cifrado pro bloques, cuando no hay más datos para rellenar el bloque es necesario rellenarlo con otros datos. El Padding que fue configurado en CrypTool fue precisamente el relleno de ceros. El relleno de ceros es el más simple de comprender, pero no es el más eficaz, ya que a la hora de reconstruir el archivo original es imposible conocer cuantos bytes fueron añadidos, y por ello obtenemos el resultado anterior. Si se hubiese escogido un Padding mejor, podría haberse evitado esto.

¿De donde salen estos 15 Bytes más? Es simple. AES usa un tamaño de bloque de 128 Bits. 161 Bytes * 8 = 1288 Bits. Si los debemos de tomar en bloques de 128, nos deja con 10 bloques completos y 8 bits de pico. Por tanto es necesario rellenar el bloque de tan solo 8 bits para completar los 128: 128-8 = 120 Bits /8 = 15 Bytes. Es decir, para poder completar el último bloque es necesario incluir un padding de 15 Bytes.

Por otro lado, si mostramos el contenido binario del archivo Encriptado.txt (sin usar esta vez la conversión a Base64 y usando mejor una imagen), esto es lo que obtenemos:

A esto nos referíamos con que una conversión a BASE64 resulta muy útil. No podría aunque quisiese exponer el contenido de la derecha, es decir, el contenido interpretado del archivo binario. Las soluciones pasan por expresarlo en hexadecimal (la parte de la izquierda) o expresarlo en BASE64. Normalmente es mejor expresarlo en formato base64 por el motivo que he dado, a la hora de manejar en las comunicaciones los datos, es mejor que estos estén expresados como un texto plano. Así, el texto descifrado expresadoen base64 sería el siguiente:

 

RXN0byBlcyB1biBhcmNoaXZvIGRlIGVqZW1wbG8gcGFyYSBlbmNyaXB0YXI
uIFBvZHLtYSBubyBzZXIgdW4gYXJjaGl2byBkZSB0ZXh0byB5IHNlciB1bi
BhcmNoaXZvIGJpbmFyaW8sIG5vIGhheSBs7W1pdGVzIGVuIGVsIGNvbnRlb
mlkbyBhIGNpZnJhciBuaSBlbiBzdSB0YW1h8W8AAAAAAAAAAAAAAAAAAAA

Da igual que fuesen caracteres no imprimibles, al convertirlos a Base64 podrían ser representados en pantalla, y es por ello que esto se usa extensamente. Cuando hablemos del correo electrónico, Base64 será algo común.


Por otro lado no solo existen técnicas para cifrar un solo archivo. Se podría realizar la misma técnica explicada pero en vez de introducir un archivo de entrada, introducir 200 archivos, 1000 archivos… incluso una unidad completa. El cifrado individual de archivos se ha quedado un poco en desuso, y actualmente tan solo se usa para transmisión de archivos puntuales o material sensible esporádico. Esto ha ido evolucionando y la práctica más generalizada actualmente pasa por el cifrado de una unidad completa

Ahora no buscamos la protección de un archivo concreto, sino de todo lo que se encuentra en la unidad. Esto evidentemente otorga un índice de protección bastante alto, dado que todo lo que se realice en dicha unidad estará siempre protegido. Si dicha unidad fuese sustraída, nuestros datos se encontrarían completamente a salvo. En un primer momento podríamos pensar que este esquema sería exactamente igual que el anterior, pero no es así. La idea es que el contenido accedido se desencripte en el momento de acceder a dicho contenido, y sea encriptado en el momento que se realice alguna modificación. Es evidente que este tipo de esquemas podría reducir las prestaciones de un equipo, dado que se estaría encriptando y desencriptando constantemente. Actualmente existen algunas soluciones para realizar esto.

Existe multitud de software de terceros para permitir la encriptación de volúmenes completos, aunque vamos a centrarnos en herramientas que podemos encontrar ya en nuestro propio sistema: EFS o BitLocker. El problema con el cifrado completo de una unidad es como hacerlo. Realizar un cifrado completo de una unidad es facil, pero ¿como se gestiona para que se pueda hacer en tiempo real? Para nosotros es imprescindible que la tarea sea llevada a cabo de forma transparente.

Por un lado tenemos EFS, “Encryption File System” que está disponible en Windows desde Windows XP. Con EFS se encripta cada archivo que es escrito en el HDD y se desencripta cuando se requiere. EFS usa un sistema híbrido entre cifrado simétrico y cifrado asimétrico, cosa que veremos es muy común uusar. El sistema es simple, cada archivo se cifra con una key por medio de cifrado si métrico. Esta key será diferente a cada archivo, con lo que aun cuando un ataque pudiese recuperar la key de un archivo, esta no sería de mucho valor, dado que tan solo serviría para ese archivo. ¿Implica que el sistema guarda una base de datos con todas las keys, una por cada archivo? No, es más eficiente. Lo que se realiza es cifrar la key usada por cada archivo por medio de cifrado asimétrico, y una vez cifrada se adjunta al propio archivo. Es decir, cada archivo cifrado incluye la key usada para desencriptarlo, claro que antes hay que desencriptar la key por medio de la clave privada del cifrado asimétrico. Comprometer un cifrado asimétrico es mucho más complicado e imposible que el cifrado simétrico. En el peor de los casos en el que el archivo pudiese ser atacado o recobrada su Key, esto no pondría en peligro ni a la clave privada ni al resto de archivos.

Para realizar este sistema, Windows asocia a la sesión del usuario la clave privada requerida para desencriptar las keys individuales de cada archivo. A lo largo de los años, con la aparición de Windows Vista y Windows 7, el cifrado asimétrico RSA se ha sustituido por un sistema de Curva Elíptica, otra “matemática imposible” que tiene ventajas e inconvenientes respecto RSA, a fin de cuenta otro sistema de cifrado asimétrico. Por otro lado se ha permitido poder guardar una key maestra en un dispositivo extraible, desde un pendrive a una Smart Card.

Esto quiere decir que no hace falta recordar una Key (a menos de querer crear una de recuperación) para usar EFS. Para usar EFS tan solo basta con ir a las propiedades de un archivo o carpeta y marcar la opción cifrar. Cuando una carpeta o un archivo sea marcado como cifrado, desde nuestro punto de vista, mientras nuestra sesión esté activa dicho archivo será completamente accesible por nosotros del modo habitual. En cambio si se intentase acceder a dicho archivo desde otra sesión o desde otro equipo, dicho archivo/carpeta sería completamente inaccesible.

Un paso más allá se encuentra BitLocker, disponible tan solo en algunas ediciones de Windows Vista y Windows 7. BitLocker es un sistema análogo a EFS, aunque ambos pueden ser usado conjuntamente. BitLocker es un sistema que puede cifrar una unidad lógica. BitLocker no cifra archivos por así decirlo, sino la unidad lógica completa deseada por medio de AES en modo CBC, por ello es posible usar EFS en conjunción con él. BitLocker funciona no solo a nivel del propios OS, sino que también protege los sectores de inicio. Si Bitlocker detecta un cambio de bios o una modificación en cualquiera de sus elementos como el bootloader, este no desencriptará la unidad lógica, y por ende el sistema no arrancará de ninguna de las formas. Es una capa de encriptación que se coloca por encima del propio OS, siendo Bitlocker el primer elemento en procesarse en el arranque del sistema, como hemos dicho incluso antes de que el propio kernel de Windows sea cargado en memoria.

El método de funcionamiento es simple, nada mas arrancar el sistema, este verifica si todo el boot es correcto o ha sufrido alguna modificación. Si todo es correcto solicita la Key para poder permitir el acceso a la unidad lógica. Si detecta algún cambio en el boot, bloqueará el sistema y obligará a la introducción de una Key de conformidad que verifique los cambios efectuados en dicho Boot. Esto produce dos cuestiones interesantes: Que tipo de subsistema se arranca para que bitlocker se ejecute y como accede bitlocker a las keys.

Para poder usar BitLocker, el sistema debe de generar una partición de pequeño espacio que será la que arranque el sistema, dicha partición no podrá estar encriptada claro está, es tan solo como un subsistema para que bitlocker pueda trabajar de forma correcta. Pero queda el otro problema o ventaja. ¿Como se suministra la Key? En un principio BitLocker requería del uso de un TPM. En Windows 7 es posible usar BitLocker suministrando la key desde un pendrive externo.

¿TPM? TPM son las iniciales de Módulo de plataforma segura. Básicamente es un hardware criptográfico que tiene algunas funciones interesantes. En primer lugar actúa como un acelerador por hardware ya que en su hardware es posible computar hashes o firmas. Por otro lado permite que las creaciones de claves privadas y públicas sean generadas en su propio interior y que estas no sean jamás exportadas al exterior. Si se requiere la clave privada el usuario a través normalmente de un PIN dará acceso al módulo TPM de usarlas. A fin de cuenta es mucho más seguro que nuestra Key privada de nuestro equipo esté almacenada en un hardware que en cualquier otro medio. Incluso si el módulo TPM es sustraído, aunque en teoría sería “posible” de extraer las key del módulo TPM en la práctica esto es “imposible”, de ahí a su seguridad. De este modo el usuario no tiene que preocuparse de Keys, de tener que transportarlas ellos mismos.

Una vez que se habilita BitLocker y la partición es creada, el Hardware TPM se inicializa, se crean las claves necesarias y se comienza con el cifrado de la unidad lógica. Como he dicho en Windows 7 no es necesario por obligación el uso de un módulo TPM, pudiendo usar en su defecto (mucho más inseguro) un pendrive.

BitLocker en Windows 7 se le añadió la opción de poder proteger no solo una unidad del propio sistema, sino unidades extraibles. Una característica que se ha criticado a Microsoft en BitLocker es la no inclusión a sabiendas de algún tipo de puerta trasera que permitiese el acceso al sistema aun cuando fuese cifrado con BitLocker. Esto apareció no hace demasiado, donde autoridades inglesas denunciaban a Microsoft que BitLocker podría ser usado por pederastas en unidades externas para proteger pornografía infantil y otro tipo de contenidos, de modo que no fuese posible la recuperación de estos datos.

Para usar las características de BitLocker tan solo es necesario acudir al panel de control y acceder a BitLocker:

El almacenaje en Smart Card es una práctica muy común, suele ser seguro y además por regla general suelen poseer de hardware criptográfico propio, lo que hace de estos soportes ideales para muchas de estas tareas. Un ejemplo simple de Smart Card criptográfico es el propio DNI-e, el cual contiene los certificados y claves dentro de él.

Podemos decir sin lugar a duda que un Sistema Windows 7 empleando tecnologías como BitLocker y EFS conjuntamente con un módulo TPM supone un sistema muy seguro ante cualquier tipo de intento de robo de información. Esto no quiere decir que no sea posible atacar un sistema similar para acceder a él, pero sí que puede poner las cosas más que complicadas a cualquiera que lo intente.

 

SSL/TLS

SSL/TLS son protocolos de seguridad para permitir una conexión segura entre cliente y servidor. Esto es posible gracias a los sistemas criptográficos explicados: Cifrados Asimétricos, Simétricos y Hash. De forma generalizada casi nadie usa el término TLS, e indistintamente se hace eco de SSL para especificar tanto SSL como TLS. No obstante, SSL es un protocolo antiguo y que ha demostrado tener algunos fallos de seguridad, el cual fue sustituido por TLS. Aunque TLS no es compatible con SSL, TLS si tiene incluía una funcionalidad de poder usar SSL en caso de que la conexión TLS no sea posible por la razón que sea. Por ello apartir de ahora y para evitar palabrería, usaré TLS en todo momento. Actualmente SSL3 se considera seguro, aunque es mejor usar TLS 1.0/1.2 en la medida que sea posible.

TLS es usado en un sin fin de aplicaciones diferentes. Por ejemplo es usado para autentificar y/o cifrar contenido de cualquier web por medio de HTTPS, pero también es usado para asegurar (encriptar y autentificar) las conexiones de correo electrónico (que no es lo mismo que decir que se envía un correo cifrado, lo que se cifra es todo el contenido de la sesión, aunque incluya el propio correo, es muy diferente). Sea como sea, su función principal es garantizar una conexión segura entre dos puntos de la red cualquiera, sin preocuparse de que cualquier posible atacante pueda interceptar la comunicación o modificarla, cosa más que necesaria para transacciones bancarias, transmisión de datos personales, lectora de correo en redes no seguras…

TLS es un sistema híbrido, al igual que vimos con EFS. TLS se basa básicamente en encriptar el contenido de la conexión por medio de un cifrado simétrico a negociar, cuya key es transmitida desde el cliente al servidor encriptada gracias a la encriptación asimétrica. De este modo, de lograr interceptar o descifrar una comunicación, tan solo sería perjudicial para dicha conexión dado que cualquier otra conexión usaría una key diferente. Es decir, TLS se apoya en el uso de certificados digitales. Aunque esto es a groso modo el funcionamiento de TLS, cabe destacar que una sesión TLS tiene dos modos de funcionamiento. El primero y más extendido, tan solo se requiere la autentificación del servidor frente al cliente. En el segundo esquema, tanto el servidor como el cliente se deben de autentificar mutuamente. Vamos a ver los pasos que se realizan en una conexión TLS:

  1. El cliente solicita una conexión segura, y envía al servidor una lista de los cifrados y hash que el navegador soporta, así como un número aleatorio y la versión del protocolo que desea usar.
  2. El servidor responde con la versión de protocolo que se usará en relación con la recibida por el cliente, así como el método de cifrado y hash que se usará. Evidentemente el servidor seleccionará el cifrado, hash y versión de protocolo mayor que soporten ambos.
  3. El servidor envía a continuación su certificado al cliente. El cliente comprobará la validez del certificado, comprobando su firma y el CA correspondiente.
  4. El servidor solicita al cliente que envíe su certificado.
  5. El servidor indica que ha finalizado por su parte toda la negociación.
  6. El cliente envía su certificado al servidor, y este lo verificará comprobando su firma y el CA correspondiente.
  7. El cliente envía al servidor una prekey cifrada con la clave publica del servidor.
  8. El cliente firma (hash y encriptar con su clave privada) los mensajes de negociación previos. El servidor verificará esto con la clave pública del cliente.
  9. El cliente y el servidor generan la Key para el cifrado simétrico que van a usar gracias al número aleatorio generado al comienzo y a la prekey
  10. El cliente envía un mensaje de finalización cifrado conteniendo el hash de los mensajes de la negociación y otros datos.
  11. El servidor descifrará el mensaje y validará los hash
  12. El servidor enviará u mensaje de finalización cifrado conteniendo el hash de los mensajes de negociación y otros datos.
  13. El cliente descifrará el mensaje y los validará.

Lo que está en otro color es tan solo válido para aquellos sistemas en los que es indispensable la autentificación del cliente de cara al servidor. En el paso 8, el servidor garantizará que el certificado que ha recibido corresponde al cliente con el que está negociando la conexión segura. Si la clave pública obtenida del certificado del cliente puede descifrar la firma realizada por el cliente, autentifica al cliente como válido.

Si en cualquier paso una verificación es fallida, un hash no corresponde al que debería de corresponder o cualquier otra circunstancia, se supone que no se ha podido establecer una conexión segura y se aborta la negociación. En cambio, si se llega al paso número 13, a partir de ese momento toda la comunicación realizada entre cliente-servidor será una conexión autentificada y segura. Incluso los pasos del 10 al 13 son pasos de la negociación ya cifrados mediante cifrado simétrico. Aquí el uso que se le da al cifrado asimétrico es relativamente pequeño, tan solo es usado en la propia negociación.

Gracias a un Sniffer es posible verificar que este es efectivamente el esquema de uso de TLS:

En dicha imagen podemos ver los pasos que se han ido realizando. En este caso es una comunicación desde un cliente de mi red (192.168.2.2) a gmail (209.85.227.83). Asi, mi paso número 1 corresponde al paquete número 4 de la imagen: “Client Hello”. El paso número 2 al paquete 6 “Server Hello”. El paso número 3 y el número 5 son realizados en el paquete 7 con “Ciertificate” y “Server Hello Done”. En este caso no hay autentificación por parte del cliente. El paso número 7, 9 y 10 son realizados en el paquete número 9 con “Client Key Exchange”, “Change Cipher Spec” y Encrypted Handshake Message”, y los pasos 11, 12 y 13 en el paquete número 10 “Encrypted Handshake Message”, “Change Cipher Spec” y “Encrypted Handshake Message”. En sucesivos paquetes, todo el tráfico irá cifrado.

Si pasásemos a analizar cada uno de esos paquetes, podríamos ver con mucho más detalle cada paso realizado. Por ejemplo, el mensaje “Client Hello” en el cual el cliente especifica los cifrados disponibles y soportados por el navegador, así como el número aleatorio:

Como podemos ver prácticamente todos los algoritmos que han aparecido los hemos tratado. Dentro del cifrado asimétrico es usado RSA y EC (Curva Eclíptica). EC aquí se aplica a diferentes sistemas, por ejemplo ECDHE (Diffie-Hellman Exchange es un sistema de intercambio de claves para realizar un cifrado simétrico). Dentro de los cifrados simétricos podemos ver AES-128, AES-256, RC4-128, Tiple DES , Camella y SEED (estos dos últimos no se han visto). Para acabar, dentro de los Hash tenemos SHA y MD5. DSA por otro lado es un algoritmo de firma digital. Hay que tener en cuenta que TLS puede ser usado en un sin fin de aplicaciones diferentes, con lo que es normal ver en la lista de algoritmos soportados algunos que podrían no tener mucho sentido a priori en ellos

Y por parte del servidor podríamos ver igualmente tanto el certificado enviado como los ajustes seleccionados. El certificado no sería más que el certificado, la respuesta en este caso de Gmail ante nuestra petición sería:

Es decir, ante todas las sugerencias del cliente, el servidor opta por seleccionar el protocolo TLS 1.0 (dado que es el máximo que soporta el navegador) y responde que usará el conjunto de cifrado RSA para el cifrado asimétrico, AES-256 para el cifrado simétrico en modo CBC y los Hash serán SHA. Como hemos dicho, TLS es una negociación. Significa que estos datos dependerán del equipo del cliente y del equipo del servido. Posiblemente si realizamos una conexión a Gmail dede IE, la lista de cifrados sea diferente, quizás aparezca alguno más quizás alguno menos. TLS no deja de ser a fin de cuentas un estándar, si se requiere que un navegador fuese 100% compatible debería de ser compatible con el 100% de los cifrados y sistemas propuestos en el estándar, pero esto es la teoría, no la práctica. De todos modos la práctica dice que los servidores TLS más seguros usan por regla general RSA+AES-256+SHA, mientras que los más inseguros pueden usar aun DES o Triple DES como cifrado simétrico y MD4 o MD2 para el hash. Lo más normal es encontrar RSA como cifrado asimétrico y RC4 o AES como cifrado simétrico.

Vamos a comparar la petición realizada anteriormente con Firefox a Gmail con la que expondremos a continuación entre IE y Live:

En este caso de los 36 sistemas de cifrado soportado por Firefox, tan solo son 12 los soportados por IE. Y la respuesta de Live frente a esto:

Es decir, el servidor de Microsoft Live seleccioan como su mejor opción el uso de RSA con RC4-128 y MD5. Es decir, el sistema usado en TLS por parte de los servidores de MS para Live es mucho más inseguro. A fin de cuentas RC4 a resultado ser relativamente vulnerable, y MD5 es también más inseguro que SHA. Esto no quiere decir que no sea un sistema seguro, pero sí que es mucho menos seguro de la seguridad que puede ofrecernos Gmail.

TLS es un protocolo muy seguro. Normalmente no es posible comprometer este tipo de sistema, y cuando se ataca no se ataca normalmente a intentar descifrar las claves, sino algún fallo del propio protocolo. Hoy por hoy la mayoría de todas las comunicaciones sensibles hacen uso de una manera u otra de TLS. Se usa para cifrar el contenido en la web por medio de HTTPS, el correo por medio de SMTPS, túneles VPN…

Podríamos incluir aquí STARTTLS. En realidad STARTTLS es un protocolo que se ve en “Email Spoofing”. SSL/TLS usan puertos específicos en los servidores. Por ejemplo por regla general, las peticiones HTTP se realizan al puerto 80 de los servidores, mientras que las peticiones HTTPS (usando TLS) al puerto 443. En el correo pasa algo similar. Para el correo SMTP se suele mapear al puerto 25, y 995 para TLS. STARTTLS se propuso para poder realizar la conexión por el mismo puerto no seguro (25), y una vez realizada la conexión al servidor se realizaría el “cambio” a usar TLS. Cuando se usa TLS toda la comunicación íntegra es cifrada, con STARTTLS tan solo cuando se llama a este protocolo, siendo posible la conexión e incluso su uso de servidores de correo que usan STARTTLS, si no están configurados para requerir después del mensaje de “HELO” el cmando STARTTLS.

Desde mi punto de vista, todo contenido que pudiese ser de carácter personal debería de ir bajo conexiones seguras. Por desgracia muchos administradores no comportan esta filosofía, y tan solo se preocupan en todo caso de cifrar por medio de TLS las credenciales de acceso de un lugar, dejando desencriptado todo el contenido al que se está accediendo.

Esto lo veremos cuando tratemos el fascinante mundo del Sniffing en otros temas, no será tratado en Encriptación y Autentificación. Lo que si debe de quedar claro es que no por usar un sistema como TLS podemos asegurarnos de que todo está protegido, nada más lejos. Y esto es muy muy importante.

Que los certificados deban de estar firmados por autoridades CA reconocidas, no implica que estos no puedan ser usados en otro tipo de entornos en los que la firma de un CA “famoso” no es necesaria. Seamos francos, los certificados digitales suelen costar dinero, debes de acudir a un CA para que certifique tu identidad y te lo extienda. ¿Pero sería esto necesario para asegurar las comunicaciones dentro de una empresa? La respuesta es no. Un CA es necesario para dar validez a un certificado de manera global, pero cualquier usuario puede en cualquier momento crear un certificado de la clase que sea (Servidor SSL, Cliente SSL, Firma…) para el fin que necesite. Es evidente que si este certificado es expuesto al exterior y un tercero tiene que hacer uso de él, posiblemente su navegador le advierta del peligro que ello entraña, dado que casi con toda seguridad el navegador del usuario no pueda verificar la firma del CA, dado que el CA posiblemente no esté reconocido por su navegador como un CA válido. Es decir, lo que realmente dicta si un certificado es de confianza o no es a fin de cuentas la firma del CA. Si el navegador o el sistema tiene el certificado del CA reconocido como confiable, el certificado será igualmente confiable.

Esto implica que una empresa puede crear un certificado CA propio, y a partir de este crear los certificados que necesite para los propósitos que sean: Servidores Web, Certificados para los trabajadores para que puedan firmar o cifrar el correo, Certificados para el acceso a los equipos informáticos, Certificados para las Smart Card para el control de acceso a las instalaciones, Certificados para el cifrado de los datos de los equipos, Certificados para asegurar las conexiones VPN… Y todos ellos estarían firmados por el certificado raiz de la propia empresa. Si dichos certificados se usan fuera de la empresa, simplemente los sistemas exteriores o los navegadores, gestores de correos… no podrían simplemente poder validad el CA. Pero para la propia empresa, esto no sería jamás un problema, dado que sus sistemas tendría reconocido el certificado CA de esta como legítimo.

La creación de certificados para uso personal es realmente útil. Dado que pueden ser usados en un sin fin de utilidades, cuando queremos usarlos nosotros para nosotros no nos preocupa lo demás, no deseamos interaccionar con un tercero, simplemente asegurar nuestros sistemas. Esto es usado muchísimo, incluso en servidores Web particulares en los que no se desea comprar un certificado, dado que los precios pueden ser relativamente altos para un particular. ¿El problema? Como se ha dicho, los navegadores, gestores de correos y otros suelen verificarlos, y como se ha dicho, si el CA no lo tienen como un CA válido, aparecerá una pantalla de advertencia. Hay que tener en cuenta que estas pantallas de advertencias de seguridad de certificado no válido son para tomarse muy en serio, aceptar un certificado no válido maligno supondría que un tercero podría estar comprometiendo toda nuestra comunicación. Un ejemplo de advertencia de seguridad de certificado en Firefox sería tal que así:

Por alguna razón, Firefox nos advierte de que la página a la que se está accediendo tiene un error con el certificado. Si expandimos “Technical Details” nos reporta el por qué el acceso a dicha web ha sido bloqueado, en este caso porque el certificado está firmado por el mismo (luego no se puede verificar el CA) y porque el certificado pertenece en teoría a otra web, no al host 192.168.2.1. Aun así, si deseamos acceder de todos modos a dicha web, tan solo tendríamos que añadir una excepción, desplegando “I Understand The Risks” y añadiendo la excepción:

Esto permite almacenar en nuestro equipo certificados específicos de terceros, marcándolos como seguros. Muchas veces la otra opción es simplemente añadiendo a nuestra base de datos el certificado del CA, configurándolo para que pueda verificar cualquier certificado que hagamos uso que esté firmado por dicho CA. De lo contrario, lo normal es que las comunicaciones sean abortadas si se detecta que el certificado no es válido para nuestro sistema.

La mejor forma de crear certificados es posiblemente gracias a OpenSSL, aunque es una herramienta creada para ser usada por linea de comandos. Tiene la ventaja no obstante de ser altamente configurable. Para los que deseen no obstante realizar la creación en un entorno de escritorio, la mejor apuesta posiblemente sea usar IIS, el servidor web de Windows que es incluido en la mayoría de todas las versiones de Windows, aunque no instalado por defecto. A través de él es fácil y cómodo la creación e instalación de certificados.

 

PGP/GPG

PGP (Pretty Good Privacy) es un programa/sistema de clave pública usando el esquemas PKI que vimos en su momento. De echo el repositorio que se vio formaba parte de PGP/GPG. Por ello no hay mucho que decir a cuanto funcionamiento se refiere. Si bien hemos visto una aplicación directa de los Certificados digitales para SSL/TLS, con PGP/GPG vamos a hacer lo mismo. GPG en contra partida (Gnu Privacy Guard) es una alternativa libre a PGP. Tanto PGP como GPG cumplen con el estándar OpenPGP, lo cual hace a ambos interoperables mutuamente.

¿Pero que sentido tiene PGP/GPG cuando el mundo está rodeado cada vez más de los certificados digitales administrados por las grandes empresas? El espíritu y la filosofía son muy diferentes. Es cierto que la utilidad podría ser exactamente la misma, pero no hay que olvidar que los certificados digitales tal y como los concebimos ahora mismo están muy comercializados, es decir, no deja de se un negocio. Es cierto que cualquier usuario de forma particular puede crear un certificado digital para encriptar una comunicación o simplemente sus datos, pero de nuevo olvidamos que OpenPGP se crea en base a la comunidad Online, sin agencias, sin comercio, sin… con completa libertad de uso, donde la legitimidad de una clave pública radica en la confianza que depositan otros en ella.

En este apartado no se usará en ningún momento PGP, siempre gnuPGP. Aun tratándose de una aplicación de línea de comandos, es bastante descriptiva. Vamos a ver a groso modo como funciona y algununos ejercicios práctico de ello, presuponemos que GPG ya se encuentra instalado en el sistema.

 

-Creación de Keys

Es evidente que uno de los primeros pasos es crear las keys que se van a necesitar, aunque esto no es necesario si lo que deseamos es usar gpg para realizar un cifrado simétrico, lo cual también es completamente posible. La creación de Keys es un proceso simple y guiado, en rojo los comentarios

C:\Users\Theliel\Desktop>gpg –gen-key

Por favor seleccione tipo de clave deseado:
Se deben de generar dos par, uno para firmar y otro para cifrar

(1) RSA and RSA (default)
(2) DSA and Elgamal
(3) DSA (sólo firmar)
(4) RSA (sólo firmar)
Su elección: 1
En mi caso se opta por la opción 1, RSA para firmar y RSA para cifrar
las claves RSA pueden tener entre 1024 y 4096 bits de longitud.
¿De qué tamaño quiere la clave? (2048)
El tamaño de la clave, por defecto 2048 bits

El tamaño requerido es de 2048 bits
Por favor, especifique el período de validez de la clave.
0 = la clave nunca caduca
<n> = la clave caduca en n días
<n>w = la clave caduca en n semanas
<n>m = la clave caduca en n meses
<n>y = la clave caduca en n años
¿Validez de la clave (0)? 0
La clave nunca caduca
¿Es correcto? (s/n) s
Es necesario establecer una caducidad, en este caso nunca caduca

Necesita un identificador de usuario para identificar su clave. El programa
construye el identificador a partir del Nombre Real, Comentario y Dirección
de Correo Electrónico de esta forma:
“Heinrich Heine (Der Dichter) <heinrichh@duesseldorf.de>”
Nuestros datos
Nombre y apellidos: Alma Oscura
Dirección de correo electrónico: theliel@almaoscura.com
Importante si deseamos posteriormente cifrar/firmar correo
Comentario: lección de gpg
Está usando el juego de caracteres `CP850′.
Ha seleccionado este ID de usuario:
“Alma Oscura (lección de gpg) <theliel@almaoscura.com>”

¿Cambia (N)ombre, (C)omentario, (D)irección o (V)ale/(S)alir? V
Necesita una frase contraseña para proteger su clave secreta.
Aquí nos solicitara la contraseña de paso para proteger la clave privada

Es necesario generar muchos bytes aleatorios. Es una buena idea realizar
alguna otra tarea (trabajar en otra ventana/consola, mover el ratón, usar
la red y los discos) durante la generación de números primos. Esto da al
generador de números aleatorios mayor oportunidad de recoger suficiente
entropía.
La entropía garantiza una buena clave generada aleatoriamente
………………+++++
…+++++++++++++++

gpg: clave F86191C9 marcada como de confianza absoluta
claves pública y secreta creadas y firmadas.
Creación completada de los dos pares de Keys
gpg: comprobando base de datos de confianza
gpg: 3 dudosa(s) necesarias, 1 completa(s) necesarias,
modelo de confianza PGP
gpg: nivel: 0 validez: 2 firmada: 0 confianza: 0-, 0q, 0n, 0m, 0f, 2u
gpg: siguiente comprobación de base de datos de confianza el: 2011-02-10
pub 2048R/F86191C9 2010-03-01
Huella de clave = 281E 9FBD AE6A 57FF EC65 D77F 57B5 75E8 F861 91C9
uid Alma Oscura (lección de gpg) <theliel@almaoscura.com>
sub 2048R/342B5359 2010-03-01

Nuestro par de claves queda completamente creado. La clave pública queda especificada con el ID F86191C9, mientras que la clave pública para firmar 342B5359. Una vez se ha completado el pequeño asistente, ya dispondremos de todo lo que necesitamos para realizar la tarea que deseemos. Por defecto, las claves creadas son firmadas por nosotros mismos, esto le da a las claves validez completa para nosotros mismos, así como cualquier clave que firmemos.

Después de la creación de las claves, lo normal es crear un certificado de revocación. Un certificado de revocación lo que nos permite es revocar nuestras clave completamente en caso de que esta haya sido perdida, comprometida… y lo que hace es marcar nuestras claves como no válidas. Dado que se requiere de nuestra propia clave privada para ello, lo normal es crearlo después de crear nuestras claves, y mantenerlo en lugar seguro. Cualquiera con nuestro certificado de revocación podría marcar nuestra clave pública como revocada:

C:\Users\Theliel\Desktop>gpg –gen-revoke -o revocar.txt almaos

sec 2048R/F86191C9 2010-03-01 Alma Oscura (lección de gpg) <theliel@almaoscura.com>

¿Crear un certificado de revocación para esta clave? (s/N) s
Por favor elija una razón para la revocación:
0 = No se dio ninguna razón
1 = La clave ha sido comprometida
2 = La clave ha sido reemplazada.
3 = La clave ya no está en uso
Q = Cancelar
(Probablemente quería seleccionar 1 aquí)
¿Su decisión? 0
Introduzca una descripción opcional; acábela con una línea vacía:
>
Razón para la revocación: No se dio ninguna razón
(No se dió descripción)
¿Es correcto? (s/N) s

Necesita una frase contraseña para desbloquear la clave secreta
del usuario: “Alma Oscura (lección de gpg) <theliel@almaoscura.com>”
clave RSA de 2048 bits, ID F86191C9, creada el 2010-03-01

se fuerza salida con armadura ASCII.
Certificado de revocación creado.

“Armadura ASCII” es el término que llama GPG para formatear los datos en BASE64, que como ya dijimos su principal uso es poder interpretar en texto plato archivos binarios. Así pues, si abrimos el archivo de texto revocar.txt, lo que veremos será algo así:

—–BEGIN PGP PUBLIC KEY BLOCK—–
Version: GnuPG v1.4.10 (MingW32)
Comment: A revocation certificate should follow

iQEfBCABAgAJBQJLjPn+Ah0AAAoJEFe1dej4YZHJKC0IAKurWg5Ft9ubYrxyASyL
ISEy5hSfVjslpVnT9qjwnMYPHYwCv7YbpHki6hGYowH3lFoYMaFl4QmrmqoIsiuV
OkrqekCPuGGt/kZCzkOh96lYYp8KWGfxBbjQyU17/yt9qLPlM0vEYNv6QHGKi/5K
flkPE0Y57rtC+Kz6WeCF6e8ao7yqfKJNkbvPLtpYTUzcrFzRiraBwNaIBuyRMod/
fmemqN+QkYf7PgVec0qLe8o5E+OBsHhFnwbYf0jQDmj2ehGpTlwLi2H02Ppfu1Wq
w6/DO33haTvFgXw1UwO4sgWACvO9bhGy711CJBFo4zto6jwHLxf/CIDNOJPTuY0S
Fcc=
=2B98
—–END PGP PUBLIC KEY BLOCK—–

Evidentemente esta clave ha sido creada tan solo para estos fines, luego no me importa publicar el certificado de revocación. Con él, cualquier persona podría revocar dicha key.


-Edición de Keys

Otra acción común es la edición de Keys. Esto tiene como objetivo por ejemplo añadir una identidad nueva a nuestras claves, modificar la expiración, modificar la contraseña de paso… es decir administrar nuestras keys. Para ello tan solo se requierer el comando “gpg –edit-key [CLAVE]” donde “clave” es cualquier identificativo de la Key que deseamos modificar. Por ejemplo podríamos poner el ID de nuestra clave, el correo electrónico, el nomre o apelllidos… cualquier dato es suficiente:

C:\Users\Theliel\Desktop>gpg –edit-key almaos
“almaos” es reconocido por almaoscura.com, que es una key presente

Clave secreta disponible.
especifica que la key a editar disponemos la clave privada

pub 2048R/F86191C9 creado: 2010-03-01 caduca: nunca uso: SC
confianza: absoluta validez: absoluta
sub 2048R/342B5359 creado: 2010-03-01 caduca: nunca uso: E
[ absoluta ] (1). Alma Oscura (lección de gpg) <theliel@almaoscura.com>

Orden> showpref
showpref muestra el orden de preferencias de los algoritmos criptográficos
para simétrico se usará AES256, para Hash SHA256, para compresión ZLIB

[ absoluta ] (1). Alma Oscura (lección de gpg) <theliel@almaoscura.com>
Cifrado: AES256, AES192, AES, CAST5, 3DES, IDEA
Resumen: SHA256, SHA1, SHA384, SHA512, SHA224
Compresión: ZLIB, BZIP2, ZIP, Sin comprimir
Características: MDC, Sevidor de claves no-modificar

Orden>

Con “help” tendremos una lista extensa de todas las posibilidades. Lo más común es la gestión de los identificadores, cambio de contraseña de paso..

 

-Encriptación/Desencriptación:

Como herramientas criptográficas, gpg puede usarse perfectamente para cifrar cualquier archivo o contenido con cifrado simétrico o asimétrico. Hacerlo es simple:

Cifrado simétrico usando AES256: “gpg -c –cipher-alg AES256 -o test_cifrado.txt test.txt”
-c especifica cifrado simétrico, –cipher-alg el algoritmo de cifrado simétrico, -o el archivo de salida, “test.txt” el archivo origen. Nos solicitará una contraseña y nada más

Cifrado asimétrico usando la key pública de AlmaOscura: “gpg -er almaosc –armor -o test_cifrado_a.txt test.txt”
-er especifica encriptación para un destino concreto (con lo que tenemos que tener su clave pública), -armor fuerza la salida en BASE64

Descifrar cualquier contenido: “gpg -d -o test_d test_cifrado.txt”
automáticamente la pantalla nos dirá como se ha cifrado. Si es cifrado simétrico necesitamos la clave, si es asimetrico tener la clave privada y la contraseña de paso:

C:\Users\Theliel\Desktop>gpg -d -o test_d test_cifrado_a.txt

Necesita una frase contraseña para desbloquear la clave secreta
del usuario: “Alma Oscura (lección de gpg) <theliel@almaoscura.com>”
clave RSA de 2048 bits, ID 342B5359, creada el 2010-03-01(ID de clave primaria F86191C9)

gpg: cifrado con clave $s de $u bits, ID $s, creada el $s
“Alma Oscura (lección de gpg) <theliel@almaoscura.com>”

C:\Users\Theliel\Desktop>

 

-Envío o recepción de Keys a un repositorio

Para acabar, otra función igualmente importante es poder exportar nuestras claves públicas para que todos puedan tener acceso a ellas. Una vez realizado, nuestras keys serán enviadas a uns ervidor público, y de este a otras réplicas a lo largo de todo el mundo, para aque así pueda cualquier persona del mundo poder enviarnos un mensaje cifrado o firmado hacia nosotros:

gpg –keyserver gpg.mit.edu –send-key theliel@almaoscura.com

Del mismo modo, si se especifica –recv-key en vez de enviar al servidor la key especificada, se obtiene de él la clave pública especificada, necesaria si deseamos cifrar un mensaje para dicha persona o enviar un correo seguro o…

Aunque existen muchas más posibilidades para GPG, enumerarlas una tras otra todas las opciones sería realmente poco práctico, dado que para ello está el manual de usuario de GPG, y aquí no pretendemos crear un manual de uso de GPG, sino comprender como funciona GPG y como poderlo usar, sobre todo en el siguiente punto, “Correo electrónico”

 

Correo Electrónico

Si TLS/SSL es la aplicación práctica predominante al uso de certificados digitales o firmas, el correo electrónico sería la segunda aplicación práctica más usada. La idea de cifrar y/o firmar el correo es lo más lógico. En todo momento hemos estado hablando de A envía un mensaje a B. En realidad el correo electrónico es esto a groso modo. Luego no es extraño que existan funciones más que extendidas para poder realizar este tipo de prácticas. Cuando hablamos de TLS/SSL dijimos que muchos proveedores de correo electrónico usan estos protocolos para evitar que un tercero pueda leer el correo. Esto es cierto, pero esto no significa que el correo en sí esté cifrado. Por ejemplo, si envío un correo sin cifrar por medio de gmail que usa para SMTP TLS, el correo se envía de forma cifrada desde el origen (mi ordenador) hasta el destino (el servidor de Gmail). Cualquier usuario que acceda al correo podrá leerlo. SSL/TLS no garantiza de modo alguno que el mensaje sea leído únicamente por el destinatario concreto, simplemente que el envío (o recepción en caso de IMAP o POP) se realiza de forma encriptada.

A día de hoy existe un estándar mayoritario, soportado por prácticamente todos los gestores de correo electrónico llamado S/MIME. S/MIME nos permite poder cifrar o firmar mensajes de correo electrónico si disponemos de un certificado para ello. Recordemos que no todos los certificados valen para todo, tendremos que tener un certificado que nos permita firmar y/o cifrar correo. En el caso concreto del DNI-e, nos permite por ejemplo tan solo firmar, dado que nuestro DNI-e no se le asocia ningún correo electrónico. En caso de los certificados CERES si que se le añade la opción de firmar o cifrar.

Para poder firmar un correo no se requiere nada en realidad, tan solo disponer de un certificado que permita la firma de correo y la clave privada de él evidentemente. En cambio para poder cifrar un mensaje lo que se requiere es la clave pública del destinatario, con lo que se depende de que este tenga o no tenga un certificado y que sea válido. Es una pena no obstante que el DNI-e expedido en españa no tenga la opción a la hora de expedirlo de asociarlo a un correo electrónico. Supongo que es solo cuestión de tiempo que esto se permita.

Del mismo modo que podemos usar S/MIME para firmar o cifrar mensajes por medio de certificados, dependiendo de la versión que tengamos de GPG podremos hacer lo mismo o necesitaremos tener instalado en nuestro gestor de correo alguna aplicación (addon) para hacerlo, es el caso de EnigMail para Thunderbird. Su funcionalidad es prácticamente la misma a la de S/MIME, lo que sucede es que en este caso no se trabajará con certificados, sino con el administrador de claves de GPG.

Vamos a ver algunos ejemplos de cifrado y firma a través de S/MIMI y a través de EnigMail. No hay que decir que es posible tan solo firmar, firmar y encriptar o tan solo encriptar.

 

-S/MIME

Usando Thunderbird, es muy fácil configurarlo para que por defecto se firme todos los correos redactados por una cuenta concreta. Tan solo es necesario especificar el certificado que será usado por dicha cuenta:

Una vez se han especificado los certificados a usar, tan solo es necesario redactar el correo deseado y en S/MIME seleccionar firmar. El mensaje se enviará sin problema alguno. La firma no deja de ser un archivo adjunto. Dependiendo de como sea abierto el correo, este nos verificará o no la firma adjunta. Por ejemplo, si el correo se abre con gmail, este tan solo verá que existe un archivo adjunto, si se abre con Thunderbird, directamente intentará verificar la firma del origen, con lo que el equipo deberá de tener los certificados pertinentes. Si es un mensaje tan solo firmado, la extensión será P7S, y P7M si el mensaje está cifrado o cifrado y firmado, siendo el adjunto en este caso el cuerpo del mensaje o cualquier adjunto que también contenga.

Si vemos el mensaje desde el punto de vista de gmail, tendremos algo así:

En cambio, de cara a un gestor de correo, lo que tendríamos sería algo así (No es el mismo correo):

En este caso, se puede ver en la esquina superior izquierda dos iconos. El primero significa que existe una firma, pero no se ha podido verificar. El segundo que el mensaje está cifrado. En pantalla, el texto “probando probando” es mostrado automáticamente ya desencriptado. ¿Por qué existe un error en la firma en este caso? Porque fue firmado por un remitente (correo electrónico) que no coincide con el correo electrónico especificado en el mismo certificado. Esto sucede si por ejemplo firmamos un correo enviado por otra cuenta con el certificado que poseemos pero que en dicho certificado lo creamos para otro correo. En cambio, el cifrado es válido, dado que para cifrar tan solo se requiere el certificado, la clave pública del destinatario, claro que tan solo el destinatario, que posee la clave privada, puede desencriptarlo.

Las claves privadas de los certificados almacenados en el propio sistema no suelen estar protegidas por una clave de paso, en cambio los certificados almacenados en una Smart Card como el propio DNI-e suelen estar protegidos por un PIN que es necesario introducir correctamente para tener acceso a nuestra clave privada.

Debería ser posible desencriptar cualquier archivo p7m directamente con OpenSSL especificando la key:

“openssl smime -decrypt -in smime.p7m -recip my.pem”

Siendo my.pem el certificado con la clave privada exportado y smime.p7m el mensaje cifrado/firmado

 

-GPG

El procedimiento en realidad es exactamente igual que el visto para S/MIME. Lo primero es asociar nuestras claves a la cuenta que desamos, al igual que se hizo para asociar a una cuenta los certificados correspondientes:

Y la recepción o envío de este tipo de correos es exactamente igual que con un certificado. Al firmar el correo lo normal será introducir la clave de paso para desproteger la clave privada y con ella poder realizar la firma:

A diferencia de S/MIME, PGP/MIME no cifra los mensajes o los firma adjuntando al correo el mensaje cifrado, sino que directamente suele cifrar el mensaje. Si nuestro gestor de correos reconoce que está firmado y/o cifrado por OpenPGP, nos mostrará el mensaje o nos dará un error de apertura, no obstante si no reconoce el formato o es abierto desde cualquier gestor online, lo normal es encontrar como es ya costumbre el mensaje y/o contenido en BASE64. Para el mensaja enterior sería:

—–BEGIN PGP MESSAGE—–
Version: GnuPG v1.4.10 (MingW32)

hQIMA0n/

fXfs2GxwARAAyJCLgdeCtg8f53jwWPSc+MZuJ15Kw/9dUEacIP79+WZl
xY8YdFf6pgkwL1Xov9P1k9vlwMN7uwYLa/g5TjUxqatoURxO+tHO6kVzFIGWn9W8
1KB/dxJWib4u98ACV0CIVC0waYyhB2XiHmrZR/TZYqEvwHHJx1l4I6t2Z2QPaahm
vdiTxOUwDixQI26qoNoUYRUei6yovKiJbviV0Sr6oItjU5XVxOVcyrpcGwTuOT34
kWig+u+CFv5rC6my2BtX1C/Aq/LC0YvIjTBce8fFNL84B5V71dgEmJhCNXSlAm23
pJ8zfltVq+ZVXV2koCKLvEoPytpyy+u/RiIUS30J/hrW1OdAdX3RVDh54h/7ODZu
z2YFjxbWQdiTWsENgpVVZ4KiA6irSz6Hc+fpJZMlUCHDG6UgSkY4Qx53c0Aj7paz
dxE/aQbGxxuZkqsKFOo6UhNfhN9aj2a5+IN5uI3vcKWlwBGQ1iCXgn4CVN6vUf5S
Kd9NV2sutZTxgOhN58xekYSLY459RPuZSHCQz42TWuku9UVhTiclg98RzSti1auY
9v+NJZtgJn5Ug9odJv7yJ4Opa0kqpFH3bbgO2dloflgpZMDnSzvbouxxl79ecjV7
IoxL8Vml4+2W3WTWw81Qh4/p9ShFOXdUhsAQxd3Q+W4ub84yrVBdcPZZLQ/R/VPS
wQ4B3yCR6PyfWR8U3ovO6TUHvPXQQdO32EInaXu4HJJkNdGf4phTk3/r8ichctbN
t2/yM4GkaVLamxSAWe5gOXfc+OtWap8W/fIsqzChrKmiQwcvO7B4ZCeEZrJ3Fjnq
8Nfr97vFFjDCdGA0gjcUyZiLUrfoljEETTxGQ5/dWYXyw5lo/yhBH+CQaG+woSDl
7BNERdn8TtTxX3BUMx40eIJgbW/nkefj7+ZRiclJ1ecmpkWuNSjWcj7USEMB4yUI
ZjNeJH0hqsbCezyaYBfArtgZ2XAeW9juNOUcdt+dHkWVZtcb6BqgbABzZ1Y4oFXV
GOqZcp0tXPrDCUNuupEDiTdnJOQvF7gaOr5q7o2Brznmzs4inh6xvjEuhMoSjmui
yh41jAKMkpb2L3abUbaPgHWCMCWO0GjEtXkDlXVebT37X0W1cK9g4yQTT8Slkuop
UQmQFD+8CI35wXDQJqjZ9/Oj5x2iDYiL2czkOiYvOxbuB9+hoDFqMSYQeQkOFzLn
MkmDL7PBoN5zDLzlpJj1SbZxN7GmcLxO+RSmmCnHxZdHfzkeuP5VSUsNkHBJs7iH
P4ZK002DLRoJw0OygcTdWkfuq7dcUkT8JHbpUtDLV7A=
=wSZC
—–END PGP MESSAGE—–

En realidad, ese mismo “texto” podría ser procesado directamente por GPG por linea de comandos para desencriptar y verificar la firma. Si copiamos dicho texto a un documento txt por ejemplo y procesamos gpg de la siguiente forma:

C:\Users\Theliel\Desktop>gpg -d 1.txt

Necesita una frase contraseña para desbloquear la clave secreta
del usuario: “Pepito Grillo <theliel@almaoscura.com>”
clave RSA de 4096 bits, ID XXXXXXXX, creada el 2008-07-16(ID de clave primaria XXXXXXX)

gpg: cifrado con clave $s de $u bits, ID $s, creada el $s
“Pepito Grillo <theliel@almaoscura.com>”

Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable

prueba

gpg: Firmado el 03/02/10 15:10:00 usando clave RSA ID XXXXXXXX
gpg: Firma correcta de “Pepito Grillo <theliel@almaoscura.com>”
gpg: alias “Pepito Grillo <theliel@almaoscura.com>”

 

Y efectivamente, “Prueba” era el texto del mensaje. Del mismo modo, al desencriptar el mensaje, se puede verificar que este estaba también firmado, y que la firma es válida. Esto quiere decir que el uso de PGP/MIME en realidad no es más que una interfaz sencilla para poder encriptar y cifrar el contenido que sea necesario.

 

Gracias tanto a PGP/MIME o S/MIME es simple y eficaz poder firmar o enviar archivos cifrados. Aunque es cierto que no es una práctica muy común el hacerlo, sí que es una práctica completamente recomendada si se desea evitar el eMail Spoofing o ataques para interceptar el contenido de los correos. En el tema de Sniffing, veremos la importancia de esto, tanto de usar TLS/SSL como el cifrado o firma de mensajes. Lo que puede parecer desde un punto de vista doméstico algo sin importancia, si que la tiene si los usuarios supiesen en realidad los peligros que entraña Internet simplemente por el desconocimiento de las propias tecnologías.

 

Firmas

Para acabar con las aplicaciones prácticas (aunque no son ni mucho menos las únicas), vamos a hablar del firmado de aplicaciones. En realidad, no es más que una extensión a la firma que ya hemos visto en los correos electrónicos o las firmas usadas por GPG para archivos. Lo cierto es que cada vez más programas permiten la firma de los documentos. Con la llegada del DNI-e, del cual hablaremos un poco al final de este capítulo, muchos trámites burocráticos son posibles hacerlo simplemente con el DNI-e. Esto es debido a la posibilidad que tenemos de firmar documentos ya no solo con nuestra firma manuscrita, sino también a los certificados digitales de firma que nuestro DNI-e posee.

Con el tiempo, veremos cada vez más programas que permiten el firmado de documentos. El correo electrónico tan solo es una de esas aplicaciones, pero no la única. Vamos a ver por ejemplo lo sencillo que podría ser dar validez legal a un documento Word o PDF. Y digo validez legal porque si realizamos una firma con nuestro DNI-e, es igual como hemos dicho como si firmamos con nuestra firma manuscrita cualquier documento. Recordar el término de “No Repudio”.

Para documentos PDF tan solo se debe acudir a la función “Firmar” y selccionar el tipo de firma, si queremos que sea incrustrada o simplemente certificar el documento. En Office, esto se hace de forma análoga a través del menú: “Colocar Firma”. En un caso o en el otro, en el momento que se accede al formulario de firma se nos mostrará la lista de certificados disponibles para ello, si tenemos el DNI-E en su lector podremos acceder a nusetros certificados de él. En caso de ser un certificado instalado en el sistema podremos seleccionarlo igualmente:

En el desplegable tan solo tendremos que seleccionar el certificado que deseamos utilizar, en este caso he optado por el certificado de Firma de mi DNI-e. Por seguridad, el software del DNI-e pide una segunda confirmación cada vez que el certificado de firma va a utilizarse, especificando la peligrosidad de ello. Peligrosidad que es exactamente la misma que puede tener nuestra firma en un papel. Nadie firmaría un papel sin leerlo. Esto es exactamente igual. En Acrobat, al terminar el proceso se colocará de forma visible (o no) nuestra firma, exactamente igual que en Word o en la mayoría de los programas que permitan realizar firmas.

 

 

DNI Electrónico

Para acabar vamos a dedicarle algunas palabras al DNI-e, expedido aquí en esta España nuestra, que empezó hace ya unos años a imponerse. Se ha hablado mucho del DNI-e y de todas las supuestas maravillas que es posible hacer con él. Del mismo modo no han sido pocos los que lo han criticado. ¿Qué hay de verdad en todo ello?

El DNI-e es una iniciativa pionera y hay que verla como tal. Ello implica que no podemos esperar que todas las maravillas que promete puedan ser visibles en el poco tiempo que lleva en funcionamiento. Si bien es cierto que el sistema de funcionamiento del DNI-e no es más que un par de certificados para validar nuestra identidad, no es facil de un día a otro tener toda la infraestructura necesaria para que estos certificados sean realmente útiles de cara a la burocracia.

La idea principal del DNI-e es sin duda el poder realizar cualquier trámite con la administración de forma remota. A fin de cuenta la necesidad de personalización física en una entidad o administración es para garantizar la identidad de dicha persona. En cambio, lo cierto es que para el 99% de todos los trámites no sería necesario movernos de la pantalla de nuestro ordenador si existiese una forma que garantice nuestra identidad. Y ese es el Alma del DNI-e. Es por ello por el que se incluyen dos certificados, uno para autentificación y otro para firma, que son los dos tipos de certificados que podríamos necesitar a la hora de hacer cualquier gestión a través de internet.

El problema es que las instituciones, administraciones y otros tienen que adaptarse a este nuevo modelo. A esto surge otro problema, que cada cual usa el sistema que más le place. Esto se refleja en problema con los navegadores a fin de cuentas. Todos estas gestiones son posibles gracias a conexiones TLS mutuamente autentificadas y, en caso de ser necesario, la firma de algún documento del que se requiera validez legal. Luego un peso importante recae en los navegadores, en los protocolos TLS/HTTPS… en como esas comunicaciones son realizadas. Al no existir un consenso de como realizar las comprobaciones, de si es mejor usar JAVA o si es mejor usar PHP, o si es mejor usar… provoca lo que son las mayores quejas de todo el sistema: “Me funciona con IE, pero no con Firefox” “Me funciona con Firefox, pero no con IE”, “A la tercera que intento funciona, pero las otras dos veces nada…”. Esto son errores comunes para cualquiera que haya intentado realizar trámites por el DNI-e.

No obstante, con el paso de los días, cada vez son más las instituciones que quedan recogidas para hacer uso del DNI-e. Es solo cuestión de tiempo que prácticamente todas las gestiones burocráticas sean posible realizarlas sin movernos del asiento, simplemente identificándonos ante la administración con nuestros certificados. Actualmente es posible realizar gestiones como el acceso a la banca electrónica, permiso por puntos, matrículas de la universidad, certificaciones estatales, becas, oposiciones, SAS, vida laboral…

 

El DNI-e no es más que una Smart Card de las que hemos estado hablando, una tarjeta de plástico con un microprocesador criptográfico, similar en parte a lo dijimos quera un módulo TPM. Dicho procesador criptográfico posee funciones para generar números aleatorios, generar claves RSA por sí mismo, generar Hash, almacenar certificados, realizar cifrado Triple DES… las especificaciones completas pueden encontrarse en la web del DNI-e, tan solo hay que conocer que dicho procesador criptográfico es un ST19wl34

Básicamente es una tarjeta de memoria que costa de tres zonas independientes: 6KB RAM, 224KB ROM, 34KB FLASH. Lo que sucede que cada una de dichas zonas de memoria está protegida por un Firewall interno con reglas de acceso a cada una de ellas, y además cada zona de memoria puede particionarse. Es decir, se pueden crear “reglas” en el firewall interno de modo que tan solo ante ciertas operaciones y ciertas validaciones, se permita el acceso a ciertas particiones de la zona de memoria que sea. De las tres zonas de memoria podemos inferior que en los 224KB destinados a la ROM se encuentra el “sistema operativo” del DNIe, llamado amigablemente DNIe v1.1. En los 34KB de la memoria flash se encontrarían los datos de nuestra propia tarjeta, es decir nombre, apellidos, dni, certificados, claves… y evidentemente la memoria RAM para las operaciones en activa que pueda necesitar.

Evidentemente la memoria flash está particionada en diferentes regiones de seguridad. Tan solo podemos hacer una idea de como es ello en relación a los datos aportados por la propia administración:

ZONA PÚBLICA: Accesible en lectura sin restricciones, contenido:

  • Certificado CA intermedia emisora.
  • Claves Diffie-Hellman.
  • Certificado x509 de componente.

ZONA PRIVADA: Accesible en lectura por el ciudadano, mediante la utilización de la Clave Personal de Acceso o PIN, conteniendo:

    • Certificado de Firma (No Repudio).
    • Certificado de Autenticación (Digital Signature).

    ZONA DE SEGURIDAD: Accesible en lectura por el ciudadano, en los Puntos de Actualización del DNIe.

      • Datos de filiación del ciudadano (los mismos que están en el soporte físico).
      • Imagen de la fotografía.
      • Imagen de la firma manuscrita.

      DATOS CRIPTOGRÁFICOS: Claves de ciudadano

        • Clave RSA pública de autenticación (Digital Signature).
        • Clave RSA pública de no repudio(ContentCommitment).
        • Clave RSA privada de autenticación (Digital Signature).
        • Clave RSA privada de firma (ContentCommitment).
        • Patrón de impresión dactilar.
        • Clave Pública de root CA para certificados card-verificables.
        • Claves Diffie-Hellman.

        DATOS DE GESTIÓN:

          • Traza de fabricación.
          • Número de serie del soporte.

          De estos datos podemos imaginar que la flash está dividida en cuatro partes. Una de ella de acceso no restringido, donde se encontrarían el Certificado de la CA intermedia (no el certificado CA raiz), que sería en este caso “AC DNIE 003″, el certificado raiz CA recae sobre “AC RAIZ DNIE”. En la misma zona se encontrarían las claves DH. DH es un algoritmo usado para comenzar a intercambiar claves. Por último se encuentra el certificado x509 de componentes, que se refiere a algunos de nuestros datos, como lo es Nombre y apellidos, DNI o equipo de expedición.

          La segunda zona de la memoria es usada para almacenar los dos certificados que posee, el certificado de firma y el de autentificación, que aunque los dos pueden ser usados para firmar, tan solo el de firma tiene habilitada la función de “No repudio”, la cual ya hemos hablado de ella, lo cual hace que una firma digital con él tenga el mismo valor que un documento firmado manuscrito.

          En la zona de seguridad tan solo se encontrarían los datos expuestos, los datos de la persona física, imagen de la fotografía, la firma.

          Quedaría por pensar donde se encuentran alojados los datos criptográficos. Por su seguridad, podríamos pensar que se encontrarían en una zona especial del mismo procesador criptográfico, pero esto no es así. Luego podemos pensar que se encuentran en una zona de memoria Flash, la cual tiene unas reglas de acceso muy limitadas. Por ejemplo, una zona de memoria marcada tan solo para lectura interna. Es decir, los datos almacenados en ella tan solo pueden ser leído por el mismo OS de la propia Smart Card, sin que existe posiblidad de lectura desde el exterior. Si nos damos cuenta, las tres zonas de memoria anteriormente especificadas pueden ser extraídas o modificadas desde el exterior. En cambio, estas zonas de memoria no. Tan solo existirá seguramente un protocolo configurado en el propios OS del DNIe para generar, borrar, crear, eliminar nuevas claves, pero nunca para extraerlas.En esta zona especial se encontraría la información más sensible, comenzando por las claves privadas de los propios certificados.

          El resto del hardware del DNI-e son algunos módulos aceleradores para las operaciones criptográficas y una memoria ROM que incluyen librerías y software ya creado por ST para ser usado por el OS introducido en la ROM de usuario. Posee a parte algún generador de números aleatorios y el resto es prácticamente electrónica pura y dura.

          Visto así, es más fácil comprender que es en realidad el chip de nuestro DNIe, que no es algo tan raro o tan complicado de comprender. Por supuesto, esto tan solo es todo especulativo, dado que tan solo podemos imaginar en función de los datos que han sido publicados. Quizás sería posible desgranar un poco más el DNIe y ver realmente como está diseñado, los comandos APDU de acceso… pero requeriría paciencia y tiempo, y tampoco este capítulo trata sobre ello, tan solo un repaso general de lo que es el DNIe y de como funciona.

           

          Para terminar todo este capítulo, recordar que la tecnología está para usarse. Un sistema usado responsablemente y sabiendo de que se trata, otorga un índice de seguridad muy muy alto. No implica que tengamos que ser neuróticos en cuanto a seguridad se refiere, pero como veremos en otros temas como el Sniffing, Spoofing… nunca puedes fiarte de quien pueda estar al otro lado, y mucho menos de las intenciones que puede tener. A quien esto le parezca desmesurado, que se comience a preguntar por qué hay tantos problemas de seguridad a día de hoy.

          Seguridad: Encriptación y Autentificación. Capítulo Tercero -> Certificados y Firmas Digitales

          ATENCION: Los ejemplos que se van a mostrar y “tutoriales” tan solo tienen carácter educativo. En ningún aspecto comparto filosofías de invasión a la intimidad, ataques contra un sistema informático o cuestiones similares. En la medida que sea posible siempre se usarán ejemplos y formas que puedan ser usados por cualquier persona, de forma que pueda verificar los contenidos escritos. No obstante, por motivos más que obvios, materiales como contraseñas, nombres de usuarios o de hosts, serán omitidos o modificado en las capturas de pantallas realizadas (o las lineas escritas). Es decir, los ejemplos serán completamente reales, los datos mostrados a vosotros necesarios para poder pertrechar estos ejemplos no siempre lo serán (Sí lo serán los resultados). Para que esto conste de forma clara, todo material sensible modificado o falso estará resaltado en ROJO. Por motivos de seguridad, todo el material que sea expuesto aquí (exceptuando software propietario o libre, citaciones expresas o código de terceros) tanto texto, imágenes y código son propiedad del autor y está completamente prohibido su reproducción completa o parcial en otros lugares, espero que se comprenda.

           

          Certificados y Firmas Digitales

          El cifrado de datos es un mecanismo que garantiza que nuestros datos, aun cuando puedan ser interceptados por otros, permanecerán seguros. Por otro lado, los Hash nos dan un mecanismo para poder garantizar la integridad de un mensaje. Fue hace ya tiempo cuando se pensó en una aplicación práctica sencilla de estas dos tecnologías, y comenzó a hablar de Certificados digitales. Pronto fue igualmente necesario el concepto de firma digital, un sistema de autentificar algo.

          Una tecnología se crea fundamentalmente pensando en algo. Así, el fundamento del cifrado de datos es simple, que cuando un mensaje sea interceptado no pueda ser leído o comprendido por una tercera persona a la cual no está destinado. Pero esto no impide que el mensaje pueda ser modificado, deteriorado, falseado… Imaginar una carta postal que se escribe con “tinta invisible”. Alguien que la intercepte quizás no pueda leer el contenido real de esta, pero puede coger otra carta, rellenarla con la información que desee y enviarla de nuevo al destino de esta. La pregunta es ¿Como podrá el destino saber si dicha carta ha sido modificada? En el caso de la carta quizás con un sello, una firma… aquí el concepto será el mismo, y podríamos decir que el fundamento de un Hash criptográfico es precisamente la integridad.

          A raíz de la necesidad tanto de proteger el contenido de los datos en las comunicaciones, como de autentificar el emisor y el destino, como garantizar la integridad del mensaje, se creó el concepto de “Infraestructura de Clave Pública” (PKI). Este concepto no es más que la aplicación práctica en las comunicaciones de los conceptos que hemos visto anteriormente (y alguno más que veremos en este capítulo): Hash, Cifrado Simétrico y Cifrado Asimétrico.

          En este capítulo vamos a intentar comprender básicamente cada uno de los elementos que constituye una infraestructura de clave pública (PKI), y veremos como cada siguiente elemento se hace necesario para el correcto funcionamiento de todo el sistema:

          • Infraestructura básica
          • Certificado: Necesidad de asociación usuario/empresa – Claves
          • Firma: Necesidad de autentificación de todas las partes e integridad


          Infraestructura básica

          Vamos a intentar aplicar todos los conceptos explicados a un entorno real que deseamos que sea completamente seguro. Para hacer esto tenemos que tener una serie de consideraciones, tendremos que crear una infraestructura en la cual podamos aplicar y hacer viable nuestras necesidades. Hemos dicho que el objetivo será triple a la hora de desear crear un canal de comunicación seguro entre dos partes: El cifrado, la autentificación y la integridad. Empezemos por lo tanto por la primera de las partes, el cifrado.

          Lo primero que deseamos es que nuestros datos sean interceptados o no por una tercera persona, esta no pueda acceder a ellos. Hemos dicho que para ello disponemos de dos sistemas muy buenos, el cifrado simétrico y el cifrado asimétrico. Cada uno de ellos tiene ventajas e inconvenientes. ¿Cual es más factible de usar? En principio vamos a pensar que el cifrado asimétrico por una razón muy simple: Además de ser más seguro tan solo requiere de un par de claves (publica y privada) para el número que sea de canales de comunicación a entablar. Realizar esto por medio de un cifrado simétrico sería muy costodo en cuanto a infraestructura, dado que ¿Como crearías una base de datos en la cual se pudiese almacenar cada usuario un número sin fin de keys asociada cada una de ellas a un usuario o entidad diferente? Sería impensable. En cambio mediante el cifrado por clave pública esto podría simplificarse, dado que tan solo es necesario hacer pública una sola key para todos los canales de comunicación posibles, no una para cada canal. En realidad el sistema actual usado es híbrido, pero esto se verá más adelante, para nosotros simplemente decir que se opta de momento por el cifrado asimétrico, en nuestro caso RSA.

          Una vez definida la necesidad de un sistema de clave pública y las ventajas que esta nos aporta, aparece el primer problema: Distribución. Hemos explicado que el sistema de cifrado asimétrico es muy eficiente e increíblemente versátil, lo que encripta una key privada lo desencripta la pública, lo que encripta la pública lo desencripta la privada. De ahí la necesidad de que la clave pública sea exactamente eso: Pública. ¿Pero como podemos hacer que cualquier usuario del planeta pueda tener acceso a dicha Key? Aquí es donde comienza a crearse la verdadera PKI, de la necesidad de ir solventando los por menores del camino. La única forma de que cualquier usuario conozca nuestra key pública es disponer de bases de datos en las que se encuentren almacenadas las claves públicas de todos los usuarios. A esto se le conoce como repositorios de claves públicas. Ahora, cualquier usuario puede enviar su clave pública asociada a un correo electrónico, nombre, apellidos… Pero de forma pareja aparece la necesidad de algún control sobre dichas bases de datos. ¿Que sucede si una key ha sido comprometida o ya no es válida? Es necesario por tanto otro Repositorio , en este caso un Repositorio de Revocación de claves públicas. Con estos dos sistemas podríamos garantizar el funcionamiento correcto del cifrado de datos entre dos usuarios. Estos repositorios existen a día de hoy, la mayoría de ellos se encuentran sincronizados con los otros para que todos tengan los mismos datos. Por ejemplo podemos visitar uno de ellos:

          Repositorio de Claves Publicas del MIT

          En dicho repositorio podemos buscar cualquier cadena de texto, ya sea nombre, apellidos, correo electrónico o ID de la clave:

           

          Type bits/keyID     Date       User ID
          

          pub  4096R/B9A35B9C 2009-12-02 Carmen Mendes <cmendes@transnumeric.com>
          

          pub  2048R/F4D68EB5 2009-11-07 María del Carmen Rodríguez Sardiña <mariadelcarmen@gens-osorio.es>
          

          pub  1024D/9BC23DEF 2009-10-15 carmenalves (ola) <carmen.alves.05@formando.gti.pt>
          ...
          

          Por supuesto si continuamos el link de la KeyID nos topamos directamente con la clave pública de Carmen:

          -----BEGIN PGP PUBLIC KEY BLOCK-----
          Version: SKS 1.1.0
          
          mQENBEuGtJwBCAD0EM6+cVCIrc2t5CLWhrdwPrTbb4ZbTAKuLjAjULl3K+/usQg7JT0Y+qL6
          Z/eGB8krZgzzT77bQHKVAw7NeUZGSMDl+kSIT9k5gx/vWxdyuBUeJODkd7IldiGbW5yhGz92
          0LGbQ5weF2GT8DewCtawOsO46baygPIgiVR99vArzNyiX+KFnrUaniVbjbiN8KQY9Nvmdvyz
          BU77W5SDRc4LbuOv5GCtnPKjlVQE5JApoelpZi2fiJkH/kKcf4ZTc0nSK8e8duHYB+zrKrxO
          ICKHWXWgLBV9aZkoCH35oShK3JpSeimnV3yqwqz2zt32p/JNKO02krPNNIUL+AqVivEfABEB
          AAG0SmNhcm1lbiByZXF1ZWpvICh1biBhbWlnbyBtaW8gc2UgbXVyacOzIGNvbmdlbGFkbykg
          PGZvMjAxMGNhcm1lbkBnbWFpbC5jb20+iQE+BBMBAgAoBQJLhrScAhsjBQkJZgGABgsJCAcD
          AgYVCAIJCgsEFgIDAQIeAQIXgAAKCRBeKv2mzKxFxS0wCACcC6fWZ9IliyKHI8gZBEl3s9Sd
          WWlUJo/PNgbzEoq3N/aiy47+ITo/Qax9+PXYUUOH6Zx+CLb4NMyplSo3cESDlg4O/hzkypP6
          9Yj6JflHQcqmWfGsWwqf3kiGSWopd8osKdb5bpvKfXI+JKc8Gj5l64JUa0f6BIPIL3/9/Uci
          EhnEyHG0b2gJx/f3bybAG+mpBo3VnV/alTfZbX8qnen3Rqg1TPxEyfJjR6E4QrSkeHb8MJp9
          ZGO58IWvWAPADJJoK2alKJMRKjeZKFjqcolr4mgNhRhg3iD77SmL1hskwfCinPXGnmimV/Xl
          VH0qTX/4Jem6aTG+9aD8u8r3p4LyuQENBEuGtJwBCADALhMeR4PFXzKcxDUzn5yWbckFrz97
          ONCbL1C0G/4Wg8fV3t0Vchzg6aKsEYUZSfTe5Ph0rqLWs1cfjgMxrCRYTfzmCffIWBmXixu7
          iDuj6bRshY+9F03xFA0X/GJG1bZ/3JuIYTP804UU1/OsH+cFsyj1CnoUNz1zZ5rvm/76VqL1
          vBskTyD7cfEPrSTh5HfBu8EatdI0rCPezyzZeE0IhWYg7OChBK6FzkaIEZifpxI7/KSadPNw
          NLO0WdLmFhqLqS/Pwt4oCcMxljB9zoO/KGRyvw4nY6BilItFwaIfOjDbrVqDSnG9RZ8+Cevo
          TfPi1j1VsBpc113vMqs0g14hABEBAAGJASUEGAECAA8FAkuGtJwCGwwFCQlmAYAACgkQXir9
          psysRcVvjgf9F0o3Q3/MbLMriwe9naCXuy2xcceWyZ9vp6ZPm5zoD1Tt7aWRBeFUhk/T88sa
          SqcpVqZSNtsdjJl7oHXVcFKeccIebOs826GIMzWgT6kCl2r79RY4W7b0iaPzljH7ayX7Ce3Z
          UM7Z0JhCmjH6aszc/dXd3JkHR9cxiY9A1HWrgGzd2RlNCYOVB1kokteVE9+CXCyJwAelSCLR
          GAYl33oyxGDKxngVCdeBRxgCeTU0szL7NXMNi3Y2cQCHCiEwTspKXS+wOtos66vgYLYXdgJs
          KvW0gau6bUwBouD7aXZOkubfpZ3J85X6KcLuPAQfJlhtuufimJ3y7/+B09c0TD+Osw==
          =PqHr
          -----END PGP PUBLIC KEY BLOCK-----
          

          Ana desea enviar un mensaje cifrado a Carmen:

          a) Ana accede a un Repositorio de Claves pública para obtener la Clave pública de Carmen, para ello busca en la base de datos por “Carmen”. Es posible que haya más de una (puesto que alguna puede estar revocada)
          b) Ana con la clave en su poder verifica que esta key no se encuentre en la lista de Revocación. Dado que no está, considera que la key está en uso y es válida.
          c) Ana encripta el mensaje con la clave pública de Carmen y le envía el mensaje
          d) Carmen desencripta el mensaje con su clave privada.

          De este modo Ana puede enviar un mensaje cifrado a cualquier usuario del mundo que esté usando un sistema de clave publica, sin necesidad siquiera que el emisor use dicho sistema, y con la garantía de que dicho mensaje tan solo podrá ser desencriptado por el poseedor de la key privada pareja a la key pública del repositorio. Este sistema logra el objetivo del cifrado de datos. ¿Pero que sucede ahora con la autenficicación?

          En el ejemplo expuesto, Ana no puede asegurar de ninguna forma que la clave pública obtenida del repositorio accedido proceda de “Carmen”. Sí, es posible incluso que en dicho repositorio quedase indicado nombre, apellidos, dirección, DNI… pero dado que son repositorios a los que todos tienen acceso, cualquiera podría introducir datos falsos en ellos. Por ejemplo, podría crear una key publica/privada a nombre de otra persona, de esta forma cuando alguien quisiese enviarle a dicha persona un mensaje, lo encriptaría con mi pública. Aquí es donde nace la necesidad de autentificación, de algún sistema por el cual Ana pueda estar convencida que la clave pública obtenida pertenezca a Carmen. Para esto se opta por dos sistemas diferentes, aunque ambos se basan en la misma premisa: Cadena de confianza.

          Imaginar que de algún modo se pudiese dar un punto positivo a una clave pública, de forma que cuantos más puntos positivos tenga una Key pública de un repositorio indicase a terceras personas que dicha key es válida. Así por ejemplo yo podría dar un punto positivo a la clave púplica de mis hermanos, puesto se fehacientemente cual es la que pertenece a cada uno de ellos. De este modo, si una tercera persona desease enviarme un mensaje cifrado a mí, se fiaría en caso de duda más de aquella clave pública que tenga más puntos positivos de personas diferentes. Ahora imaginemos que Ana desea enviar un mensaje cifrado al mismísimo Linus Torvalds (El cual espero no le importe que use su nombre para estos ejemplos) para consultarle un bug crítico en el kernel de linux. Lo primero que haría sería acceder al repositorio y buscar por “Linus Torvalds”, dado que ni siquiera conoce su correo electrónico. El repositorio le devolvería lo siguiente:

          Type bits/keyID     Date       User ID
          

          pub  1024D/825D2E82 2008-09-03 Linus Torvalds (Teste) <linus@linux.org>
          

          pub  1024D/D080B7A0 2008-07-26 *** KEY REVOKED *** [not verified]
                                         Big Gay Al (kay) <letsseesomelove@love.com>
                                         REVOKED KEY (u suck) <FUNBO@T>
                                         Linus Torvalds (revoke revoke revoke) <werfsdfasdf@fakefakefake.com>
          

          pub  1024D/006D1B6D 2005-11-11 *** KEY REVOKED *** [not verified]
                                         Danilo G. Magrini <danilo.magrini@gmail.com>
                                         Danilo G. Magrini <danilomagrini@uol.com.br>
                                         Danilo G. Magrini <danilo@onclicksistemas.com.br>
                                         Danilo Gustavo Magrini (Linus Torvalds) <danilomagrini@uol.com.br>
          

          pub  1024D/8BC6EDEF 2005-11-10 Danilo Gustavo Magrini (Linus Torvalds) <magrini_sp@superig.com.br>
          

          pub  1024D/76E21CBB 2005-04-23 Linus Torvalds (tag signing key) <torvalds@osdl.org>
          

          pub  1024D/CE904A82 1999-11-21 Linus Torvalds <vnixroot@netscape.com>
          

          pub  1024D/449FA3AB 1999-10-05 Linus Torvalds <torvalds@transmeta.com>
          

          pub  1024R/A86B35C5 1996-06-08 Linus Torvalds <Linus.Torvalds@Helsinki.FI>
          

           

          Ana es una chica lista, pero según el repositorio existen 8 posibles claves públicas supuestamente todas correspondientes al bueno de Linus. Sin dificultad Ana descartaría de forma automática las que están marcadas como Revocadas, lo que deja el listado con 6. La primera se podría descartar dado que aunque el correo podría ser legítimo, pone (Test)… podemos imaginar que fue creados con fines de testeo, además, la fecha de la clave es relativamente nueva. La cuarta la excluimos porque el nombre ni siquiera pertenece al de Linus. De este modo tan solo nos quedarían como posibles las 4 últimas. la quinta no obstante puede leerse como (tag signing key) que podríamos suponer que se trata de una clave tan solo para firmas (esto se verás más adelante), así que de momento la descartamos también. Las otras tres restantes podría parecer legítimas a simple vista. Como Ana quiere asegurarse, quiere ver lo que hemos llamado como “votos positivos” de ellas. Si accedemos a la sexta obtenemos la siguiente información:

          pub  1024D/CE904A82 1999-11-21            
          
          uid Linus Torvalds <vnixroot@netscape.com>
          sig  sig   CE904A82 1999-11-21 __________ __________ [selfsig]
          sig  sig   8061A830 2005-05-30 __________ __________ Dan Mundy <harob02@earthlink.net>
          
          sub  2048g/1EEE5A92 1999-11-21
          sig sbind  CE904A82 1999-11-21 __________ __________ []
          

          Los votos positivos que hemos nombrado en realidad son firmas, dado que aun no hemos hablado de ellas tan solo imaginamos que son algo así como voto de confiabilidad. En este caso vemos que tan solo posee una firma creada por él mismo “selfsig” y otra firma (voto) creado por un tal Dan Mundy. Ana, que no es tonta, imagina que una persona como Linus, de tener una clave pública en estos repositorios tendrá seguro bastantes votos de confiabilidad. Luego la rechaza.

          Esto deja a Ana con dos opciones, las dos últimas. Ana conoce un poco la vida de Linus y le suena que trabajó o tubo relación con trasmeta.com, luego parece un buen punto de partida. No obstante sabe también que Linus es finlandés, nacido en Helsinki, lo que quiere decir que las dos claves que aparecen podrían ser completamente legítimas. Y en este caso las dos pertenecen a él. No obstante, si nos adentramos en la última de ellas, generada nada más y nada menos que en 1996!!, esto es lo que obtenemos:

          pub  1024R/A86B35C5 1996-06-08 __________ 
          
          uid Linus Torvalds <Linus.Torvalds@Helsinki.FI>
          sig  sig   A86B35C5 1996-06-08 __________ __________ [selfsig]
          sig  sig   2A960705 1997-04-24 __________ __________ H. Peter Anvin <hpa@zytor.com>
          sig  sig   29BC0185 1998-01-24 __________ __________ george a. r. hill <9x>
          sig  sig   0C00E6AD 1998-08-21 __________ __________ Alexander Smith <Sabin84@usa.net>
          sig  sig   CCBEA8D2 1998-09-02 __________ __________ Kenyon Ralph <kenyon@san.rr.com>
          sig  sig   ACF5A545 1998-12-17 __________ __________ H. Peter Anvin <hpa@zytor.com>
          sig  sig   A4679654 1999-01-30 __________ __________ Drizuid <drizuid@drizuid.net>
          sig  sig   F0C36E09 1999-01-30 __________ __________ Drizuid <dark-druid@geocities.com>
          sig  sig   29B0C351 1999-06-18 __________ __________ Jens S�lwald <j.suelwald@gmx.de>
          sig  sig   FEEFE90B 1999-09-15 __________ __________ []
          sig revok  FEEFE90B 1999-09-15 __________ __________ []
          sig  sig   6470AB26 2000-03-02 __________ __________ Cedric Blancher <cblancher@cmc.fr>
          sig  sig   A4C70528 2000-03-15 __________ __________ Alexander Smith <sentinel@freshshell.de>
          sig  sig   A24D8B4E 2000-08-10 __________ __________ C�dric Blancher <cblancher@startem.net>
          sig  sig   24901EE8 2001-05-31 __________ __________ Simon A Soanes <simon@nullifynetwork.com>
          sig  sig   9CD30D3D 2001-10-09 __________ __________ ZC Wong <zcwong@hotmail.com>
          sig  sig   01B45CE2 2001-10-09 __________ __________ ZC Wong <zcwong@hotmail.com>
          sig  sig   D925418D 2004-04-18 __________ __________ Kevin W. Peters (Guitarman) <guitarman@ntdf.com>
          sig  sig   6422D07C 2004-05-23 __________ __________ Fabian Foerster (Root CA) <fabian_foerster@web.de>
          sig  sig   0C877B34 2004-05-23 __________ __________ The Root Networks (Root CA) <root-networks@web.de>
          sig  sig   FA81F1E6 2004-06-14 __________ __________ Thomas Shea <lrmm@comcast.net>
          sig  sig   AAE6022E 2004-12-28 __________ __________ Karlheinz Geyer (RBOS) <karlheinz.geyer@lhsystems.com>
          sig  sig   4D34B354 2004-12-28 __________ __________ Karlheinz Geyer (DKB) <karlheinz.geyer@lhsystems.com>
          sig  sig   8061A830 2005-05-30 __________ __________ Dan Mundy <harob02@earthlink.net>
          sig  sig3  099A79AC 2005-07-12 __________ __________ Konstantin Vinakovsky <kvinakovsky@earthcam.com>
          sig revok  AAE6022E 2005-07-28 __________ __________ Karlheinz Geyer (RBOS) <karlheinz.geyer@lhsystems.com>
          sig revok  4D34B354 2005-07-28 __________ __________ Karlheinz Geyer (DKB) <karlheinz.geyer@lhsystems.com>
          sig  sig   6BEEAF8D 2008-08-02 __________ __________ Kristoffer Warming <heavyhenning@gmail.com>
          

           

          Ana comprende que efectivamente no solo ese puede ser un correo válido de Linus, sino que también lo es su clave pública. Puede comprobar que tiene una serie de firmas en su clave que de un modo reafirman que dicha clave pertenece a él. Se puede observar que 3 de las firmas (votos) están igualmente revocados, pero aun así parece claro que esta es una clave válida y legítima. La última forma pertenece a 2008, lo que nos puede hacer pensar que la cuenta está aun en activo.

          pub  1024D/76E21CBB 2005-04-23 Linus Torvalds (tag signing key) <torvalds@osdl.org>

          Pertenece también a él, es un correo que es más que conocido por programadores y otros que frecuentan listas de correos del kernel de linux, lo que sucede es que aparentemente por ese nombre podemos deducir que Linus la usa tan solo para firmar, y no para encriptar (esto se verá como he dicho más adelante)

          Llegados a este punto, Ana ha logrado dos objetivos. El primero cifrar los datos y el segundo asegurarse que dichos datos están cifrados efectivamente y tan solo para Linus Tolvards, gracias al anillo de confianza que generan estos votos (que no son sino firmas digitales). Pero aun le queda a Ana un problema. La integridad. Como puede estar Ana convencida que el mensaje que reciba Linus no haya sido modificado por un tercero. Ana desea que en el peor de los casos y que este haya sido modificado, Linus pueda conocer que este ha sido modificado, así pueda contactar de nuevo con Ana y solicitarle de nuevo el envío del mensaje legítimo.

          Después de un rato de meditación, Ana recuerda la funcionalidad del Hash criptográfico. Ana no podrá garantizar nunca que el mensaje llegue sin modificación alguna, pero puede garantizar que de ser modificado Linus se percatará de ello. ¿Como? Ana recuerda que si aplica por ejemplo un Hash SHA-1 al mensaje cifrado y envia tanto el hash como el mensaje cifrado, Linus podría verificar si el hash especificado por Ana y si coincide con el Hash real del mensaje. Una tercera persona sino, podría interceptar el mensaje, crear un mensaje nuevo, cifrarlo con la key Pública de Linus y enviárselo en nombre de Ana. No obstante, según este esquema una tercera persona podría igualmente interceptarlo, y como conoce el Hash que ha usado Ana, tan solo tendría que redactar el mensaje, encriptarlo, calcularle el nuevo Hash y enviar los datos a Linus. Es aquí donde aparece la necesidad de la firma digital.

          Ana ha comprendido las técnicas de los hackers que quieren modificar su mensaje cifrado (sin saber siquira que hay dentro de dicho mensaje) así que ha descubierto la solución definitiva. Ana, que también tiene usa sistemas de clave pública tiene su propia clave pública y privada:

          a) Ana redacta el mensaje y lo encripta usando la clave pública de Linus
          b) Ana calcula un Hash SHA-1 al mensaje encriptado y este mismo hash lo encripta con su clave privada (A esto se le llama firma digital)
          c) Ana envía tanto el mensaje cifrado como la firma a Linus.
          d) Linus accede al repositorio de claves públicas y busca la correspondiente a Ana y a dicha dirección de correo (del mismo modo que hizo Ana). Encuentra la que busca con muchos “votos” a su favor, y con la clave pública de Ana es capaz de desencriptar el hash de Ana. Linus calcula el Hash SHA-1 al mensaje cifrado y verifica que ambos valores coinciden!! Luego el mensaje ha conservado su integridad y tanto Ana como Linus han sido autentificados el uno al otro y establecido un canal seguro cifrado.

          Si un tercero intentase de nuevo interceptar el mensaje de Ana, cualquier cambio que produjese en él destruiría el hash del mensaje, Linus al descifrar el Hash de Ana comprobaría que este no coincide con el Hash del mensaje, luego comprende que el mensaje ha sido comprometido y rechaza la comunicación. El atacante podria redactar un nuevo mensaje, cifrarlo, calcularle el hash y firmarlo (encriptarlo con su clave pública), pero entonces Linus sabría perfectamente que la clave pública necesaria para desecifrarlo no correspondería a la Ana!! Sino a la del atacante, con lo que jamás la aceptaría. Es aquí donde radica la importancia del círculo de seguridad, la necesidad de saber fehacientemente que una clave pública pertenece a quien dice pertenecer.

          Este esquema PKI es básicamente lo que se lleva a cabo en los sistemas de clave pública PGP/GPG, pero ahora veremos las herramientas para el esquema SSL/TLS.

           

          Certíficado Digital

          Ahora sí es la primera vez que lo nombramos. Un certificado digital no es más que un documento, un archivo que identifica/asocia a un usuario con su clave pública. Cuando veíamos los repositorios de claves públicas y realizábamos una búsqueda, cada entrada tenía asociada un nombre, descripción, clave pública y firmas (los votos que hablábamos) de verificación de otras personas. Un certificado es lo mismo (con algunos matices).

          El esquema PKI anterior (llamado Web of Trust) tiene el problema de la confianza, de la legitimidad. Es un buen paso hacia delante el firmar las claves ajenas para avalar su legitimidad, y está bien para trámites particulares, personales, encriptar archivos, correos a familias y amigos… pero si una organización mundial, un gobierno, un particular o una empresa quieren garantizar que dicha clave pública pertenece sin lugar a dudas a quien dice pertenecer, es necesario un sistema más fiable. Es aquí donde aparece la “Autoridad de Certificación” (CA). Se van a continuar firmando los certificados sí, pero no por cualquier persona o grupo de ellas. Un certificado Digital asocia una serie de datos personales a una clave pública, y será un tercero, llamado Autoridad de Certificación, quien garantice que esos datos corresponden a dicha clave pública. Visto de otro modo, se trata de eliminar todas las firmas y sustituirla tan solo por una, una entidad, empresa, gobierno… cuya firma tendrá mucho más valor que cualquier otra, dado que posiblemente se ha encargado previamente de verificar y asegurar que los datos son correctos.

          Los CA de máximo nivel se les llama CA raíces o root. Existen CA que delegan autoridad a otros CA secundarios para permitirles otorgar y firmar otros certificados. Esto se debe a la cadena de confianza. Yo como máxima autoridad certifico a una empresa como CA secundaria de la cual tengo plena confianza, permitiéndole emitir y firmar certificados a ellos mismos. Si cualquiera quiere verificar un certificado emitido por un CA secundario o terciario, se realizará una verificación ascendente, primero al CA superior, el certificado de dicha CA se verificará por el CA por encima… hasta llegar al CA raíz, el cual emite él mismo su propio certificado.

          Los CA son los que emiten los certificados, y al firmarlos les otorgan plena legitimidad dado que todos nos fiamos de ellos, dado que son la máxima autoridad de certificación. Podemos decir que los CA son también esas bases de datos de claves públicas/certificados de cada usuario. Pero el CA no es la única autoridad que existe. Por otro lado suele ser necesaria (no obligatoria) la presencia de la “Autoridad de Registro” (RA). El papel de un CA puede acabar aquí, y encargarse tan solo de la emisión y firmado. Muchas veces cuando se desea cotejar/verificar si un certificado es correcto, es el RA quien se encarga de verificar dicho certificado, siendo él el que conecta con el CA. Otra figura menos usada es la “Autoridad de Validación” (VA), la cual tendría un papel similar, verificar si el certificado es válido atendiendo a fechas de tiempo y otros datos. Aun así, como digo, lo normal es ir unificando las autoridades de verificación, y de paso las comunicaciones son más eficientes. Así el mismo CA actúa como RA y como VA. Hace unos años los CA raíces eran muy pocos, lo que hacía muy útil estas autoridades intermedias. Cada vez son más los CA raíces y los sistemas más eficientes, siendo innecesaria la presencia de otras autoridades intermedias. Muchos de los lectores conocerán el nombre de algunos de ellos, actualmente el listado de CA raíces debe de rondar las 90 entidades (sin contar con los CA estatales, como CA de países, aunque estos no suelen considerarse como “universales”. Entre ellos los más importante con diferencia son: VeriSign, Thawte, GoDaddy, GeoTrust, RSA Security Inc (la empresa)…

          En los tiempos actuales, no es raro ver como gobiernos, grandes instituciones o multinacionales están considerados también como CA, lo que sucede es que normalmente estos CA no emiten certificados a cualquier persona. Por ejemplo, el gobierno español tiene al menos dos Autoridades de Certificación, la FNMT (certificados CERES) y La dirección General de Policía (Certificados para el DNI-e). Pero estas dos instituciones tan solo emiten certificados a los que tenemos nacionalidad española. Otro ejemplo de esto podría ser Intel o Microsoft. Ambos están considerados como CA raíz, pero no se dedican al negocio de los certificados digitales. Esto le permite a estas grandes multinacionales no depender de terceros, ahorrar costes y gestionar ellos mismos sus propios certificados, aunque evidentemente tan solo usan dichos certificados para ellos mismos, sus servidores, sus empleados quizás… por eso podemos dividir estos dos grandes grupos como aquellos CA comerciales y aquellos que no lo son.

          Con esto, el esquema anterior PKI se modifica ligeramente y es el CA, el RA o el VA quien valida o garantiza la legitimidad del certificado.

          Hay que destacar que no existen dos certificados, uno que sea público y otro que sea privado. El certificado es tan solo el vehículo de la clave pública. Es cierto que los certificados personales almacenados en el equipo se “guardan” con la clave privada junto a este, lo cual es completamente lógico, puesto que sin clave privada no podríamos firmar o desencriptar. En realidad esto no es del todo cierto, dado que las claves privadas de estos certificados suele estar guardadas en un anillo de seguridad del sistema/equipo. Esto no obstante ocasiona un problema de seguridad importante dado que si alguien se hace con la clave privada, el sistema quedaría completamente expuesto. Es por ello que cuando se requierer una seguridad avanzada, tanto certificados personales como las claves privadas, jamás serán almacenados en un equipo, sino en soportes extraíbles como un pendrive (en el peor de los casos) o una SmartCard (Tarjeta Inteligente) en el caso ideal, o incluso un dispositivo TPM. Esto quiere decir que nuestra clave privada residirá en nuestro DNI-e o tarjeta CERES o… protegida además por un PIN por si es extraviada o sustraída. Cuando se requiere su uso es necesario un lector de tarjetas y el software adecuado para tomar de esta la clave privada y el certificado.

          El Certificado no solo indica el nombre y apellido de quien representa, sino que incluye información del CA que lo ha emitido, algoritmos de cifrado y hash que usa, fecha de revocación, validez, tipo de certifiado… toda esta información es necesaria. Por ejemplo el certificado de identificación o cifrado de un servidor no tiene nada que ver con un certificado de cliente que podamos usar nosotros, o el certificado raiz de un CA es diferente a los otros dos. Por otro lado no todos los certificados se emiten para todos los propósitos. Lo normal es emitir los certificados con ciertas características. Por ejemplo, si se desea usar un certificado para cifrar correo electrónico será necesario que el certificado especifique una dirección de correo, y este certificado quedará anclado a él. Otro buen ejemplo es un certificado con unas características concretas para el control de acceso de una empresa o para cifrar datos en un equipo. Así, nuestro DNI-e por ejemplo tiene dos funciones principales, autentificación y firma (hablaremos más detenidamente del DNI-e en otro capítulo).

          Vamos a ver unos certificados de ejemplos: Un certificado de un servidor para SSL/TLS (Gmail), un certificado CA raíz (VeriSign) y un certificado personal para identificación SSL/TLS, firma y cifrado de correo que no de datos (Mi Certificado CERES):

          Hay que decir que estos datos son totalmente públicos, cualquiera que acceda a gMail o descargue el certificado de gMail podrá verlo. Firefox divide el certificado en dos pestañas. La primera es un resumen sobre el emisor, a quien representa y si el certificado es válido para los propósitos marcados (en este caso el propósitos es para un servidor SSL). Recordar que cada vez que un certificado es usado, lo normal es verificarlo. ¿Cómo? Verificando la firma de la entidad firmante. Podemos ver en la primera pestaña que el emisor es Thawte (que es el CA de dicho certificado), que está a nombre de Google Inc para la web mail.google.com (gMail). Se puede ver también la fecha, que aunque no hemos hablado de ella es importante, ya que cuando se emite un certificado este suele tener un tiempo limitado. Tras el cual, el certificado pasa a ser revocado (anulado) y se emite otro (normalmente antes de que expire) con nuevas claves privadas y públicas, esto se hace por seguridad evidentemente.

          La segunda pestaña desglosa completamente el contenido del Certificado. En caso de este certificado, Firefox nos muestra en la parte superior la jerarquía de CA que intervienen en dicho certificado, es decir la cadena de confianza. Así, el certificado de google para mail.googl.com es emitido por el CA “Thawte SGC CA”. Este CA no es un CA raíz, sino un CA secundario. El certificado de este CA a su vez es el que ha sido emitido por el CA raíz “Verisign Class 3 Pubblic…”. Por último se muestra la clave pública contenida en dicho certificado.

           

          El primer certificado pertenece a un certificado raíz de VeriSign, el mismo que estaría arriba del todo del certificado de gMail para la web. En este caso el uso que se indica es el de “Status Responder Certificate”. Es decir, tan solo es usado prácticamente para atender a las peticiones OCSP que pueda recibir de sus CA secundarios, es decir… verificar si los certificados están o no revocados. En este caso no se considera un CA dado que el papel de verificación de CA lo realizará el CA que esté a su servicio. Este certificado raíz fue el que emitió/validó el certificado de “Thawate SGC CA”, y es este último quein actuó realmente como CA del certificado de mail.google.com. El certificado CA intermedio será por tanto realmente el que en su descripción de uso rece: “SSL Certificate Authority”, puesto que el certificado Raíz tan solo atiende a peticiones de revocaciones. Se puede observar que efectivamente es un certificado raíz dado que el emisor (Issued By) y el destino del certificado (Issued to) no se encuentran presente, es él mismo emisor y destino, está firmado por él mismo.Si vemos la fecha por otro lado de expiración, vemos un intervalo muy grande, un certificado ahora con más de 14 años de antiguedad, que usa un algoritmo de hash MD2, un hash ya muy antiguo.

          Por último tenemos un certificado de CERES. He preferido poner este en vez del DNI-e porque este es más útil, tanto y cuando además de poseer las características de autentificación en internet (Cliente SSL), permite también la firma de correo (Email Signer) y su Encriptación (Email Recipient). Podemos ver que el emisor es la FNMT, y dado que mi navegador tiene instalado el certificado Raíz de estos y considerado fiable, el certificado de CERES lo es también, podemos leerlo arriba: “This Certificate has been verified…” Por motivos de seguridad he eliminado mi nombre, DNI y esas cosillas.

           

          Firma Digital

          En realidad poco más o menos ya se ha comentado que es y cual es su utilidad. Cuando explicábamos una PKI, exponíamos que cada clave pública se “votaba” para que los otros usuarios pudiesen así garantizar que era legítima. Esto es realmente una firma. Una firma tiene la característica de no repudio, es decir, una vez se ha firmado algo un usuario o una entidad no puede desquitarse de ello, dado que la firma lo identifica a él de forma irreversible, sin que este pueda negar que lo ha hecho.

          Las firmas digitales usan de forma conjunta dos tecnologías, la inviolabilidad de un sistema de cifrado asimétrico tipo RSA y la integridad de datos que ofrece un Hash criptográfico como SHA-1 o MD5. Si un usuario desea cifrar un documento o un mensaje para que tan solo podamos ser capaces de descifrarlo nosotros, tan solo tiene que cifrarlo con nuestra clave pública, y tan solo nosotros poseedores de nuestra clave privada podremos descifrarlo. Pero esto puede usarse de manera inversa. Si yo cifro algo con mi clave privada, la clave pública lo descifra. Dado que todos tienen acceso a mi clave pública, todos pueden descifrar aquello que yo cifre con mi clave privada. ¿Pero entonces para que vale esto? Porque un certificado garantiza la asociación de una clave pública a una persona física. Luego quien descifre algo con mi clave pública obtendrá un contenido que tiene la certeza fue cifrado solo por mí. Y por parte del Hash, otorga integridad al mensaje. El proceso es simple:

          a) Se calcula un Hash criptográfico al mensaje, documento… a firmar, por ejemplo un Hash SHA-1.
          b) Ahora se encripta por medio de nuestra clave privada dicho Hash, lo cual obtenemos un Hash cifrado.
          c) A partir de este momento, al documento se le incrusta (adjunta) la firma. El destinatario, se topará con que existe una firma de dicho documento, con su certificado público correspondiente, y por supuesto con las validaciones pertinentes. El destinatario puede descifrar el hash y obtener el Hash que aseguró el remitente que era el idóneo. El destinatario calcula el mismo Hash al mensaje recibido. Si los dos Hash coinciden, el destinatario comprende que el mensaje es legítimo y que no ha sido modificado de ningún modo.

          Una forma digital puede usarse para varias tareas. Por ejemplo, evidentemente como sustituto natural de nuestra firma física. No obstante ya hemos hablado que se usa para los certificados. Los certificados que nos emiten los CA deben de estar firmados por estos. La firma de estos en nuestro certificado funciona del mismo modo. Cuando se verifica un certificado, entre otras cosas como comprobar la fecha de validez o las listas de certificados revocados, se verifica que la cadena de confianza es correcta. ¿Esto que implica? Ir verificando uno a uno todos los certificados implicados en un certificado. Esto es verificar la firma del firmante de nuestro certificado, lo cual para ello es necesario verificar que el certificado de este CA está firmado por otra CA que sea igualmente válido… así hasta llegar al CA raíz. Si en cualquier lugar de la cadena falla la verificación, la cadena entera se rompe y el certificado no puede garantizarse como seguro.

          Otro uso común es la firma de un código. Esta es una práctica cada vez más expandida en el mundo del software. Un método de proteger un sistema operativo frente a ataques, como pueda tener Windows Vista o Windows 7, es que los drivers deben de estar firmados obligatoriamente por Microsoft (en este caso), de forma que esto garantiza que los drivers no son dañinos y son legítimos. Esto puede verse también en las partes más críticas del sistemas, en las que los archivos o el contenido más sensible para el correcto funcionamiento del sistema se firma de forma que el propio sistema no permite su ejecución si la firma no es válida. El problema que ocasiona esto no obstante es que se puede hacer un uso intensivo de esto para evitar la libertad. Por ejemplo el iPod Touch/iPhone, en el que cualquier contenido que se desee ejecutar, debe de estar obligatoriamente firmado por Apple, si no lo está no se puede ejecutar. Esto implica que (sin JB) tan solo las aplicaciones aprobadas del AppStore pueden ser usadas, al margen de que pudiese ser posible o no instalar otro tipo de aplicaciones, al margen del degradamiento de rendimiento por tener que estar continuamente verificando las firmas. Desde mi punto de vista la diferencia del buen uso y el abuso es la intencionalidad. Proteger con una firma una bios o un bootloader tiene un sentido muy simple, es una parte crucial del sistema y cualquier virus o modificación dañina produciría que el sistema sea inutilizado, lo cual implica que es positivo. Pero debería de ser una opción, no una obligación. Por ejemplo, se dijo mucho sobre los drivers de Windows x64 y que nadie podría crear drivers para ellos dado que todos tienen que estar firmados por Microsoft. Esto no es tampoco tan así. Se pueden instalar drivers firmados por uno mismo si se quiere, lo que pasa es que el sistema nos advertirá sobre la procedencia del certificado y categorizará el driver como no seguro, avisándonos del peligro que ello implica. Pero a fin de cuenta la libertad es del usuario.

          Lo habitual por tanto es ver una firma digital como un documento adjunto en un correo (extension p7s), incluida en el mismo cuerpo del mensaje en el caso de usar PKI como PGP/GPGo como un “añadido” a un documento. Al final del todo veremos aplicaciones prácticas de todo ello de todas estas cosas. De cara a un gestor de correos o cualquier otro programa que acepte contenido firmado, simplemente sabrá como interpretarlo y verificar dicho contenido.

           

          Visto todo esto podemos hacernos una imagen de lo que es un certificado digital y la firma electrónica:

          a) Ana descarga el certificado de Carmen, lo ha descargado del servidor LDAP de la empresa (o de la web de Carmen). Al instalarlo en su equipo (y sin que ella lo sepa) el certificado de carmen es comprobado. Dado que el certificado de Carmen está firmado por VeriSign, el equipo de Ana tan solo tiene que verificar que la firma de VeriSing es válida. Dado que el certificado raiz de VeriSign está incluido en el equipo, el equipo de Ana desencripta la firma de Verisign del certificado de Carmen con la clave pública que se encuentra en el certificado raiz de VeriSign. El equipo de Ana obtiene así el Hash del certificado de Carmen, el cual coincide a la perfección con el propio certificado, luego Ana está convencida de que el certificado que tiene en su poder es sin duda el de Carmen.
          b) Ahora que Ana está convencida, redacta el mensaje y lo encripta con el certificado de Carmen y lo firma con su clave privada. Lo envía a Carmen.
          C) El mensaje llega a Carmen y lo primero con lo que se topa es la firma. El gestor de correo busca la clave pública perteneciente a dicho correo electrónico accediendo posiblemente al repositorio del CA emisor y el nombre y apellidos de Ana. Carmen no se fia de que sea Ana, pero el certificado que ha encontrado efectivamente tipifica dicho correo electrónico y dichas credenciales, y está emitido y firmado por la FNMT (se verifica la firma de la FNMT, que a su vez verifica el certificado de Ana). Cuando está seguro del certificado de Ana, desencripta la firma con él, dado que la clave pública de Ana desencripta el hash que fue encriptado con la clave privada de esta. Carmen verifica la firma y con su clave privada desencripta el mensaje y lo lee.

          Seguridad: Encriptación y Autentificación. Capítulo Segundo -> Cifrado de Datos

          ATENCION: Los ejemplos que se van a mostrar y “tutoriales” tan solo tienen carácter educativo. En ningún aspecto comparto filosofías de invasión a la intimidad, ataques contra un sistema informático o cuestiones similares. En la medida que sea posible siempre se usarán ejemplos y formas que puedan ser usados por cualquier persona, de forma que pueda verificar los contenidos escritos. No obstante, por motivos más que obvios, materiales como contraseñas, nombres de usuarios o de hosts, serán omitidos o modificado en las capturas de pantallas realizadas (o las lineas escritas). Es decir, los ejemplos serán completamente reales, los datos mostrados a vosotros necesarios para poder pertrechar estos ejemplos no siempre lo serán (Sí lo serán los resultados). Para que esto conste de forma clara, todo material sensible modificado o falso estará resaltado en ROJO. Por motivos de seguridad, todo el material que sea expuesto aquí (exceptuando software propietario o libre, citaciones expresas o código de terceros) tanto texto, imágenes y código son propiedad del autor y está completamente prohibido su reproducción completa o parcial en otros lugares, espero que se comprenda.

           

          Cifrado de datos

          Este no es un término nuevo, y desde tiempos inmemorables es algo que se ha ido haciendo de un modo u otro. Y es que seamos honestos… no nos suele gustar la idea de que puedan invadir nuestra intimidad o interceptar cartas, mensajes, ideas… que van hacia otra persona. Evidentemente esto toma una importancia mayúscula cuando esta información es sensible o de suma importancia. Quzás el primer gran ejemplo de criptografía en el ámbito de las comunicaciones fue sin duda la máquina Enigma.

          Para quien no lo sepa, la máquina Enigma fue un dispositivo similar a una máquina de escribir diseñada allá por los años 30, siendo famosa por ser usada por los Alemanes durante la Segunda Guerra Mundial. Era un dispositivo creado con inteligencia. Digamos que poseía tres discos con 26 posiciones cada uno. En cada una de esas posiciones se mapeaba una letra. Cada letra de cada disco a su vez se encontraba conectada con el disco vecino, y dependiendo de la posición inicial de cada uno de los discos, la letra era mapeada de disco en disco en una o en otra. Se diseñaba de tal modo que al presionar una tecla de la máquina, esta quedaba asociada con una letra mapeada del primer disco. En el primer disco la letra se mapeaba a la letra de salida del primer disco (que no correspondía a la de entrada) y en dicha salida se conectaba el segundo disco. El segundo disco tomaba de entrada la salida del primer disco e igualmente que como hacía este, internamente esa letra de entrada la mapeaba a la salida. El tercer disco hacía lo propio, tomaba la letra de salida del segundo y según su posición en dicho momento la transformaba en otra diferente a su salida. Despues de todo esto, un 4 disco (no obligatorio) hacía que existiese un camino de retorno, de forma que se pasase de nuevo por el tercer disco, despues por el segundo y después por el primero. La salida se conectaba a una bombilla que indicaba la letra codificada. Para evitar separaciones de palabra, todo el mensaje era enviado sin espacios.

          Posiblemente fue la primera máquina seria para cifrar comunicaciones. Hay que decir que, según dicen, gracias a que la alianza fue capaz de desencriptar la mayoría de las comunicaciones de los alemanes (gracias a que pudieron romper en gran medida el sistema de Enigma) la guerra duró dos años menos de lo que podría haberse alargado. Un buen ejemplo sin duda alguna de criptología.

           

          Para nosotros es cosa del pasado. Vivimos en un mundo digital y un mundo en el que las comunicaciones juegan un papel a día de hoy imprescindible. Por lo tanto es de sentido común que existan sistemas que podamos considerar seguros tanto para almacenar datos de forma protegida como para ser capaces de crear canales seguros de comunicación entre dos puntos cualquieras del mundo. Precisamente porque las comunicaciones se han convertido en algo imprescindible y de uso constante, no podemos hacer oídos sordos y pensar erróneamente que nuestros datos no son de la importancia de nadie. Dado que los canales de los que hacemos uso son públicos, nuestra información, nuestros datos están expuestos a todos. Puede que a nadie le importe que otros puedan saber en un momento dado en que blog escribe, que vean las fotos que tienen guardadas o las recetas archivadas. Pero seguro que a nadie le gustaría que humeen en su correo, en sus cuentas bancarias, en todo aquello que pueda ser de índole personal. Lo que pasa es que se presupone que todo es seguro y que no existirá nunca una intervención externa… y esto no es así. Como vimos con el Spoofing o como veremos en otros artícuos como el Sniffing, la intención rara vez encaja con la realidad.

          Por todo ello vamos a introducirnos un poquito en los sistemas reales de protección que podemos encontrar a día de hoy. Y digo reales porque posíblemente gracias tan solo al cifrado de datos es posible garantizar una intimidad a la cual tiene derecho todas las personas. No vamos a estudiar la máquina enigma de ningún modo, vamos a ver los dos sistemas de cifrado que disponemos en la actualidad, cada uno con sus pros y sus contras, claro está:

          • Cifrado Simétrico
          • Cifrado Asimétrico

           

          Cifrado Simétrico

          Un cifrado simétrico no es más que algún sistema por el cual se encripta un contenido aplicándole una clave (o key, del ingles llave) y se desencripta usando la misma clave. Podemos pensar de un modo más específico en una contraseña, pero esta no es más que una particularidad de un cifrado simétrico. Por ejemplo, la máquina enigma era un dispositivo de cifrado simétrico, en el que la key era la posición inicial de los discos y el cableado interno que mapeaba las teclas a los discos. Se usaba por tanto la misma disposición si se deseaba recuperar el mensaje original. En la era digital, nuestras key suelen ser lo que comunmente llamamos “contraseñas”, aunque no todas las contraseñas son para cifrar. Así por ejemplo llamamos contraseña a la cadena de caracteres que debemos de teclear para poder encriptar un documento, pero también llamamos contraseña a la cadena de caracteres que debemos de teclear para acceder a nuestro correo, y no se usa en modo alguno para cifrar nada, solo como método de control de acceso. En cualquier caso, esta key (no usaremos el termino “contraseña”) en los cifrados simétricos sería la misma para encriptar un dato que para desencriptarlo.

          Como vimos en su momento con los Hash, podríamos suponer que con el cifrado simétrico lo que sucede es algo similar. A un dato de entrada se le aplica una función que depende de una key para producir una salida. Pero a diferencia de los hash, la encriptación no es un camino único, es decir, la salida puede convertirse bit a bit exactamente igual a la entrada cuando el mensaje se desencripta. Esto implica que la función que sea aplicada a la entrada no será sino una serie de modificaciones que se realizarán a los datos de entrada para ocultarlos. Esas modificaciones dependerán íntegramente de una key.

          Según el sistema usado por el sistema de cifrado, se puede clasificar dos tipos de cifrados simétricos: Cifrado de bloques y cifrado de flujo. Pese a que pueda ser más o menos complicada la matemáticas detrás de cada algoritmo de cifrado, no lo es tanto comprender su funcionamiento.

           

          Primero veamos el cifrado simétrico de flujo. El cifrado de flujo se pensó idealmente para aquellas tareas en las que se desea cifrar algo que se está generando en tiempo real. Es decir, en un principio pensado para las comunicaciones. Esto tiene su lógica, si deseamos encriptar un archivo de 20MB en disco por ejemplo, conocemos a priori no solo el tamaño completo del archivo, sino también cada uno de sus byte. En cambio cuando los datos a transmitir son en tiempo real (por ejemplo) el modelo anterior no vale, tan solo podemos ir codificando pequeños fragmentos de un todo, fragmentos tan pequeños como bytes o incluso bits. Es decir, cada byte (por ejemplo) que se genera, se encripta y se envía. El fragmento enviado por tanto tiene significado propio, puesto que aunque pertenece a un todo, el mismo byte (en este caso) se desencripta directamente en el destino.

          Pese a la complicación que esto pueda parecer, es relativamente simple en concepto. La idea es poder cifrar unidades mínimas de contenido sin que estas dependan de nada más. Pero esto crea un problema… Si la misma key fuese usada para todos los bytes, sin siquiera conocer la key sería muy facil atacar un cifrado en flujo, dado que las unidades codificadas son muy pequeñas, sería fácil encontrar mensajes o partes de estos, patrones… Para evitar esto lo que se hace con los cifrados de flujos es generar también un flujo constante de keys. Esto suena raro… el algoritmo de cifrado simétrico de flujo aplica una serie de operaciones matemáticas “seguras” para generar a su salida un flujo constante de bits, no predecibles claro está, que a su vez son los que son usados para cifrar a su vez el flujo de datos. Vamos a ver un ejemplo sencillo de esto aplicando posiblemente uno de los cifrados más básicos que existe, el cifrado XOR. XOR es una operación lógica que dice lo siguiente:

          style=”text-align: justify;”>Si A = B => A XOR B = 0. Es decir, se puede expresar como A XOR A = 0
          style=”text-align: justify;”>Si A != B => A XOR B = 1. Es decir, se puede expresar como A XOR 0 = A

          Al igual que con los hash, imaginemos una función tal que F (key) = Kflujo

          Si tenemos lo anterior en cuenta, ahora imaginemos dos flujos de datos constantes de bits:

          Datos para EnviarMensaje XOR KeyDatos Enviados
          Mensaje Original:1010011101011001
          Kflujo:1100101111100100
          Mensaje Final:1010011110111101

          Es decir, el flujo constante de datos a enviar se combina mediante una operación XOR con un flujo de datos constantes también generado por una Key inicial gracias a un algoritmo dado. El receptor en nuestro ejempli tan solo tendría que generar el mismo flujo de datos desde la key original y aplicar la misma operacion XOR a los datos recibidos, de ese modo el mensaje original se reconstruiría. De este modo, a partir de un cifrado simple y lleno de problemas como pueda ser un cifrado XOR, se logra que sea consistente gracias al flujo constante de bits derivados de la key original.

          No obstante, por regla general los cifrados en flujo son mucho menos robustos que los cifrados en bloques, y estos a su vez pueden actuar como cifrados en flujos, lo que poco a poco deja a los cifrados simétricos de flujo en desuso. No obstante, a día de hoy continúan siendo una fuerte columna vertebral de las comunicaciones, siendo su buque insignia el cifrado RC4. Aunque es un cifrado que ya no podríamos considerar seguro dado a los ataques pertrechados hacia él con relativo éxito, continúa siendo un cifrado extremadamente simple de implementar y de procesar, lo que lo hace ideal para tareas en las que la seguridad a lo mejor no es crucial, pero si importante. Por ejemplo, RC4 es el cifrado que usan las redes WIFI que usan WEP, el algoritmo de cifrado es RC4, y como todos sabemos WEP es un sistema a día de hoy completamente roto. Otros ejemplos de RC4 fue su uso (cada vez menos habitual) en certificados digitales (ya veremos esto más adelante). Y posiblemente los amantes de las redes Torrent podrán ver en muchos de sus clientes la opción de cifrar todo mediante RC4. Como vemos, aunque no nos otorga un grado de seguridad completo, para muchas tareas es bastante útil. En la actualidad existen otros cifrados de flujos más seguros que RC4, como por ejemplo las alternativas eStream. Personalmente no creo que vuelvan a ponerse de moda los cifrados en flujos, y que se continuará con la tendencia de los cifrados en bloque.

           

          El cifrado simétrico en bloques difiere en concepto del cifrado en flujo. En este caso no se pretende a priori cifrar bit a bit un contenido, sino aplicar a un bloque de un tamaño preestablecido una serie de transformaciones (evidentemente reversibles) para dar como resultado una salida encriptada de dicho bloque. La pregunta podría estar entonces, que si dicho bloque es pequeño y el cifrado de flujos actúa sobre unidades “grandes”, ambos conceptos podrían ser iguales. Y esto es cierto.

          En el caso del cifrado en flujo lo importante es la forma en la que se generará el flujo de keys y el sistema que se realizará para “combinar” los dos flujos. Aquí el sistema es mucho más complejo y sólido normalmente. Normalmente un mensaje que se quiere cifrar es dividido en bloques (de ahí su nombre) de tamaños de 64-256 bits cada uno. Lo ideal por tanto es siempre encriptar un contenido que sea cientos de veces dicho número, con lo que se tendrían cientos de bloques independientes. Cada bloque suele funcionar del mismo modo, las mismas operaciones que se aplican a uno se aplican a otro. No obstante, al igual que sucediese con los cifrados de flujo, lo normal es que la key original tan solo sea key del primer bloque, siendo la key del resto de ellos una key derivada ya no solo de esta, sino del contenido encriptado, lo cual hace ya de por sí complicada su “búsqueda”. La diferencia por lo tanto entre los diferentes cifrados de bloques radicará en esas transformaciones realizadas dentro de los bloques para obtener el resultado.

          Normalmente, a estas transformaciones se les denominan “Etapas”, y no es extraño ver cifrados de bloques con varias de ellas. Por ejemplo el Cifrado AES consta de entre 10 a 14 etapas, dependiendo de la longitud de su Key. Al final de todas las etapas de cada bloque, se genera el mensaje cifrado, que en contraposición con el cifrado de flujo, aquí normalmente cada bloque cifrado es dependiente de todo su bloque, no existe una correspondencia bit cifrado – bit descifrado.

          Pese a que cada algoritmo es diferente, los cifrados de bloques igualmente tienen diferente modos de operación. Cada uno de ellos no difieren por el tipo de transformaciones aplicadas, sino más bien por las interacciones entre sus bloques. Así por ejemplo, el sistema más sencillo de cifrado por bloques sería aplicar a cada bloque una función matemática tipo Fbloque(Key) = Bloque_Cifrado. Es decir, a cada bloque se le aplicaría siempre la misma key de forma independiente. Este esquema se contempla, y se llama sin ir máss lejos ECB.

          Un paso más allá sería algo similar a lo que se ha visto con el cifrado de flujos. En este caso cada bloque no es independiente. En el modo CBC el bloque cifrado se combina mediante una operación lógica XOR con el bloque aun sin cifrar del siguiente bloque, y el resultado será el bloque que, ahora sí, se pasará a cifrar. De este modo simple, se logra una dependencia completa de cada uno de los bloques, haciendo inviable muchos ataques criptográficos.

          Aunque existen otros sistemas de funcionamiento de los cifrados de bloques, la mayoría aplican el concepto explicado para CBC (Cifrado de bloques en cadena) pero en diferentes partes. Por ejemplo, se podría realizar la operación XOR en vez de entre el bloque cifrado y el bloque siguiente sin cifrar entre el bloque sin cifrar y el bloque cifrado de un mismo bloque y realizar a continuación otra XOR con el bloque sin cifrar siguiente, y a esto se le llamaría PCBC.

           

          Estos modos de funcionamiento que pueden parecer no tener importancia, la tienen y mucha. Un test bastante conocido para comprobar la resistencia de un sistema de cifrado frente a la posible repetición de patrones, es la codificación de una imagen. Una imagen suele tener patrones que se repiten constantemente, es decir, en una imagen suelen existir zonas uniformes que pueden tener el mismo contenido. Luego una imagen es un ejemplo perfecto para atacar a un cifrado. ¿Como se realiza esto? Una imagen no son más que puntos distribuidos uniformemente sobre toda una superficie, cada cual con un color. Si quisiésemos almacenar una imagen en nuestro sistema, el método más simple sería simplemente tomar cada punto de la imagen de forma consecutiva e ir añadiéndolo a un archivo binarios simplemente especificando su color. Esto se comprende mucho mejor con un ejemplo. Pensar en que tenemos una imagen de 5 x 5 pixeles, cada uno de los pixeles está codificado en RGB con 1 byte para cada canal, es decir, que cada punto se representaría en una matriz de (5×3)x5 en la cual cada elemento constituye un byte (un valor entre 0 y 255) . Esta podría ser nuestra imagen expresada como una matriz de puntos:

          128 045 135 236 002 237 112 222 012 087 158 255 000 055 099
          128 045 135 236 002 237 112 222 012 087 158 255 000 055 099
          128 045 135 236 002 237 112 222 012 087 158 255 000 055 099
          128 045 135 236 002 237 112 222 012 087 158 255 000 055 099
          128 045 135 236 002 237 112 222 012 087 158 255 000 055 099

          En un archivo binario esto se almacenaría simplemente un valor tras otro. Para visionar dicha matriz de puntos tan solo tendríamos que conocer esta distribución y aplicarla a la pantalla de nuestro monitor. Sabemos que es una imagen de 5×5 con 3 canales de color, con lo que el PC tan solo debería de tomar los valores de 3 en 3. Cada 3 valores obtendrá el color de cada pixel, y su ubicación dentro de la matriz corresponderá a la ubicación del pixel en la pantalla. Este sistema no obstante no puede aplicarse a los algoritmos de imágenes actuales como JPG, PNG, TIFF… ya que estos de un modo u otro aplican compresión a las imágenes (ya sea con pérdida o sin ella), y no se podría comprobar lo que queremos explicar. Podríamos llamar a esto una imagen RAW, el problema de llamarlo así sería la confusión que ocasionaría con las imágenes RAW de las cámaras de fotos.

          Visto esto, veamos la aplicación real. Primero partiremos de una Imagen RAW Fuente creada para tal ejemplo a la que he llamado egocéntricamente “Theliel”, “Alma Oscura” era muy largo para este propósito:

          Evidentemente la imagen mostrada aquí no es una imagen RAW (Entendiendo RAW no como imagen de las cámaras de fotos), es una conversión a png para que el navegador pueda mostrarla. ¿Pero que es lo que sucede cuando la codificamos con un algoritmo como AES-256 (el cual veremos más adelante)? Para ello se ha realizado dos simples conversiones, una usando el método ECB y otra usando el método CBC:

          La primera pertenece a la codificación ECB, mientras que la segunda imagen corresponde a la codificación CBC. Ambas imágenes hablan por si mismas. Si se accede a las versiones grandes, se puede comprobar aun mejor que incluso cuando se está codificando con AES-256 (un cifrado muy fuerte), cuando se realiza en ECB la imagen puede ser adivinada, incluso el texto es completamente legible. La imagen no es del todo clara, pero se puede apreciar perfectamente el contorno de la manzana de Apple. Esto nos plantea lo que a mi parecer es uno de los grandes problemas de la seguridad, y es que el problema no radica ya en encontrar sistemas que sean seguros, sino en el uso que se den de ellos. Que exista el método ECB no implica que sea una buena opción usarlo. El resultado de un cifrado en ECB de cada bloque es el mismo si el bloque a encriptar no varía. En una imagen, no es raro encontrar estos patrones, y dado que podemos representar de una forma gráfica esta encriptación, obtenemos un resultado realmente curioso, como el que hemos mostrado. En contrapartida, al usar CBC, cada bloque tenga o no tenga la misma información, será codificado de forma diferente, dado que la codificación de cada bloque depende del anterior. El resultado es una nube de píxeles de colores sin sentido alguno, quedando la imagen real completamente oculta.

          Los cifrados de bloques según lo explicado, no obstante deja algunas incógnitas como que sucede cuando el contenido a cifrar no corresponde a un tamaño múltiplo del tamaño de bloque o que sucede con aquellos bloques que requieren de un bloque anterior (o posterior) y no lo poseen dado que son el primero o el último.

          Respecto al primer problema, el tamaño de bloque, se acude a una técnica mas que conocida por la mayoría de los programadores, el Padding. Es decir… rellenar. Si los bloques son por tanto de 64bits y el último bloque tan solo tiene 32, los 32 bits restantes se rellenarían. Esto hace a su vez aparecer un problema añadido… la salida tendrá un tamaño siempre mayor que la entrada, dado que será necesario añadir tantos bits como sea el caso para poder completar el bloque. Y el segundo problema que aparece es con que datos rellenar ese Padding, lo que produce a su vez que sea complicado esclarecer el tamaño REAL del mensaje original. Para esto existen diferentes técnicas más o menos elaboradas, pero decir al menos que rellenarlo todo con simples carácteres “null” (nullo) no sería recomendado.

          Respecto al segundo problema, lo normal es que exista una entrada adicional a la Key y al contenido a cifrar en el sistema, que se denomina como vector de inicialización (IV). No obstante, dado que estos vectores no pertenecen al algoritmo dado y normalmente no es dado tampoco como dato de entrada, lo normal es que la propia implementación del algoritmo lo establezca. Otra solución sería no usarlo o suponer que de no expresarlo, el vector de inicialización será una cadena de ceros.

          No han sido pocos los cifrados de bloques que han existido y existen. Muchos de ellos buscando siempre ser el mejor en cuanto a seguridad se refiere, otros por ser los más rápidos, otros por ser mejores en otros fines… y se llegó al absurdo de que existían un sin fin de cifrados de bloques que eran usados. Todo ello por supuesto sin contar con el secretismo. Antes se pensaba que cuanto más secreto fuese un cifrado, más invulnerable era. Esto parecía lógico, si nadie sabe como se implementa o como funciona, lograr desencriptarlo sería complicado. El problema no obstante es que un millón de cabezas piensan más y mejor que unas cuantas cabezas de ingenieros que en su día crearon dicho algoritmo.

          Así, posiblemente el primer cifrado por bloques que llegó a convertirse en un estándar y publicado como tal fue DES (Estandar de encriptación de datos). DES contaba con una key de 56bits, bloques de 64 bits y un total de 16 rondas. Al margen de lo seguro o no que pudiese ser, hoy por hoy sería impensable un sistema de cifrado con key de 56bits. En el peor de los casos por simple fuerza bruta serían necesarias 256 comprobaciones, y con el hardware actual sería un valor fácilmente alcanzable. En 1998 se creó un hardware “barato” que fue capaz de obtener una key DES por fuerza bruta en tan solo 56 horas, aunque un año más adelante tan solo necesitó 22 horas. Esto hizo replantearse seriamente el uso de DES. Después de esto, se comenzó con el uso del sucesor de DES, llamado Triple DES, publicado en 1998 y que básicamente era igual a DES, pero usaba un conjunto de 3 Key DES de 56 bits cada una. En algunos esquemas estas Keys eran independientes, en otros eran keys derivadas. Y aun que a día de hoy se puede considerar Triple DES como seguro, la realidad es que en 2001 fue publicado oficialmente AES. Al igual que se hiciese con los Hash SHA, el período de estandarización de AES fue de 5 años. 5 años en los que compitieron los mejores algoritmos de cifrado de la época, algunos de ellos conocidos dentro del mundo de la criptografía: RC6, Serpernt, Blowfish… y por supuesto el ganador: Rijndael, que pasaría a ser llamado AES (Estandar avanzado de encriptación). AES se estandarizó con 3 longitudes de key diferente, así existe a día de hoy AES-128 AES-192 y AES-256, con un tamaño de bloque de 128 bits. No obstante, el algoritmo original permitía bloques de diferente tamaños y keys.

          AES a día de hoy es completamente seguro. Tal es así, que el gobierno de EEUU aceptó el uso de AES-256 para su uso en su material clasificado como “Alto secreto” y AES-128 AES-192 para su material clasificado como “Secreto”. Es decir… actualmente y posiblemente por muchos muchos años, AES permanecerá como cifrado simétrico estandar y seguro.

          El como funciona AES en realidad no es tan complejo si comprendemos el funcionamiento de los cifrados de bloques. Lo único que habría que conocer son las transformaciones que se realizan en los boques, esas 10-14 etapas que se llevan a acabo en cada bloque. En primer lugar lo que AES realiza es generar una subkey de bloque derivada de la key original e interpreta la hilera de bits del bloque (128 bits) como una matriz de 4×4 bytes (1 Byte son 8 bits, 4x4x8 = 128 bits). Una vez se ha creado la estructura básica del bloque, se aplica el cifrado XOR a la matriz entre esta y la subkey de bloque generada. Una vez realizada esta operación, se realizan una series de operaciones en la matriz, como desplazamiento de columnas, mezclado y otras operaciones no lineales. Para acabar se realiza de nuevo una operación XOR con la subkey que corresponda (diferente a la key de la primera XOR). La matriz resultado se envía como bloque cifrado en una sucesión de bytes.

          Como vimos en el ejemplo anterior, AES-256 en realidad sí que es extremadamente seguro, pero es necesario siempre un buen uso de dichos cifrados. Para terminar un pequeño ejemplo de un esquema de codificación simétrica, mostrando muchos de los conceptos aquí tratados:


          CrypTool 2 Beta


          En el esquema se puede observar como existen tres elementos principales de entrada: El archivo a codificar llamado “Original”, la Key usada llamada “Key” y un generador aleatorio de IVs. Los bloques en azul claro corresponderían a los algoritmos de cifrado, en este caso se ha usado AES-256 ECB y CBC y DES ECB. Por último los archivos de salida generados de los procesos aplicados. Se observa no obstante que para los módulos AES no se ha usado una entrada IVs. Lo que sucede es que el vector de inicialización en este caso sería 0×0000000000000000 (8 bytes). DES por el contrario requiere que se incluya, por ello se ha usado un generador aleatorio de IVs, que no es más que un generador aleatorio de valores de 8 bytes en este caso, dado qeu DES requiere un IV de 8 bytes, es decir, del tamaño de cada bloque (64 bits). Cabe destacar que para la desencriptación del archivo cifrado DES sería necesario suministrar exactamente el mismo IVs, de lo contrario no sería posible recuperar el archivo original. Para esto, siguiendo el esquema, sería tan siple como incluir en la entrada del supuesto módilo de desencriptación DES otra salida del mismo generador de IVs.

          El cifrado simétrico es seguro cuando se usa un algoritmo y sistema de cifrado correcto.

           

           

          Cifrado Asimétrico

          El cifrado simétrico es seguro, es cierto… pero estará siempre enfrentado a una serie de ataques que antes o después es posible que sean rotos. Y su principal desventaja no es esa… es la key. El cifrado asimétrico apareció como alternativa a ello. Pero vamos a ver primero la necesidad del cifrado asimétrico, sería absurdo crear un sistema que no tenga una utilidad.

          Hemos dicho que el cifrado simétrico tiene dos problemas. El primero de ellos es que está basado en algoritmos de dos sentidos, es decir, prácticamente (por no decir todas) todas las transformaciones que sufre el bloque por las diferentes etapas son funciones invertibles que a través de la misma key se puede reconstruir el mensaje (dato) original. Esto implica que la fortaleza del algoritmo simétrico recaiga tan solo en las transformaciones algebraica que se realizan sobre el bloque. De ahí que prácticamente todos los cifrados simétricos que se han estudiado antes o después se descubren diferentes ataques a sus diferentes etapas. Por ejemplo, para AES existen ataques exitosos en versiones reducidas de este, es decir, AES con menos etapas. Si AES-128 posee 10 etapas, a lo mejor se ha logrado ataques que pueden considerarse una roptura (es decir, que son computacionalmente posibles) para versiones de 6 o 7 etapas tan solo. La idea de estos ataques es ir logrando cada vez más romper cada etapa, de modo que al ir añadiendo una etapa más, el coeste computacional pueda considerarse factible. Si se llega a obtener un ataque a AES-128 en el que el coste computacional obtenido sea de 280 (por ejemplo) se considerará una roptura, frente a 2128 posibilidades iniciales.

          El segundo problema al que se enfrenta el cifrado simétrico es la Key. La key es necesaria tanto para cifrar un mensaje como para desencriptarlo. Esto implica que tanto origen como destino tengan que compartir dicha Key. Esto a simple vista puede carecer de importancia, pero esto quiere decir que si queremos realmente una seguridad decente, en el mejor de los casos tendríamos que tener una key diferente de comunicación con cada uno de los usuarios con los que deseamos entablar una comunicación segura, dado que no usaríamos nunca la misma key con otros usuarios, de ser así otros usuarios podrían leer los mensajes que eran destinados para otros. Esto provoca la necesidad de múltiples keys para cada usuario, lo cual es engorroso e inseguro, dado que la comodidad podría implicar usar la misma key en todas las comunicaciones y esto supondría un problema de seguridad.

           

          El cifrado simétrico resuelve estas dos cuestiones. La primera de ella haciendo uso de lo que podríamos llamar “Matemática Imposible”. En el cifrado simétrico se logra un algoritmo de cifrado de un único sentido, el cual no es computacionalmente viable el invertirlo. Podemos decir así que existen en realidad dos algoritmos diferentes dentro de un esquema de cifrado asimétrico, un algoritmo que encripta y otro que desencripta. Y al contrario que sucede con las transformaciones o la álgebra aplicada a un algoritmo simétrico, en la criptografía asimétrica esta función suele ser mucho más simple, lo cual no implica que sea más rápida, todo lo contrario. Así por ejemplo el cifrado AES requiere de 10 etapas mínimas para completar el cifrado de un bloque, mientras que el el cifrado RSA esto se limita a una “simple” función, aunque lo que no es simple es la teoría y el cálculo de dicha función. Estas funciones se basan en la premisa de que es imposible invertirlas, así por ejemplo tenemos el problema matemático de la factorización (usado en RSA) y el del logaritmo discreto (usado en ElGamal). Vamos a basarnos por simplicidad y fácil compresión en RSA. Posiblemente hasta los niños más pequeños aprenden a temprana edad que es la factorización de un número. Factorizar un número no es más que encontrar sus factores, es decir, los diferentes números que lo dividen, es decir, aquellos números que al dividirlo dan como resto cero:

          Factorización de 20: 1,2,4,5,10 ya que 20 mod 10 = 0 20 mod 5 = 0….

          Todos sabemos factorizar un número, el problema radica en dicho método. El problema reside en que la única forma real de obtener los diferentes factores de un número (así como saber si dicho núnero es por ejemplo primo) radica en ir dividiendo dicho número por cada uno de los números desde el 2 (el 1 es factor de todos los números) hasta n-1, siendo n el número a factorizar. Si disponemos de un número relativamente pequeño como el 101, podemos simplemente ir dividiendo este por 2, por 3, por 4… hasta llegar al 99. En realidad a la hora de encontrar los factores no es necesario llegar a dicho número, tan solo es necesario realizar Raiz (n) operaciones. Es decir, en el caso que el número a factorizar fuese 101, en realidad tan solo sería necesario ir probando Raiz (n) = 10 aprox, es decir, después de 10 operaciones podríamos conocer si realmente 101 es primo: 101/2, 101/3, 101/4… 101/10. Esto podría parecer no tener complicación alguna, 10 operaciones podríamos hacerlas incluso a mano. ¿Pero que sucede cuando el número a factorizar es infinitamente mayor? Podríamos pensar que un PC actual podría manejarlo en segundos, pero esto no es así. Existen diferentes algoritmos que intentan dar una opción viable a la factorización sin necesidad de usar divisiones una a una, el problema es que estos algoritmos no son fiables al 100% ni mucho menos, produciendo lo que se conocen como falsos números primos. Aun así, cuando se manejan los números tan ingentes que pronto veremos, ni haciendo uso de estos algoritmos sería posible. Vemos por tanto en este caso, que la matemática detrás de la factorización es más que conocida, es sencilla, pero es computacionalmente imposible para grandes números.

          Respecto al segundo problema comentado, la key, en el cifrado asimétrico no existe una sola key, sino dos. Una key se denomina como clave pública y la otra como clave privada. El concepto es simple. Cada una de las claves son complementarias y pueden ser usadas tanto en el algoritmo de encriptado como en el de desencriptado, es decir, lo que encripta una clave lo desencripta la otra. No hay que pensar en clave pública como clave para desencriptar, sino clave que se distribuye a todo aquél con el que deseamos entablar un canal seguro. A diferencia que el cifrado simétrico en el que es necesario una key única para cada canal de comunicación, aquí será la clave pública la que será usada para todos. Este concepto choca al principio, una clave que se da a conocer a todos. Por otro lado la clave privada será el mayor secreto para su dueño, y es aquí donde reside la vulnerabilidad desde mi punto de vista del cifrado asimétrico. Visto esto, es lógico asumir que el par de claves (privada y pública) deben de estar relacionadas de modo alguno, pero sin que pueda suponer un riesto el conocimiento de dicha clave pública.

          Estas dos características hacen que el cifrado asimétrico sea a día de hoy posiblemente el sistema más seguro en cuanto a encriptación de datos, y ello puede verse diariamente. Todas las comunicaciones cifradas a día de hoy que requieren de una privacidad importante, están basadas de un modo u otro en cifrado de clave pública (o cifrado asimétrico). No obstante no todo son ventajas. El cifrado asimétrico para empezar requiere de una capacidad de computación muy superior a la del cifrado simétrico para realizar la encriptación o desencriptación, llegando a ser cientos de veces más lento. Por otro lado se requieren por regla general keys de una longitud muy superior a lo que es habitual encontrar en el cifrado simétrico. Por ejemplo AES-256 (Key de 256 bits) frente a RSA, que puede usar Keys de entre 1024-4096 bits. Aunque una Key de 4096 bits (512 Bytes) sea un tamaño irrisorio para las comunicaciones, nadie sería capaz de recordar jamás una clave de 512 caracteres. En contrapartida, con AES-256 (32 Bytes) por un lado no sería complicado recordar una frase de 32 caracteres, pero además no es necesario, dado que generalmente las subkeys usadas son generadas apartir de nuestra “clave” introducida. Pero en el cifrado asimétrico esto no funciona así, no existen keys derivadas, una para encriptar todo el mensaje, una para desencriptar todo el mensaje.

          Este problema de keys grandes se une al echo de la necesidad de que una Key pública sea conocida. Si deseamos que alguien encripte un mensaje hacia nosotros, este mensaje deberá de cifrarlo usando nusetra key pública, luego dicho usuario deberá tener acceso a nuestra key pública. Del mismo modo si queremos responder a dicho mensaje, tendremos que o usar la clave publica de dicho usuario para encriptar la contestación o encriptar la contestación con nuestra clave privada, ya que el receptor dispondrá de nuestra clave pública para desencriptarlo o su clave privada. Para que esto pueda ser posible, hace ya mucho tiempo que se establecieron bases de datos de claves públicas, de modo que cualquier persona pued acceder a ellos de forma simple y conocer la clave pública de cualquier persona.

           

          Posiblemente los dos algoritmos de cifrado asimétrico más conocidos sean como hemos dicho RSA y ElGamal. Cada uno de ellos se basa en una imposibilidad matemática y por comodidad vamos a explicar como funciona RSA a grandes rasgos.

          RSA como hemos dicho se basa en la imposibilidad matemática de factorizar un número grande. El proceso no es muy complejo. Lo primero es generar las claves que serán usadas, tanto la privada como la pública:

          1. Tomar dos números primos, llamados ‘p’ y ‘q’, los cuales por seguridad se requiere que ambos tengan una longitud de bits similar, para garantizar en caso de un posible ataque el “peor de los casos posibles”, y por otro lado que puedan escaparse a los algoritmos conocidos de búsqueda de primos. Estos dos números es normal encontrarlos de al menos 512 bits de longitud, es decir, un número con más de 154 cifras.
          2. Se calcula n = p x q, y acto segido la función Phi de Eulerm definida como Phi (p x q) = (p-1)(q-1). La función Phi de Euler calcula el número de coprimos que existen a un número dado. dos números son coprimos si no tienen ningún factor en común salvo el 1. Es decir, aunque el 10 no es un número primo, el 14 es coprimo de 15, dado que tan solo comparten el factor común uno. Dado que tanto p como q son números primos (ta solo divisibles por 1 y por ellos mismos) poseerán cada uno un número p-1 y q-1 de coprimos cada uno.
          3. Se escoge un número ‘e’ que se encuentre entre en el intervalo 1 < e < Phi(p x q), de modo que e y Phi sean coprimos entre ellos. Si ‘e’ a su vez es primo mejor.
          4. Se calcula ‘d’ en la siguiente función: d x e = 1 (MOD Phi (pxq)). de = 1 MOD Phi(pq) es quizás el principal problema de comprensión en RSA. Esta función recibe el nombre de multiplicación modular inversa, y se calcula de forma simple gracias al método extendido de Euclides. En realidad es tan solo matemáticas aplicadas. NOTA: Los “Iguales” que son especificados en estas igualdades en las que implican operaciones modulares, no son en realidad “Iguales”, sino “Congruentes”, es decir… equivalentes. Escribir “d x e = 1 (MOD Phi (pxq))” siendo ese “Igual” el símblo de congruencia, significa que 1 = dxe MOD Phi, siendo ese Igual un Igual de los de toda la vida.

          Después de estos 4 pasos, la clave privada y la clave pública estarán ya creadas. La clave privada corresponderá entonces a la tupla Clave_privada (n, d), mientras que la clave pública a la tupla Clave_pública (n, e). Una vez obtenidas sendas claves tan solo es necesario aplicar la función de encriptación o desencriptación. Por cuestiones de Padding y seguridad, el mensaje es convertido a un número entero ‘m’, menor a ‘n’:

          me = Cifrado MOD n -> Se obtiene así un valor en Cifrado

          Cifradod = m MOD n -> El valor Cifrado será desencriptado por medio de dicha función y se obtendrá m, es decir el mensaje original. Tan solo es necesario deshacer el padding.

          Como se pueden ver, en realidad las funciones de encriptado y desencriptado son sencillas. Si quisiésemos llevar esto a un ejemplo real a pequeña escala (con números pequeños):

          a) p = 101, q = 103 -> Ambos números son primos, de longitud similar (aunque números muy pequeños).

          b) n = p x q = 101 x 103 => n = 10403. Phy (10403) = (101 – 1) (103 – 1) => Phi = 10200

          c) 1 < e < Phi => 1 < e < 10200 => e = 13. 13 a su vez es primo y coprimo de 10200. Esto puede comprobarse de forma sencilla gracias al algoritmo de Euclides.

          d) d x e = 1 (MOD Phi (p x q)) => d x 13 = 1 MOD 10200. Esta ecuación se expresa del mismo modo como: d-1 = e MOD Phi. Si se aplica el método extendido de Euclides se puede obtener de forma sencilla la identidad de Bezout. El método de euclides no es más en realidad que ir dividiendo dividendo entre divisor. Una vez se realiza la operación, el divisor pasa a ser dividendo y el resto divisor y se realiza otra iteración, hasta que se obtiene un resto de 1. A cada iteración se le calcula sus dos coeficientes para generar así la igualdad de Bezout. En nuestro caso para la iteración 5 (en la cual el resto es 1) del método extendido de euclides estos son 5 y -3923. calcular estos coeficientes se obtienen por sustitución de las iteraciones anteriores. En la iteración 3 se obtienen los coeficientes sustituyendo en esta la igualdad de bezout obtenida en la iteración una y dos. Las iteraciones una y dos a su vez se conocen de antemano:

          restoi= Combi = Comb (i-2) + Comb (i-1)

          RondaDivndo.Div.CocienteRestoSustituciónCombinaciónCoef. 1Coef. 2
          11020013-10200-10200=10200*1+13*010
          21020013-13-13=10200*0+13*101
          310200137848=10200-13*7848=(10200*1+13*0)-(10200*0+13*1)* -7848=10200*1+13* -7841-784
          413815=13-8*15=(10200*0+13*1)-(10200*1+13* -784)*15=10200*-1+13* 785-1785
          58513=8-5*13=(10200*1+13* -784)-(10200*-1+13*785)*13=10200*2+13* -15692-1565
          65312=5-3*12=(10200*-1+13* 785)-(10200*2+13* -1569)*12=10200*-3+13*2354-32354
          73211=3-2*11=(10200*2+13* -1569)-(10200*-3+13*2354)*11=10200*5+13* -39235-3923
          82120=2-1*20=(10200*-3+13*2354)-(10200*5+13* -3923)*20=10200*-13+13*10200-13

          10200


          Pese a la aparente complejidad, si se presta atención al procedimiento realizado rápidamente se comprende como se ha realizado. Una vez obtenido los dos coeficientes, tan solo nos quedaría que d = Phi + Coef. 2 (Resto 1) => d= 10200 – 3923 = > d = 6277. Si deseamos verificar esto: d x e = 1 MOD (Phi(pxq)) => 6277 * 13 = 1 MOD 10200 => 81601 MOD 10200 = 1. Es decir, se cumple.

          e) Con esto tendríamos la claves privadas y públicas calculadas:

          Clave Privada (n->10403, d->6277), Clave Pública (n->10403,e->13)

          Cabe destacar que todo este proceso de 4 fases es tan solo llevado acabo una sola vez, y estas claves serán las que sean usadas durante meses o años sin ningún tipo de problemas. Una vez se tienen estas dos claves, el resto tan solo es aplicar la función de encriptación o la función de desencriptación. Continuando con el ejemplo imaginemos que quisiésemos encriptar la palabra “Casas”, y que estamos usando un sistema simple de translación de dichos valores a ASCII en hexadecimal. Imaginar también que se tiene un Padding que inserta en el mensaje un valor de “0×01″ cada dos caracteres:

          Mensaje Original: C -> 0×43 a -> 0×61 s -> 0×73 a -> 0×61 s -> 0×73
          Mensaje Con Padding: 43 61 01 73 61 01 73. Es decir, cada dos bytes se incrusta un 01.
          Tamaño de la palabra: 2 Bytes. Es decir, se especifica la cantidad de Bytes que se van a tomar para realizar la codificación, en este caso por ejemplo 2. Es decir, se divide el mensaje con el padding incorporado en grupos de 2 bytes, si el número es impar (como en nuestro caso) se añade un byte más de padding al final para rellenar

          Codificación 1- >4361, Codificación 2 -> 0173 Codificación 3 -> 6101 Codificación 4 -> 7300

          me = Cifrado MOD n ->Se cifrará usando la clave pública. En caso de que se quisiese cifrar con la clave privada, en vez de e se usaría d.

          436113 = Cifrado MOD 10403 => Cifrado = 436113 MOD 10403 = 7905
          017313 = Cifrado MOD 10403 => Cifrado = 017313 MOD 10403 = 6398
          610113 = Cifrado MOD 10403 => Cifrado = 610113 MOD 10403 = 3597
          730013 = Cifrado MOD 10403 => Cifrado = 730013 MOD 10403 = 3217

          En mensaje cifrado por tanto correspondería a la cadena hexadecimal: “79 05 63 98 35 97 32 17“, algunos de esos valores tendrían representación en ASCII y otros no. El proceso de desencriptación sería similar:

          Cifradod = m MOD n

          79056277 = m MOD 10403 => m = 79056277 MOD 10403 = 4361
          63986277 = m MOD 10403 => m = 63986277 MOD 10403 = 0173
          35976277 = m MOD 10403 => m = 35976277 MOD 10403 = 6101
          32176277 = m MOD 10403 => m = 32176277 MOD 10403 = 7300

          Para poder calcular el módulo a tales cifras exponenciales no servirá una calculadora normal, es necesario recurrir a técnicas concretas para el cálculo de módulos a exponenciales. Un buen punto de partida para poder realizar esto sería: AQUI

          Como se puede observar, los resultados obtenidos son exactamente los mismos que los iniciales, la cadena desencriptada correspondería a “43 61 01 73 61 01 73 00″, eliminando el Padding nos quedaría “43 61 73 61 73″ que se traduciría en ASCII de nuevo como “Casa”.

          Según el esquema propuesto se puede ver la necesidad del Padding. El Padding en RSA toma una importancia aun mayor, dado que no solo sirve para añadir al final bytes que puedan faltar para rellenar, sino que es importante incluir ciertos bits o bytes (de forma reversible) en el mensaje original, de este modo RSA se hace resistente a ataques conocidos como “textos específicos”, aunque las vulnerabilidades serán tratados en el último capitulo de este artículo. El Padding debe de ser conocido por todos, no debe de ser un secreto.

          Como se puede comprobar, RSA (o los algoritmos de clave pública en general) no son en realidad complejos por sus funciones, sino por la carga matemática que hay detrás de ellos. Las funciones en RSA para cifrar son muy simples, 4 variables de las cuales se conocen siempre 3 y dos operaciones, una exponencial y otra modular. La seguridad en cambio radica en que es virtualmente imposible obtener a partir de la clave pública la clave privada. Como hemos visto, la clave privada corresponde a la tupla n y d. Mientras que n es también un valor dado por la clave pública, d es calculado desde la clave privada a la hora de generar las claves. El cálculo de ‘d’ se podría intentar, pero como hemos visto anteriormente, d depende de Phi (p x q) y para calcular Phi (p x q) es necesario conocer ‘p’ y ‘q’. Aquí es donde radica el problema de la factorización. Sabemos que n = p x q y es un dato conocido, pero no conocemos el valor de ‘p’ y el valor de ‘q’ necesario para poder calcular Phi y posteriormente ‘d’. Para poder obtener ‘p’ y ‘q’ sería necesaria la factorización de ‘n’, y esto como hemos dicho no es viable. Es computacionalmente sencillo obtener dos primos con un número de bits muy grande. Es computacionalmente sencillo multiplicar dichos primos entre ellos. Y es computacionalmente imposible revertir el proceso y obtener los factores de dicho producto, es un camino solo de ida, si perdiésemos ‘q’ y ‘p’ sería imposible volver a encontrarlos.

          Para aquellos que les pueda interesar RSA, recuerdo bien el programa DisMat, una herramienta para aprendizaje sobre RSA y otras cuestiones igualmente interesantes.

           

          RSA no es el único sistema de clave asimétrica que existe. En la otra cara de la moneda tenemos ElGamal, que está basado en algunas asunciones similares pero en principios diferentes. No voy a detallar el funcionamiento de ElGamal por dos razones. La primera porque honestamente se escapa a los conocimientos matemáticos del redactor (es decir, a mi) y no sería ético buscar información sobre ello y plasmarla aquí sin comprenderla. Y por otro lado, aunque ElGamal es un sistema libre (RSA está patentado), su popularidad es relativa, siendo RSA inmensamente más usado y popular. De todos modos ElGamal si podemos decir que aplica otro principio de la “matemática imposible”, llamado como logaritmo discreto. Lo gracioso es que esto lo hemos visto a menos de pasada dentro de RSA. El problema reside en esta ecuación:

          a = bx MOD n => x = log discretob (a)

          Siendo a, b y n números conocidos y X la incógnita. El problema es poder calcular X. En RSA nos tenemos que enfrentar a esta ecuación, pero en nuestro caso no tenemos que calcular X, tan solo a. En ElGamal, poder obtener la clave privada implicaría resolver dicha ecuación, y esta es imposible de resolver computacionalmente, es decir… en un tiempo razonable, de nada sirve que pueda ser resuelto con un ordenador funcionando durante miles de años.

           

          Los algoritmos de cifrado asimétrico como RSA son extremadamente seguros. El echo de que sea “lentos” comparados a los sistemas de cifrado simétrico hace que normalmente se opte por sistemas híbridos de los que serán tratados en los próximos capítulos. Dado que el potencial de computación es limitado estos sistemas suelen estar a salvo de cualquier posible ataque contra el propio sistema (no implica que no sean vulnerables a otros ataques), pero todos sabemos que la capacidad de cálculo de los dispositivos actuales se incrementa exponencialmente cada año que pasa. Esto significa que cada día que pasa se está un poco más cerca de alcanzar el reto computacional que plantean tanto los cifrados simétricos como AES-256 a cifrados asimétricos como RSA-1024. La ventaja de estos segundos, es que están diseñado para trabajar con longitudes muy superiores, mientras que no sucede lo mismo con los cifrados simétricos. Es probable que dentro de X años, AES-128 sea considerado inseguro, o incluso su sistema sea roto, como en su día lo fue RC4. En cambio encontrar una roptura en sistemas como RSA es harto más complicado.

          Seguridad: Encriptación y Autentificación. Capítulo Primero -> Hash

          ATENCION: Los ejemplos que se van a mostrar y “tutoriales” tan solo tienen carácter educativo. En ningún aspecto comparto filosofías de invasión a la intimidad, ataques contra un sistema informático o cuestiones similares. En la medida que sea posible siempre se usarán ejemplos y formas que puedan ser usados por cualquier persona, de forma que pueda verificar los contenidos escritos. No obstante, por motivos más que obvios, materiales como contraseñas, nombres de usuarios o de hosts, serán omitidos o modificado en las capturas de pantallas realizadas (o las lineas escritas). Es decir, los ejemplos serán completamente reales, los datos mostrados a vosotros necesarios para poder pertrechar estos ejemplos no siempre lo serán (Sí lo serán los resultados). Para que esto conste de forma clara, todo material sensible modificado o falso estará resaltado en ROJO. Por motivos de seguridad, todo el material que sea expuesto aquí (exceptuando software propietario o libre, citaciones expresas o código de terceros) tanto texto, imágenes y código son propiedad del autor y está completamente prohibido su reproducción completa o parcial en otros lugares, espero que se comprenda.

           


          Hash

          A diferencia del Spoofing, si hablamos de encriptación o autentificación se debe de establecer un orden sobre lo que vamos a ir viendo. Esto se debe a que un elemento suele requerir de otro, y este otro de otro… si no se explica adecuadamente cada uno de los elementos, será imposible comprender los que dependan den estos. Y el primero de estos elementos es el hash.

          Un hash podemos definirlo como el resultado de una función matemática aplicada a una entrada arbitraria de datos, de forma que el resultado es (idealmente) asociado únicamente a la entrada dada y siempre obteniendo un resultado de longitud finita y concreta para el mismo hash. Es decir, idealmente para los hash criptográficos sería imposible volver a obtener el mismo resultado con otros datos diferentes. La idea es poder convertir la cantidad de datos que sea en un “resultado” de longitud fija (fijada por el propio hash). Veamos un ejemplo muy sencillo de esto. Imaginar uan función hash que realiza lo siguiente sobre números enteros:

          Hash = numero1 + numero2 + numero3…. MODULO 100

          En dicho ejemplo el hash se calcularía sumando cada numero de entrada dado y se le realizaría la operación Módulo 100. La operación módulo devuelve simplemente el resto de la división, y dado que el divisor es 100, el resto será siempre un número entre 0 y 99:


          n1 = 500 n2 = 100 -> Hash = (500+100) MOD 100 = 600 MOD 100 = 0 Hash = 0 (600/100 = 6 y resto 0)

          n1 = 1250 n2 = 25 n3 = 5460 Hash = (1250+25+5460) MOD 100 = 6735 MOD 100 = 35 Hash = 35 (6735/100 = 67 y resto 35)

          Evidentemente esta función hash sería un tanto absurda desde un punto de vista criptográfico, dado que sería relativamente muy facil obtener el mismo resultado con dos entradas de datos diferentes. Pero sirve para dejar ver más o menos de lo que estamos hablando. En este caso tan solo existen 100 posible resultados, pero se puede observar que si modificásemos cualquier número este podría repercutir en un resultado completamente diferente. Las funciones hash hacen más o menos esto, aunque no con una precisión de 100 posibles valores y de una forma mucho más eficiente, pero la idea es la misma. Pero no solo es útil pensar en criptografía, una función Hash puede tener un valor muy importante simplemente en la detección de errores por ejemplo.

          ¿Para que sirve esto? Tiene una gran utilidad en muchísimos campos. Podemos decir que existen tres tipos de Hash: Hash checksums, Hash CRC y Hash criptográficos.


          CheckSum

          Sería el ejemplo más básico de Hash. El concepto apareció de la necesidad de verificar de algún modo la integridad de la transferencia de los datos. Es decir, si estos se habían transmitido de forma alguna de forma errónea. ¿Pero como podemos verificar esto? Podemos tratar los datos de entrada de tal forma que nos de un resultado, de modo que si el resultado es diferente en el destino, los datos son erroneos. Generalmente un CheckSum es una operación matemática basada en sumas. El ejemplo expuesto anteriormente sería un posible ejemplo de checksum. El ejemplo de checksum más simple es el bit de paridad. Imaginar que sea cual sea el bloque de datos de entrada, se le computa la paridad al dato, y esta se le añade al dato final. El checksums en sí mismo es tan solo un bit, un cero o un uno que corresponde a la paridad del dato inicial. Cuando los datos son recibidos por el destino, el destino calcula de nuevo la paridad del bloque y la compara con la paridad recibida. Si coincide los datos son válidos. Evidentemente este checksum tan solo previene contra 1 posible cambio de valor en uno de los bits transmitidos. Vamos a verlo con un ejemplo:

          Se desea transmitir la cadena “Casa” desde A hasta B. Imaginar que cada carácter es acompañado con un bit de paridad. Un carácter tiene un valor entre 0 y 255 según la tabla ASCII, es decir, un carácter ocupa 1Byte de datos (8 bits). El carácter “C” equivale al código ASCII x43 (43 en hexadecimal), lo que en binario equivale a “01000011″:

          C -> 01000011 -> Se aplica Paridad Par por ejemplo (Hay número par de “unos”? si es asi el resultado es cero, de lo contrario es uno) -> 3 Unos, es impar, bit de paridad par = 1

          C -> 01000011 + bit de paridad -> Datos transmitidos: 010000111

          De este modo, el destino tan solo tiene que tomar los primeros 8 bits y realizar la misma operación. Si el resultado coincide no hay error o no se ha podido detectar. Si no coincide se ha producido un error y los datos no puede tomarse como válidos. En este caso caso, tan solo se podría detectar con un bit un número impar de errores: 1, 3, 5… dado que si se produce un número par de errores el bit de paridad no cambiaría.


          Evidentemente existen Checksums más eficientes, aunque todo depende del uso que se le haga. En cambio todos los días tratamos con este tipo de sistemas, y no hay que profundizar siquiera en la informática. En la mayoría de datos personales que puedan ser sensibles, suele existir un carácter o caracteres de control que verifican que los datos introducidos son válidos. Por ejemplo la letra de nuestro DNI no es más que un checksum, que se obtiene aplicando un módulo 23 al número de la división. Al resultado (entre 0 y 22), se le asigna una letra ya espeificada. Por ejemplo, el Cero es la letra T, el tres es la letra A… de tal forma que si damos o introducimos nuestro DNI de forma incorrecta, es posible verificarlo simplemente comprobando la letra proporcionada y ver si coincide con la que debería de ser. A este ejemplo se le suman los carácter de control de los números de cuenta corriente, de otros datos del DNI, número de la seguridad social… es una forma simple y efectiva de detectar con prontitud cualquier error en los datos tomados.

          Otro uso increíblemente extendido es en la verificación de datos en sí mismos, no solo en la transferencia de estos. Así por ejemplo, si se quiere disponer de algún tipo de archivo que pueda tener datos relativamente sensibles como bios, firmwares, datos personales… lo normal es ir aplicando checksums a determinadas partes del archivo incrustando este mismo en las diferentes partes del archivo. De este modo, el software a medida que va procesando el archivo puede ir verificando cada bloque para asegurarse de que el archivo es confiable. Pensar en una bios que se quiere actualizar y por cualquier motivo existe un error en uno solo de sus bits. Es suficiente para que el PC no arranque. Para evitar esto, se distribuye por toda la bios checksums que van verificando bloques menores,

          Su uso no obstante se ha ido reduciendo con la aparición de los Hash CRC, los cuales suelen realizar operaciones similares pero de una forma mucho más efectiva. No obstante para pequeños bloques de datos o comprobaciones sencillas suele ser más fácil y barato de implementar Checksums. Entre los Checksums más habituales encontramos Sum8, Sum16, Sum32 o Sum64.


          CRC

          Se traduce como comprobación de redundancia cíclica. Su objetivo y uso es muy similar al del checksum, de tal modo que no es raro ver lugares en los cuales el nombre de CRC no es más que un tipo de checksum. La necesidad de la verificación de los datos es algo de suma importancia, siendo quizás su máximo exponente la firma digital, de la cual ya hablaremos de ella. Pero no solo la detección de errores es necesaria, a veces es necesaria también la corrección de estos. Aunque un checksum puede usarse para esto, es más normal ver este tipo de correctores como CRC. Aun así, los sistemas de corrección de errores suelen ser costosos en cuanto a rendimiento, precio, implementación… tanto que normalmente no compensa, y es mucho más eficiente simplemente un buen sistema de detección, y si la detección es erronea simplemente se retransmiten de nuevo los datos. Si bien los checksums pueden ser una herramienta muy extendida dentro de los propios archivos, los CRC suelen ser usado de forma mucho más extensa en la transmisión de datos, aplicado normalmente a bloques de datos de un tamaño mayor.

          El peor escenario que puede darse en una transmisión de datos o en un error en un archivo, es que este no pueda detectarse, haciendo que los datos sean enviados o procesados como legítimos. Y es esto lo que se debe de evitar a cualquier precio. Por ello, los CRC son usados intensamente en la transmisión de datos sobre internet, telefonía… y por supuesto en la integridad de los datos en un disco duro, CD, pendrive y otros dispositivos. Cuando hablo aquí de integridad no me estoy refiriendo a sistemas de checksums que puedan estar implementados en la misma estructura del archivo, sino sistemas de ingreidad que poseen los propios dispositivos. Gracias a la integración hardware y la simplicidad de como opera un CRC (la mayoría de ellos), la gran mayoría de nuestro hardware implementa funciones CRC en él mismo, sin necesidad de un software. Es decir… todo el proceso es transparente a nosotros.

          El funcionamiento de un CRC es simple. A un bloque de entrada se le añade primero los bits correspondiente al CRC, y el nuevo bloque se divide por un polinomio preestablecido. El resto de dicha división binaria será el CRC. Dicho CRC se añade al bloque original y se retransmite. El destino tomará el bloque y lo dividirá por el polinomio generador (que será el mismo que usó el emisor). Si el resto es cero, no hay error de transmisión, o al menos no hay error detectable. La eficiencia radica por lo cual en el polinomio generador usado y evidentemente en el número de bits usados para el CRC. El caso más simple de CRC sería el bit de paridad, que correspondería a un bit de CRC tan solo, y el polinomio generador sería X + 1, el cual se traduciría como “11″ como divisor del mensaje de entrada. Un polinomio generador tal como X5+X4+X+3 se traduciría por lo tanto como “110011″ y se tendría un CRC de 6 bits.

          Aun en los CRC-32, no se puede considerar CRC un hash seguro, no está pensado como resultado único de una posible entrada ni como sistema de ocultación o cifrado de datos, sino como un sistema robusto de detección de errores, y francamente, hace su trabajo a la perfección. Gracias a este tipo de funciones hash, a día de hoy disponemos de medios de comunicación fiables y con una gran tolerancia a fallos. Que no apreciemos este tipo de tecnologías, no implica que las estemos usando constantemente. Para hacernos una idea de la eficiencia de los CRC, un CRC-16 tienes el siguiente índice de detección:

          • Detección del 100% de errores simples (errores que afectan tan solo a un bit)
          • Detección del 100% de errores dobles de bits adyacentes (Si dos bits consecutivos son erróneos)
          • Detección del 100% de los errores para datos de hasta 16 bits.
          • Detección del 100% de todos los errores de dos bits que no estén separados uno del otro exactamente a 216-1 bits
          • Para el resto de posibles errores, se establece tan solo una no detección en un fallo de cada 216

          Es decir, un cRC-16 sería capaz de detectar aproximadamente el 99.995% de todos los errores. ¿Esto es mucho o es poco? Esto equivale a que cada 20.000 errores, uno no se detecta. Teniendo en cuenta las comunicaciones ultrarápidas de hoy en día, la cantidad de información que es manejada en segundos es simplemente impresionante, por lo cual podemos afirmar que de cuando en cuando efectamente aparecerán errores no detectados. Esto se subsana también gracias a la fiabilidad cada vez mayor de las propias redes, con menos ruido, con mejores equipos…

          Los CRC más comunes son CRC8, CRC16, CRC32… aunque si se desea ver una lista de ellos con sus polinomios generadores tan solo hay que acudir a la Wikipedia, por ejemplo.


          Criptografía

          En realidad son los Hash que nos van a interesar a nosotros. Este tipo de hash se usan ya no solo como detectores de errores (que pueden valer para ello también). Este tipo de Hash, al igual que los que hemos visto, es u procedimiento determinista que devolverá un resultado de una longitud fija. Pero a diferencia de los CRC o checksums en los que su objetivo principal es la detección de errores, la función de un hash criptográfico va mucho más allá:

          • La imposibilidad de poder encontrar una cadena (un bloque de datos…) cuyo resultado sea un hash dado.
          • La imposibilidad de modificación de la cadena inicial, sin modificar el hash.
          • La imposibilidad de encontrar una segunda cadena que verifique un hash de otra cadena.
          • Un hash que sea computacionalmente eficiente y facil de implementar.

          Hay que comprender que con imposibilidad no podemos asegurar que sea imposible, sino que el coste computacional para ello sería tan ingente que de ninguna forma sería factible. Esto evidentemente no es más que la teoría, en la práctica todo no es tan simple.

          A diferencia de los CRC o los checksums que pueden comprenderse sin muchas nociones de matemáticas y parten de unos conceptos simples, los hash criptográficos son bastante más complicado de comprender (las matemáticas escondidas detrás de ellos). Cada algoritmo hash tiene sus propios fundamentos, basados en premisas diferentes, siempre intentando cumplir cada una de las premisas dadas. No obstante podemos citar los Hash criptográficos más usados a día de hoy, como pueden ser: MD4, MD5, RIPEMD, SHA-1, SHA-256, SHA-512. Por supuesto existen muchos otros, aunque menos usados. Posiblemente a muchos algunas de esos nombres les sea conocido.

          Al cumplir las premisas citadas, los Hash criptográficos suelen ser usados de forma intensiva en los siguientes campos:

          • Comprobaciones de archivos
          • Firmas digitales
          • Tablas Hash
          • Integridad de un mensaje/contenido


          Dado que un Hash puede ser usado para detectar errores en el envío y/o recepción de los datos, un Hash criptográfico puede ejercer función de Comprobador de archivos. Mientras que CRC o checksum suelen aplicarse normalmente a porciones de código, tramas en las comunicaciones, pequeños detectores… este tipo de hash en realidad no se diseñan como correctores de errores o para que el contenido sea reenviado si no es correcto. Este tipo de Hash se suelen aplicar sobre un archivo completo (o conjunto de ellos). Para estos Hash, no importa lo grande o pequeño que sea el dato a verificar (pensado especialmente para grandes cantidades de datos en comparación con CRC o checksum claro está).

          Comprender su función en este caso es simple. Al contenido original se le apluca un Hash criptográfico el cual se adjunta al software/archivo original. Cuando el receptor lo descarga, tiene acceso a él… solo tiene que calcular el mismo el mismo Hash y comprobarlo con el Hash que ha sido descargado desde la fuenta original. La idea es que sl el hash es el mismo, tenemos la certeza de que el archivo no se ha corrompido por el envío y la recepción ha sido satisfactoria. Por un principio similar, se puede verificar la integridad y veracidad de dicho archivo, que no ha sido modificado por nadie, que es legítimo. Podemos afirmar esto dada las propiedades ya vistas de este tipo de Hash: La imposibilidad de poder encontrar o crear otro archivo que pudiese coincidir con el hash del archivo original, y por otro lado no sería posible modificar el contenido del archivo sin alterar el hash que se calcularía en el destino.

          Ver esto es muy fácil con algunos ejemplos. Tan solo tenemos que buscar un software que sea distribuido por razones de seguridad con su hash. En este caso vamos a usar por ejemplo la imagen de Windows 7 x64 Ultimate ENG. Imaginad que no te quieres molestar en ir a la tienda y encuentras un vendedor supuestamente autorizado que te permite descargar una copia de la imagen de Windows 7 (la misma que he expuesto ahi). Pero claro… quieres asegurarte de que la imagen sea legítima, y no sea una imagen modificada a la que se le haya puesto una activación o algún crack para poder instalarla. Solución? Conocer el Hash de la imagen legítima. Me pongo en contacto con Microsoft o investigo un poco para conocer el Hash de la imagen original y lo que obtengo es lo siguiente:

          Windows 7 Ultimate x64 ENG: 7600.16385.090713-1255_x64fre_client_en-us_Retail_Ultimate-GRMCULXFRER_EN_DVD.ISO
          MD5: F43D22E4FB07BF617D573ACD8785C028
          SHA-1: 326327CC2FF9F05379F5058C41BE6BC5E004BAA7

          Lo único que se debe de hacer en este caso es verificar si los valores que yo obtengo al calcular el hash son esos o difieren. En teoría con el cálculo de uno de ellos es suficiente. Para hacer esto se puede usar por ejemplo la utilidad md5sum sha1sum:

          E:\Windows 7 Ultimate Final (EN-DE-JP-AR)>md5sum 7600.16385.090713-1255_x64fre_client_en-us_Retail_Ultimate-GRMCULXFRER_EN_DVD.iso
          f43d22e4fb07bf617d573acd8785c028 *7600.16385.090713-1255_x64fre_client_en-us_Retail_Ultimate-GRMCULXFRER_EN_DVD.iso

          E:\Windows 7 Ultimate Final (EN-DE-JP-AR)>sha1sum 7600.16385.090713-1255_x64fre_client_en-us_Retail_Ultimate-GRMCULXFRER_EN_DVD.iso
          326327cc2ff9f05379f5058c41be6bc5e004baa7 *7600.16385.090713-1255_x64fre_client_en-us_Retail_Ultimate-GRMCULXFRER_EN_DVD.iso

          Si dicha imagen hubiese sufrido cualquier tipo de modificación el resultado sería muy diferente. Por ejemplo, si a la imagen le modifico simplemente el primer bit (que es un “cero”, y lo establezco a “uno” con un editor hexadecimal) y le recalculo el hash MD5, esto es lo que obtengo:

          4420bc0022a2ca8a361111b7a4d24ea7

          Es decir, modificando tan solo un bit, el hash es completamente diferente. Por los mismos principios sería en la práctica imposible modificar aleatoriamente (o a conciencia) los bits de forma que pudiese obtener el mismo hash. Y he dicho en la práctica por una razón concreta que ahora veremos.

          Vamos a suponer el caso concreto del Hash MD5. El Hash MD5 es un hash de 128 bits, lo que significa que cualquier contenido al que se le aplique este hash, se obtendrá una salida de 128 bits, una cadena de 32 caracteres hexadecimales. Es decir, sin entender siquiera de paradojas o estadística, podríamos afirmar que podríamos obtener un máximo de 2128 posibles hash. Esto es un número un tanto ingente, tanto que posiblemente una mente no es capaz de cuantificar, hablamos de 3.4 * 1038 es decir… 34 con 37 ceros a su derecha. Pero aun cuando este número es mentalmente imposible de imaginar, si es posible de imaginar que en el peor de los casos, cada ese número de hash calculados estos se volverán a repetir, lo cual implica evidentemente que sería teóricamente posible encontrar dos archivos exactamente con el mismo hash. Esta afirmación en realidad no rompe los esquemas vistos, dado que no se “rompe” la veracidad al decir que es improbable modificar un archivo para obtener un hash concreto o encontrar ese segundo archivo que verifique dicho hash. Aunque teóricamente esto es posible, aun cuando solo fuese de forma estadística.

          Este es por tanto uno de los principales problemas de los hash criptográficos, y a esto se le llama colisión. Al margen de lo bueno o malo que sea el Hash, estadísticamente es posible encontrar dos hash iguales. En este caso concreto visto, aunque es posible teóricamente, en la práctica si el Hash está bien diseñado sería imprácticable. Cuanto tiempo necesitaría un PC en ser capaz de encontrar una colisión? Pues haciendo números muy por encima… 15 * 1010 años en el supuesto de que toda la población mundial tenga un procesador de 4 núcleos trabajando al mismo tiempo en la misma tarea 24 horas al día. Es decir… en el peor de los casos sería virtualmente imposible.

          El problema es que esta lógica no es así. Cuando se habla de una colisión en un hash hay que recordar la llamada “Paradoja del cumpleaños”. Cabe señalar de nuevo que es muy diferente encontrar un contenido que verifique un hash concreto a encontrar dos contenidos disferentes que posean un mismo hash. Lo segundo es una colisión. Es cierto que para el primer caso la probabilidad sería la ya citada, pero no para el segundo caso, y aquí aparece lo que puede parecer increible: La paradoja del cumpleaños establece que en una habitación con 23 personas, existe un 50% de probabilidad de que dos personas cumplan años el mismo día, y si fuesen 60 personas la probabilidad sería del 99%. No hay truco, simplemente se busca una coincidencia entre cualquiera de las 23 personas, no una coincidencia concreta dentro de las 22 restantes. Teniendo esto en cuenta, MD5 posee tan solo 232 posibilidades de encontrar una colisión. Es decir, 4294967296 hash calculados de 4294967296 archivos aleatorios, estadísticamente debería de existir alguna colisión, es decir, dos archivos diferentes que poseen el mismo hash. Y es evidente que este número si que es comprensible y relativamente bajo, dado que un PC normal podría generar colisiones de hash MD5 con relativa facilidad, y esto comenzaría a invalidar los puntos en los que se asienta un Hash criptográfico. Es por esto que MD5 ha dejado de considerarse un Hash seguro, y es solo cuestión de tiempo que quede en desuso, a favor de otros Hash más seguros.

          En teoría cualquier Hash debería de presentar posibilidad de Colisión, aunque es evidente que si esta probabilidad es computacionalmente imposible, podemos afirmar que no existe colisión (aunque teóricamente exista). Para tener presente esto, pensar que al Hash MD4 es posible encontrarle colisiones con tan solo en 256 hash.

          A raiz de las Colisiones, aparecieron las primeras herramientas que han empezado a romper del todo el Hash MD5. A día de hoy existen herramientas capaces de generar dos programas diferentes que satisfagan el mismo Hash MD5, con lo que se rompe la seguridad de MD5 para la verificación de integridad y comprobación de un contenido. Es evidente que esto tiene matices. A día de hoy continua siendo imposible generar un contenido nuevo que satisfaga un hash buscado (lo cual rompería de forma definitiva el Hash). Pero en cambio si es posible producir dos archivos o dos contenidos que satisface el mismo hash. Esto quedó de manifiesto por el doctor Xiaoyun Wang, el cual incluso liberó el código de una aplicación que es capaz de realizar esto (En la cabecera de este artículo se puede encontrar)

          SHA-1 es el segundo Hash más usado a día de hoy. A diferencia de MD5 (aunque basado en sus mismos principios) es un hash de 160 bits, al cual se le ha podido establecer un índice de colisiones de 252 en el mejor de los casos. En dicho caso el cálculo de una colisión sería relativamente práctica de llevar a acabo, quizás un año o dos años en poder lograr encontrar dos contenidos que compartan el mismo hash. No obstante se le continúa considerando seguro.

          SHA-2 (conocidos como SHA256 y SHA-512) funcionan de forma muy similar a SHA-1, anque en este caso producen salidas de 256 y 512 bits respectivamente. En ambos casos no se conocen colisiones posibles.

          Ante todo esto y dado que podemos asumir que tanto MD5 o SHA-1 son algo así como estándares, ya está en marcha el nuevo “concurso” que será seleccionado como sucesor de SHA-1/SHA-2 y que posiblemente será el próximo estandar en Hash dentro de un par de años. Actualmente se ha comenzado la segunda ronda, y a final de este año debería de quedar todo más o menos finalizado. La idea es encontrar un Hash más seguro y que sea muy eficiente su cálculo ,es decir… la velocidad con la que se pueda calcular el hash a un contenido. Se puede acceder a una lista de todos los candidatos de la segunda ronda en la web oficial del NIST (Instituto nacional de estándares y tecnología)

           

          El último uso que deberíamos explicar son las Tablas Hash. Antes de entrar en detalle sobre este tipo de prácticas sería más correcto hablar antes de la Sal o Salt (en inglés). Hasta ahora hemos visto funciones de los Hash criptográficos para comprobar la integridad de los archivos, pero ¿que sucede si queremos usar un Hash como una especie de “encriptador” de contenido? Esto podría no tener mucho sentido dado que cualquier persona puede calcular un hash MD5 por ejemplo a cualquier entrada… pero en cambio no es posible partir del hash para obtener el contenido. Esto adquiere mucha más relevancia cuando se usan un hash para proteger detrás de él un contenido pequeño como un nombre de usuario o una contraseña, y es aquí donde aparece el término y la idea de Salt. Salt es un apéndice que se añade a una cadena de entrada para generar un Hash no intuituvo

          Dentro de la web, las cookies y otros contenidos que puedan ser sensibles de cara al exterior como nombres y contraseñas puede ser sometido a un hash criptográfico para esconder su “significado” original. Esto nos dará como resultado una salida “única”, con lo que se podría usar dicha salida como contraseña y nombre del usuario de cara a un servidor, en vez del texto plano. Esto incrementa de forma exponencial la seguridad de cualquier base de datos o sistema de control de acceso. Pero como hemos dicho la utilidad de esto podría ser relativa. Vamos a ver esto con 3 ejemplos que ilustrarán la eficacia o no eficacia de un Hash para estos procesos, así como la implicación de Salt:

          Imaginemos que hemos robado un archivo que guarda las credenciales de acceso a una importante base de datos. Imaginemos que dichas credenciales pueden ser almacenadas en dicho archivo como texto plano, MD5 y MD5+Salt. Si abrimos ese documento encontraríamos esto para cada una de las opciones:

          1º. Nombre: Theliel Contraseña: perico

          2º. Nombre: 5A04B2D961488CDA31CD065F259783BE Contraseña: DFE483413E24A5B1506389D36EBFD05C

          3º. Nombre: 217B11413677EE9D4806967515D66607 Contraseña: 8E50E5A474DDAF3BC370F87DD97EC7F0

          En el primer caso, es evidente que si está configurado como texto plano, las credenciales serán tomadas de forma directa y rápidamente podremos acceder a la base de datos.

          En el segundo caso no obstante n oparece que sea posible descifrar absolutamente nada… ¿pero que pasaría si hacemos uso de la inteligencia? Podemos intuir que es un hash, y si buscamos información del sistema podemos incluso conocer que se trata de un Hash MD5. No podemos revertir el MD5 (a priori), pero en cambio si podemos presuponer el nombre de usuario y ver si hay una coincidencia con el hash que tenemos. Dado que el atacante es listo, comenzaría por cotejar en un diccionario que ya tiene el hash. Su diccionario no es más que una lista precalculada con quizás millones de posibles nombres de usuarios a los que ya se les ha calculado el hash correspondiente. Si el hash se encuentra en su diccionario, obtendrá de forma automática le nombre de usuario. Esto mismo se puede aplicar a la contraseña. Que usuarios se probarán primero? Admin, admin, theliel, Theliel… y en este caso, el diccionario encontraría que dicho hash corresponde a la palabra “Theliel”. En caso de la contraseña es exactamente igual, si la palabra o frase empleada en la contraseña existe en su diccionario, obtendrá directamente la contraseña buscada. Es por ello que siempre es importante tener una contraseña alfanumérica de una longitud decente.

          En el tercer caso la cosa es más complicada. El atacante agotaría todos sus diccionarios y no lograría encontrar el hash deseado. ¿Por qué? Porque lo que no sabe el atacante es que el programa que codificó el hash usó una Salt, un trozo de datos que simplemente añadió al final del usuario y la contraseña. Así si el usuario escribió el nombre de usuario: “Theliel”, el servidor jamás lo tomó como tal, sino que automáticamente le añadió el Salt “TATA” (en este caso). Es decir, de cara al servidor cualquier dato introducido es concatenado con “TATA”. Así, el servidor no calcularía el hash de “Theliel” o de “perico” (la contraseña), sino de “ThelielTATA” y “pericoTATA”. dicha modificación es seguro que no aparecerá en su diccionario. La única opción del atacante es conocer la Salt usada por dicho servidor, y crear así un programa que automatice el proceso, recalculando todos los hash de su diccionario con la Salt aplicada y así con suerte obtener algún resultado. Esto lo trataremos mejor cuando se vean las diferentes técnicas para romper la seguridad.

          Pero volvamos a las tablas Hash. Hemos explicado que la Salt o la importancia que puede tener un hash para “esconder” unos datos, pero ¿qué es una tabla hash? Dado que el índice de colisiones es relativamente alto, podemos presuponer que no será posible dar la casualidad de tener a dos nombres de usuarios que compartan el mismo hash. Si esto es cierto, para un servidor es mucho más seguro no guardar jamas en sus bases de datos el usuario o la contraseña como tal, solo sus Hash. Al introducir los datos el usuario, son sus hash los que alcanzan el servidor y este simplemente tiene que cotejar dicho hash (el usuario) en su base de datos para comprobar si existe una coincidencia. Si existe tal coincidencia verificar el hash de la contraseña con el hash de contraseña ya almacenado. De este modo nuestros datos de sesión no serían jamás enviados como tales. Pero la utilidad de las tablas de hash radica no en la seguridad (que por supuesto también lo es) sino su eficiencia.

          Hemos dicho que el servidor debería de verificar si el hash de nombre de usuario existe en su base de datos. ¿Pero como hace esto? Si nuestra base de datos posee 100 registros, en el peor de los casos la base de datos debería de hacer 100 comprobaciones, para acabar en el último registro que sería el que coincidiese con el hash del usuario introducido. Pero aun, si el usuario introducido no se encontrase en la propia base de datos, esta la habría recorrido entera buscando una coincidencia. Este proceso sería muy costoso para los servidores. Ahora bien, partimos de la premisa que el índice de colisión de un hash MD5 es relativamente alta, 4 mil millones aproximadamente. Podríamos calcularle simplemente el módulo a dicho Hash (en función del número de índices que tengamos en la base de datos), el resultado sería un número de 1 a X, siendo X el número de entradas posibles en nuestra base de datos. Es decir, pongamos que nuestra base de datos tiene 100 registros insertados y tiene una capacidad máxima de 997 (por ser un número primo). Es decir, se aplicaría la operación módulo 997 a cada hash de entrada. Esto convertiría todos los hash de entrada en un número que iría desde el 0 al 996. Este número sí podría ser usado como índice, luego el acceso al registro en la base de datos sería inmediato. Por razones de precisión, usar un número de 128 bits no es aconsejable, lo normal es acotar este número a una resolución de 64bits, tomando por ello los 64 bits primeros del hash o los 64 bits últimos de este. En el ejemplo anterior, al Hash “Theliel” se le aplicaría módulo 997, y el resultado sería: 5A04B2D961488CDA31CD065F259783BE -> 5A04B2D961488CDA MOD 997 = 763. Es decir, que el nombre de usuario Theliel sería convertido al índice 763 en la base de datos. De este modo, al introducir “Theliel” en el navegador, se calcularía el Hash, en el servidor se truncaría y daría como resultado un índice. Con este índice el acceso a la base de datos sería directo, “Acceso a elemento 763″. Asociado a dicho índice se podría encontrar por ejemplo el hash de la contraseña y se procedería a realizar una simple comparación, si los dos hash coinciden se obtiene el acceso.

          Esto evidentemente multiplica exponencialmente la posibilidad de una colisión, dado que el espacio disponible ahora es de tan solo 997 elementos. Como hemos dicho la posibilidad de colisión dependerá en gran medida de la ocupación del espacio disponible. Por la paradoja del cumpleaños no obstante, se daría el caso que con unos 35-40 elementos introducidos la probabilidad de una colisión sería de un 50%!!. Para evitar esto se acude a tablas muco mucho mayores en relación al indice esperado de ocupación que se tendrá. Es decir, se sacrifica espacio en post de velocidad. En la Wikipedia aparece un ejemplo parejo, en el que se dice que con 2500 elementos introducidos en una tabla de un millón de elementos, la probabilidad de colisión ascendería al 95%. Que hacer en caso de colisión? Primero evitarlas, ya sean con grandes tablas o con crecimiento dinámico de estas. Por otro lado asumir que es posible que exista una colisión, y diseñar el sistema de forma que ante una colisión sea necesaria una segunda búsqueda en los registros afectados para determinar el destino final.

          Seguridad: Spoofing. Índice (Actualizado)

          Bienvenidos al tema de Hoy: Spoofing, el arte del engaño.

           

          Spoofing es un término genérico que puede ser aplicado a un buen número de cuestiones en la red. Todos ellos comparten la misma premisa, por tanto podemos definir el Spoof o la técnica de Spoofing a la falsificación de unos datos, modificándolos de algún modo para obtener por ello un beneficio.

          Lo que vamos a intentar hacer aquí es explicar los diferentes ataques de Spoofing que podemos encontrar a día de hoy, intentando mostrar ejemplos de uso real y por tanto como podemos evitarlos:

          Herramientas Utilizadas/Material necesario: (No todo es necesario, dependiendo de la plataforma a usar, de cada Spoofing y de lo que a cada cual le sea más cómodo)

          • Windows 7 x64 Ultimate -> OS principal (General)
          • Debian Squeeze x64 -> OS secundario (General)
          • Firefox 3.7a2pre
          • Thunderbird 3.2a1
          • Servidores Whois RIPE, ARIN, APNIC, LACNIC, afriNIC -> También útil usar la linea de comando “Whois” (IP Spoofing)
          • Servidor Proxy anónimo con soporte SSL -> Cientos en Internet (IP Spoofing)
          • NMAP -> Escaner de puertos (IP Spoofing, MAC Spoofing)
          • Winpcap -> Librerías para Windows para capturar frames (IP Spoofing, MAC Spoofing, Header Spoofing)
          • Wireshark ->Sniffer (IP Spoofing, MAC Spoofing, Header Spoofing)
          • Cuenta de Correos Gmail (IP Spoofing, eMail Spoofing)
          • Cuenta de Correos Live/Hotmail (eMail Spoofing)
          • AirCrack Suite (Linux) (MAC Spoofing)
          • Servidor Web con soporte PHP o hosting con iguales características (Web Spoofing)
          • Cliente FTP: WinSCP, FileZilla… (Web Spoofing)
          • Web Spider: HtTrack, wget… (Web Soofing)
          • Apache, PHP (Web Spoofing)
          • NoScript, Cookie Monster, Firebug-> Extensiones para Firefox (Web Spoofing)
          • User-Agent Switcher, Firebug-> Extensión para Firefox (Header Spoofing)
          • Paros Proxy (Header Spoofing)
          • Ncat (incluido en NMAP) ó NetCat, Telnet… (eMail Spoofer)
          • OpenSSL (eMail Spoofer)
          • hMailServer (eMail Spoofer)
          • Dig (eMail Spoofer)

           

          Sobre SMS Spoofing, he decidido posponerlo conjuntamente con la versión PDF. Continuaré con la publicación de artículos, y posiblemente sea al final cuando revise todo el material, lo compacte, lo ordene… y lo lance todo como dios manda.

          Volver a arriba

          Sobre Mí

           
          Creative Commons License
          Alma Oscura por Theliel is licensed under a Creative Commons Reconocimiento-No comercial-Sin obras derivadas 3.0 Unported License.
          Basado en el trabajo de blog.theliel.es.
          Para otros permisos que puedan exceder el ámbito de esta licencia, contactar en blog.theliel.es/about.