domingo, 2 de noviembre de 2014

Ataque de inyección CCS con MITM en OpenSSL (CVE-2014-0224)

Todavía no nos hemos recuperado del susto del Heartbleed cuando aparece una nueva vulnerabilidad crítica en OpenSSL (CVE-2014-0224). Parece que se está poniendo de moda las vulnerabilidades en las librerías de cifrado. En este caso se trata de combinar un ataque de Man-in-the-Middle (MITM) con una inyección de paquetes CCS para renegociar los atributos de seguridad de la conexión segura.
openssl-logo
Bien es cierto que para que el ataque tenga éxito, tanto el cliente como el servidor han de ser vulnerables. Parece ser que todos los clientes OpenSSL son vulnerables, y los servidores los de la versión 1.0.1, además el atacante tiene que estar en disposición de poder hacer un MITM. Hoy en día con las redes WiFi disponibles en bares, restaurantes, hoteles o aeropuertos esto es más probable que hace 10 años.
¿Cómo se realizaría el ataque?
Las sesiones SSL/TLS se inician con los mensajes de ClientHello y ServerHello desde ambos lados de la conexión, similar al handsake en las conexiones TCP/IP. Durante esta parte del protocolo se negocian los atributos de la sesión como por ejemplo las claves de cifrado o protocolo de cifrado.
Por alguna razón, el cliente o el servidor puede modificar la estrategia de cifrado de la conexión durante la etapa del handshake. Esto es posible gracias al ChangeCipherSpec (CCS), que consiste en paquetes enviados entre cliente y servidor para informar que los siguientes registros de la conexión estarán protegidos bajo otras especificaciones de cifrado y claves.
ChangeCipherSpec
El mensaje CCS se envía durante el handshake, después de que los parámetros de seguridad han sido aceptados pero antes de verificar si se ha enviado el mensaje de “Finalizado”.
Ante este escenario un atacante podría esperar a una nueva conexión TLS, seguido de los mensajes ClientHello y ServerHello. A continuación emitir un paquete CCS en ambas direcciones provocando que OpenSSL use una clave maestra con longitud cero, obligando a que las claves de sesión usen una longitud cero, así como las futuras claves de sesión, extrapolando la debilidad de la sesión durante toda la conexión. Una vez renegociados los parámetros del handshake, el atacante podrá descifrar y modificar los paquetes que pasen por sus manos.
OpenSSL ya ha corregido esta vulnerabilidad (CVE-2014-0224) cambiando la forma en la que los paquetes CCS son recibidos y no permitiendo longitudes cero como valores de las claves maestras.
Espero que os sirva de ayuda para entender mejor en qué consiste la vulnerabilidad y hasta que punto nos puede afectar.
Hasta la próxima!

Informacion tomada del sitio web: 

http://hacking-etico.com/2014/06/05/ataque-de-inyeccion-ccs-con-mitm-en-openssl-cve-2014-0224/

toda la información presentada en este articulo es propiedad de Miguel A. Arroyo, @Miguel_Arroyo76


Introducción a sockets en python




Hola a todos los que aun siguen este pequeño blog olvidado, espero inyectarle un poco de vida a este blog con nuevas entradas, en esta ocacion explicare un poco lo que son los sockets en python y haremos unos pequeños scripts en python de un cliente y servidor, los cuales enviaran y recibirán instrucciones, en pocas palabras cadenas de textos.


Sockets

De acuerdo con wikipedia los sockets son un concepto abstracto por el cual dos programas (posiblemente situados en computadoras distintas) pueden intercambiar cualquier flujo de datos, generalmente de manera fiable y ordenada.

El termino socket es también usado como el nombre de una interfaz de programación de aplicaciones para la familia de protocolos de internet TCP/IP, provista usualmente por el sistema operativo.
Los sockets de internet constituyen el mecanismo para la entrega de paquetes de datos provenientes de las tarjetas de red a los procesos o hilos apropiados. Un socket queda definido por un par de direcciones IP local y remota, un protocolo de transporte y un par de números de puerto local y remoto.



El modelo de programación distribuida que sería popularizado por el API de sockets era el modelo cliente/servidor, en donde hay un servidor y un grupo de clientes. Los clientes envían mensajes al servidor pidiéndole que haga trabajo en su nombre, esperan que el servidor realice el trabajo pedido, y en algún momento posterior reciben una respuesta. Hoy en día este modelo computacional es tan utilizado que a menudo es el único modelo con el que muchos ingenieros de software están familiarizados. Sin embargo, en el momento que fue diseñado, era visto como una manera de extender el modelo de I/O de Unix a través de una red. Otro factor que llevó al API de sockets hacia el modelo cliente/servidor fue que el protocolo más popular que soportaba, TCP, era un modelo comunicacional 1:1.
El API de sockets hizo que el modelo cliente/servidor fuera fácil de implementar, porque el programador podía usar una pequeña cantidad de llamadas de sistema y agregarlas a su código existente ("desconectado") para aprovechar otros recursos computacionales. Aunque era posible usar otros modelos, el API de sockets hizo que el modelo cliente/servidor dominara al mundo de las redes.

Programando los sockets
Ahora que ya sabemos que son los sockets, explicare mediante un ejemplo sencillo como programarlos en python, la forma de explicacion sera como habitual mente se hace en este blog, colocare el codigo y seguidamente explicare cada una de sus sentencias para que el lector pueda entender claramente el codigo, bueno comencemos.
script cliente:
1.-  #!/usr/bin/python
2.-  import socket
3.-
4.-  sock = socket.socket()
5.-  sock.connect((“localhost”, 5000))
6.-
7.-  while True:
8.-           mensaje = raw_input(“#>”)
9.-           sock.send(mensaje)
10.-          if mensaje == “exit”:
11.-                    break
12.- print “Bye”

13.- sock.close()



En la linea 1 colocamos el shebang para el interprete de python en gnu/linux:

          #!/usr/bin/python

En la linea 2 se encuentra la importacion del modulo socket, para el manejo de sockers en python
          import socket

En la linea 4 se encuentra la instanciacion del objeto socket en la variable sock

          sock = socket.socket()

En la linea 5 realizamos la conexión con el servidor, la sentencia connect, esta compuesta de una tupla que pide como parametro el host y el puerto del servidor para realizar la conexión, en este ejemplo usaremos como host el localhost, que para el despistado el localhost es nuestro propio ordenador que igual es representado por 127.0.0.1, y utilizaremos el puerto 5000, para el que no sabe esto la cantidad maxima de puestos logicos en un ordenador es de 65535 puertos, pero eso ya es otro tema que abordaremos en una entrada relacionada con redes o sistemas operativos.

          sock.connect((“localhost”, 5000))

En la linea 7 iniciamos un bucle infinito mediante la sentencia while y el valor booleano True con el fin de poder repetir indefinidamente las sentencias siguientes.

          while True:

En la linea 8 inicializamos la variable mensaje con el valor de retorno del metodo raw_input, el metodo raw_input retorna el buffer de entrada, que podrian ser datos del teclado.

          mensaje = raw_input(“#> ”)

En la linea 9 utilizamos en metodo send del modulo socket el cual anteriormente inicializamos, la finalidad de este metodo es enviar datos por la conexión del socket hacia el servidor, asi que enviaremos la variable mensaje

          sock.send(mensaje)

En la linea 10 y 11 se encuentra la condicion if que determinara si la variable mensaje es igual a “exit” si en dado caso lo es se ejecuta la sentencia break que rompe el bucle infinito y termina el programa.

          if mensaje == “exit”:
                    break

En la linea 12 se encuentra la sentencia print que enviara un mensaje de Bye si se concluye el while

          print “Bye”

En la linea 13 se encuentra el metodo close del objeto socket, este metodos finaliza la conexión del socket con el servidor.


          sock.close()



script servidor:
1.-  #!/usr/bin/python
2.-  import socket
3.-  
4.-  sock = socket.socket()
5.-  sock.bind((“localhost”, 5000))
6.-  sock.listen(1)
7.-  
8.-  source, adreess = sock.accept()
9.-  
10.- while True:
11.-           datos = source.recv(1024)
12.-          if datos == “exit”:
13.-                     break
14.-          print “Se recibio:”, datos
15.-          source.send(datos)
16.- print “Bye”
17.- source.close()
18.- sock.close()


En la linea 1 colocamos el shebang para el interprete de python en gnu/linux:

          #!/usr/bin/python

En la linea 2 se encuentra la importacion del modulo socket, para el manejo de sockers en python
          import socket

En la linea 4 se encuentra la instanciacion del objeto socket en la variable sock

          sock = socket.socket()

En la linea 5 especificamos mediante una tupla el cliente que tendra acceso al servidor y el puerto por el cual el servidor se mantendra a la escucha a espera de el cliente, si en dado caso queremos que cualquier cliente se pueda conectar dejamos el primer campo vacio entre comillas pero en este caso especificaremos al localhost como el unico que puede conectarse al servidor , ademas de eso especificamos que escucharemos a los clientes en el puerto 5000.

          sock.bind((“localhost”, 5000))

En la linea 6 especificamos cuantos clientes aceptara el servidor, mediante la sentencia listen, en este caso solo aceptamoas un solo cliente.

          sock.listen(1)

En la linea 8 aceptamos la conexión entrante del cliente.

          source, adreess = sock.accept()

En la linea 10 iniciamos un bucle infinito mediante la sentencia while y el valor booleano True con el fin de poder repetir indefinidamente las sentencias siguientes.

          while True:

En la linea 11 inicializamos la variable datos con los datos provenientes del cliente, que en este caso es el valor de la variable mensaje en el script del cliente socket

          datos = source.recv(1024)

En la linea 12 y 13 especificamos una condicion if que verifica que el dato recibido sea igual a “exit”, en dado caso de que sea igual a exit, ejecuta la sentencia break y termina el bucle infinito.

          if datos == “exit”:
                    break

En la linea 14 mandamos a imprimir en pantalla el mensaje “Se recibio: ” seguido del dato proveniente de la comunicación con el clientes

          print “Se recibio:”, datos

En la linea 15 se envia el valor de la variable datos al cliente conectado al servidor.

          source.send(datos)

En la linea 16 ya fuera del bucle infinito se imprime en pantalla el mensaje Bye indicando que se concluira el script.

          print “Bye”

En la linea 17 y 18 indicamos el cierre de la conexión con el cliente conectado al servidor y el cierre de servidor creado.

          source.close()
          sock.close()


con eso concluye esta nueva entrada, creo que aplazar una entrada por dos semanas en contraproducente asi que cada semana lanzare una nueva, en esta ocacion el tiempo y la falta de microfono no ayudo en realizar un videotutorial de este tema, pero espero que la proxima entrada pueda lanzar junto con su version escrita una version en video, ademas de esto la encuenta para el proximo tema en abordar quedo en un triple empate por eso, omitire para la proxima un tema de programacion y tomare como el siguiente tema, los sistemas operativos.

viernes, 14 de febrero de 2014

Reparando el Kernel Panic Volume group "VolGroup00" not found en Centos 5


En esta ocacion explicare como solucionar este error que me llevo 1 dia y medio resolver, me atormento por un buen rato pero al final lo pude vencer.

bueno al grano, si estas viendo esta entrada de seguro tienes este mismo problema y te sale en el post este mismo error que muestro a bajo:

Scanning logical volumes
No volume groups found
Activating logical volumes
Volume group "VolGroup00" not found
Trying to resume from /dev/VolGroup00/LogVol01
Unable to access resume device /dev/VolGroup00/LogVol01
Creating root device
Mounting root filesystem
mount: could not find the system "/dev/root/"
Setting up other filesystems
Setting up new root fs
setuproot: moving /dev/failed: No such file or directory
no fstab.sys, mounting internal defaults
setuproot: error mounting /proc: No such file or directory
setuproot: error mounting /sys: No such file or directory
Switching to new root and running init
unmounting old /dev
unmounting old /proc
unmounting old /sys
switchroot: mount failed: No such file or directory
Kernel Panic - not syncing: attempted to kill init


todo esto se debe a que el nucleo de linux no reconoce las particiones del disco duro, en este caso el /dev/VolGroup00/LogVol00 y /dev/VolGroup00/LogVol01

la manera con que pude resolver este dilema es mediante un enjaulamiento de sistema, para eso necesitamos una ditribucion de linux, yo use lubuntu para esta tarea ya que tiene livecd, pero cualquier distribucion de gnu/linux con livecd funciona.

ok, iniciamos nuestro ordenador con nuestro livecd, accedemos a una terminal y montamos todo lo necesario, a bajo mostrare los comandos.

$sudo mount /dev/VolGroup00/LogVol00  /mnt
$sudo mount /dev/sda1  /mnt/boot
$sudo mount  --bind  /dev  /mnt/dev
$sudo mount  --bind  /dev/pts  /mnt/dev/pts
$sudo mount  --bind  /proc  /mnt/proc
$sudo mount  --bind  /sys  /mnt/sys

ahora que hemos montado todo esto, es hora de realizar el enjaulamiento con el comando chroot, e aqui el ejemplo:

$sudo chroot /mnt

ok, en este momento ya estamos dentro de nuestro CentOS 5 en el cual no teniamos acceso, por culpa del kernel panic, ahora es hora de hacer la magia para que todo funcione.

Ahora debemos averiguar que modulos esta usando el livecd para que funcione nuestro disco duro, en mi caso fue el ahci, esto lo puedes averiguar con el comando lspci y lsmod.

ok, una vez sabiendo que modulos  son para nuestro equipo es hora de modificar el archivo modprobe.conf asi que lo modificamos con nuetro editor de texto favorito, yo usare nano.

#nano /etc/modprobe.conf

y renombramos los drivers que corresponden a nuestro ordenador, en mi caso asi quedo.

alias eth0 tg3
alias scsi_hostadapter ahci

una vez hecho esto guardamos, cerramos y nos dirigimos a la carpeta de boot de esta forma.

#cd /boot

lo que haremos sera recontruir el initrd para que reconozca nuestro nuevo hardware que es el motivo por el cual linux nos lanza el kernel panic.

Pero antes tenemos que hacer una copia de nuestro initrd por si las dudas.

#mv initrd-2.6.18-238.9.1.el5PAE.img initrd.backup

Una vez ya hecho una copia procedemos a realizar la recontruccion del initrd.

#mkinitrd initrd-2.6.18-238.9.1.el5PAE.img   2.6.18-238.9.1.el5PAE

ya finalizada la reconstruccion, nos salimos del modo enjaulamiento con un exit

#exit

y ya solo queda reiniciar el equipo y acceder con el kernel que reparamos.

$sudo reboot

Nota: este error surgio por una clonacion de un servidor que maneja raid y al pasarlo a sata, centos no tenia idea de como levantar las particiones LVM ya que no tenia los drivers necesarios para poder reconocer el disco duro.


espero que le sirva a alguna persona que tenga el mismo problema que yo tuve :)

lunes, 27 de enero de 2014

Reparando disco duro dañado con Gnu/Linux







En esta ocasión explicare algunos comando de Linux que nos permite reparar los sectores dañados de un disco duro.

Badblocks

badblocks es un comando que nos permite reparar sectores de nuestro disco duro ya que analiza el disco y sobre escribe los sectores en caso de que estén dañados por una mala escritura de los datos en el, existen dos formas de usarlo que ahora explicare.

la primera forma de usarlo es la que recomiendo, esta borra todo el contenido del disco duro y repara completa mente el disco. 

ahora supongamos que nuestro disco a reparar se llama sdc, entonces realizaríamos algo similar a esto.

#badblocks -s -v -w /dev/sdc

donde:

-s    nos muestra el proceso de escaneo del disco.

-v    es la verbosidad del programa, nos muestra información del proceso.

-w   realiza la reparación de los sectores dañados.


ahora explicare como realizar el mismo proceso pero sin perder los datos que vendría siendo la segunda forma.

#badblocks -s -v -n -f /dev/sdc

donde:

-s    nos muestra el proceso de escaneo del disco.

-v    es la verbosidad del programa, nos muestra información del proceso.

-n    nos coloca en modo no destructivo  con el fin de no perder nuestros datos a la hora de repara los sectores.

-f    nos permite reparar los sectores dañados, a diferencia de -w, -f es usado para el modo no destructivo, con el fin de recuperar y reparar la información del sector dañado.


Fsck

fsck te permite reparar una partición si así lo deseas en lugar de todo el disco duro.

ahora supongamos que tenemos la partición sdc1 la cual tenemos problemas por sectores defectuosos, entonces usaríamos el comando siguiente para realizar esta reparación.

#fsck -c -v -y  /dev/sdc1

donde:

-c    comprueba los bloques en el disco.

-v    despliega información del proceso.

-y    asume yes de respuesta.


bueno con esto concluyo una nueva entrada, ojala le sirva a alguna persona esta información.