viernes, octubre 02, 2020

Raspberry Pi Random Numbers Beacon: Una baliza de números aleatorios del mundo Maker para el mundo IoT #IoT #Criptografía #makers #RaspberryPi

Antes de empezar, quiero aclarar que este no es un artículo sobre la teoría de los números aleatorios de los muchos que podéis encontrar por Internet ;). Esta vez nos centraremos en lo práctico, es decir, implementar nuestro propio generador de números aleatorios lo más “verdadero” posible (luego veremos un poco más este término) utilizando hardware asequible, en este caso una Raspberry Pi.

Figura 1: Raspberry Pi Random Numbers Beacon:
Una baliza de números aleatorios del mundo Maker para el mundo IoT

Por cierto, si queréis encontrar más proyectos enfocados a la ciberseguridad usando este mismo hardware, en el libro “Raspberry Pi para Hackers & Makers: PoC & Hacks Just for Fun” de la editorial 0xWord podéis encontrar varios de ellos:

Figura 2: Libro de Raspberry Pi para hackers & Makers
PoCs & Hacks Just for Fun en 0xWord escrito por
Pablo Abel Criado, Hector Alonso y Amador Aparicio

Los números aleatorios son un elemento fundamental dentro del mundo de la ciberseguridad, y sobre todo en criptografía. Pero no sólo en criptografía son importantes los números aleatorios. También lo son por ejemplo en la secuencia de números para TCP/IP, TLS, ASLR offsets, Salts, DNS, etcétera. Volviendo de nuevo a la criptografía, estos se utilizan principalmente para obtener cifrados seguros. Pero estos números aleatorios, a pesar de lo que podamos pensar, no son sencillos de generarlos digamos, de manera 100% random

Números aleatorios, un breve repaso 

Generar un número aleatorio con un ordenador u otro dispositivo que sea capaz de hacer los cálculos, puede que, debido a su naturaleza, ese número no sea tan aleatorio o incluso se abre la posibilidad de llegar a predecirlo. Y esto puede comprometer la seguridad del cifrado y, por lo tanto, de todo el sistema. La calidad de un número aleatorio define en un alto porcentaje la fortaleza del cifrado final. 

Figura 3: Representación en imágenes de los números aleatorios. A la izquierda, números aleatorios reales y a la derecha podemos observar los patrones de repetición en otro generador. 

Dicho de otra manera, la calidad del número aleatorio obtenido con un generador influye directamente en la dificultad de atacar cualquier tipo de sistema que use algún tipo de cifrado. La mayoría de los algoritmos se basan en cómo un atacante es capaz de adivinar (o predecir) cierto número de bits que se utilizaron en la clave original. 


Y aquí es donde radica la importancia de los números aleatorios, si el atacante no tiene información por donde empezar (ya que es aleatoria) el porcentaje de éxito para romper el sistema se reduce prácticamente a cero. En definitiva, sin aleatoriedad, todas las operaciones de criptografía se podrían predecir y por ello, dichas operaciones o transacciones serían inseguras.

Pseudo-Random

La mayoría de las librerías que podemos utilizar en un ordenador, generan los números llamados Pseudo-Random (PRNG, pseudo random number generators) o casi-aleatorios. La mayoría de ellos son creados por un proceso determinista (es decir, los números se generan con una misma base y existen posibilidades de repetir el patrón) lo que implica que al final, no son realmente tan aleatorios. La Figura 3 muestra perfectamente ese hecho. 

Para muchas aplicaciones esto no es en sí un problema, pero en ciberseguridad es vital siempre mejorar la precisión de la semilla (seed). Por lo tanto, es importante obtener mejor precisión a la hora generar estos números ya que son la base que se utiliza como entrada al algoritmo de cifrado. Muchos sistemas operativos llevan incluidos un PRNG implementados por software (en este enlace del blog de LUCA podéis obtener más información sobre cómo generarlos).

Ya sabemos que en Linux cuando generamos una clave criptografía, a la hora de generar la semilla se nos pide teclear algo o mover el ratón. De esta forma generamos la suficiente entropía (la manera en la que podemos medir la incertidumbre o el desorden de cualquier sistema) y por lo tanto obtener así el mejor resultado aleatorio posible para nuestra semilla. El problema es que esta entropía se recolecta de la misma manera en todos los sistemas operativos Linux y, por lo tanto, en cierto modo es teóricamente predecible. 

True Random

Por otro lado, la generación de números aleatorios denominados True Random (TRNG) se basa principalmente en la obtención de datos de fenómenos físicos, como por ejemplo, temperatura, luz, radioactividad, radio e incluso fenómenos cuánticos (aquí tienes un ejemplo) de los cuales obtenemos una salida no determinista. Otra característica que los define es que no son periódicos en su naturaleza, es decir, no podremos obtener nunca la misma salida, aunque la semilla sea la misma en el mismo generador. 



Este factor es importante ya que marca la diferencia y ofrece diversas técnicas matemáticas para conseguirlo. En el mercado existen una gran variedad de hardware (HRNG) que intentan de mayor o menor manera, conseguir los TRNG lo más preciso posible. El rango de precios puede variar desde los 50€ hasta más de 1.000€


Intel por ejemplo, incluye un TRNG en sus procesadores desde Ivy Bridge, aunque hay discusiones sobre si es TRNG o PRNG. Todos ellos se basan en medir fenómenos cuánticos o de naturaleza, pero siempre son valores out-of-the-box, es decir, aquellos que ocurren alrededor del dispositivo.

Raspberry Pi Random Number Generator Beacon

Como antes hemos comentado, nuestro objetivo para esta PoC es construir una especie de baliza (beacon) que esté continuamente generando números aleatorios y los presente realizando simplemente peticiones HTTP a la dirección IP o URL del dispositivo. De esta forma, cuando un usuario o un dispositivo necesite un número aleatorio, con hacer esa llamada recibirá uno distinto cada vez que se realice la solicitud. 

Como base de esta PoC hemos utilizado dos componentes fundamentales, una Raspberry Pi, un shield llamado Sense Hat, el cual nos ofrece una gran cantidad de sensores, pero además hemos añadido una cámara típica de Raspberry Pi para obtener más mediciones, como ahora veremos. 


Con el Sense Hat tendremos la posibilidad de leer valores como temperatura, humedad, presión atmosférica, acelerómetro y giróscopo. Además, incluye un display led de varios colores y un pequeño joystick que, en principio, no usaremos en este proyecto (aunque este podría servir como una entrada más de datos aleatorios). 

Figura 9: Aspecto final del Raspberry Pi Random Number Generator Beacon. 

En total, para generar toda la entropía necesaria y así obtener un número lo más aleatorio cercano a los TRN, vamos a utilizar los siguientes sensores para recibir los datos del exterior:

1. Cámara
2. Giróscopo (x,y,z)
3. Acelerómetro
4. Magnetómetro
5. Temperatura
6. Humedad
7. Presión

La cámara realiza una foto y a partir de ella genera una serie de valores que siempre serán distintos en función de donde esté enfocando (por ejemplo, a una ventana es perfecto ya que las variaciones, por ejemplo, de luminosidad, nos servirán para obtener información lo más aleatoria posible. Una vez tomada la foto, obtenemos su hash utilizando la librería ImageHash el cual pasamos a su vez a base64

El resto de los valores obtenidos de las diferentes lecturas de los sensores, se almacenarán igual, en base64. Una vez obtenidos todos los datos, convertimos la información a binario y realizamos una serie de operaciones XOR entre las diferentes entradas también de forma aleatoria.

Finalmente, obtenemos un número aleatorio codificado como ya hemos comentado en base64. Pero para añadir aún más entropía, de cada valor leído por cada sensor, utilizaremos sólo los primeros 32 bits de cada uno de ellos. Estos trozos los reordenamos de forma aleatoria para componer finalmente un nuevo número basado en esas diferentes partes. El siguiente esquema explica en detalle el funcionamiento descrito:

Figura 10: Esquema de funcionamiento desde la lectura de los datos
de los sensores hasta la generación del número final. 

Obviamente esta secuencia se puede perfeccionar de muchas maneras, como por ejemplo evitando usar números random (generados por la Raspberry Pi, podría conseguirlo de otra manera por ejemplo usando los datos de un sensor o varios) para el primer XOR y también para la ubicación (1 y 3) entre otros cambios posibles. Pero el objetivo de este proyecto no es montar un generador comercial de números aleatorios verdaderos, sino experimentar con él y aproximarnos lo máximo posible a ellos.

Figura 11: Salida de ejecución del código que levanta el servidor
web en Flask y genera los números aleatorios. 

En resumen, esta puede ser una buena plataforma para comenzar a investigar otros métodos de obtención de dichos números aleatorios usando hardware relativamente barato. Por cierto, existen sensores muchos más asequibles que el Sense Hat o directamente podemos utilizar un breadboard y montarlos individualmente allí, pero esta opción la he elegido simplemente porque la tenía por casa ;) y además incluye una gran colección de sensores que podemos utilizar fácilmente con su librería.

Recibiendo los números generados

Para recibir los números aleatorios generados por la Raspberry Pi Beacon, hemos creado un pequeños servidor web basado en Flask el cual será el responsable de enviar el número aleatorio generado a través de HTTP. Por ejemplo, con el comando curl podríamos acceder al número aleatorio generado en ese momento de la petición:
$ curl 192.168.2.230
mMeyNFZDuPG9TQHlGvoVQ0NFiFc=%

$ curl 192.168.2.230
4eGAtQv/AON9imQ98iNZuzfElPY=%

$ curl 192.168.2.230
2N0tdUtTCqRaMPPudE0Ecb/W+lM=%
O también dese el navegador web:

Figura 12: Número aleatorio generado accesible
vía web usando el navegador Safari. 

Un posible escenario práctico para esta PoC se podría situar dentro del mundo del IoT. Muchos dispositivos en el Internet of Things están continuamente generando claves de cifrado tanto para transmisiones como para proteger la información que se encuentra almacenada en ellos. En el siguiente vídeo se puede ver todo el proceso, así como el funcionamiento interno del servidor web. 


Figura 13: Raspberry Pi Beacom: Random Number Generator

Por ejemplo, en ese entorno IoT podríamos usar nuestro Raspberry Pi Beacon para obtener los números aleatorios necesarios en intervalos de tiempo hacia dispositivos IoT y de esta forma conseguir nuevas claves de cifrado en todos nuestros aparatos. Eso sí, previamente habría que cifrar el acceso al servidor web o incluso los números obtenidos, pero eso ya es otra historia ;) 

Conclusión 

En definitiva, hoy día disponemos de una gran variedad de hardware a precio asequible el cual podemos utilizar para proyectos similares al que exponemos hoy aquí. La potencia de algunos de estos elementos nos permite explorar su funcionamiento si estar demasiado alejados de productos comerciales que hacen la misma función. Y todo esto gracias al movimiento Maker, que ya sabéis que a nosotros nos gusta, y mis compañeros tienen el libro de Arduino para Hackers: PoCs & Hacks Just for Fun.

Figura 14: "Arduino para Hackers: PoCs & Hacks Just for Fun"

Por cierto, si os interesa el tema de los números aleatorios es indispensable acceder a la web de Random.org, la cual está repleta de recursos relacionados con los ellos.  Gracias a Marta Vila y a Enrique Blanco por sus consejos a la hora de implementar las diferentes combinaciones que conforman el número aleatorio final. 

Happy Hacking Hackers!!!

Fran Ramírez, (@cyberhadesblog) es investigador de seguridad y miembro del equipo de Ideas Locas en CDO en Telefónica, co-autor del libro "Microhistorias: Anécdotas y Curiosidades de la historia de la informática (y los hackers)", del libro "Docker: SecDevOps", también de "Machine Learning aplicado a la Ciberseguridad” además del blog CyberHades. Puedes contactar con Fran Ramirez en MyPublicInbox.

Figura 15: Contactar con Fran Ramírez en MyPublicInbox

jueves, octubre 01, 2020

Machine Learning: Ataques FGSM (Fast Gradient Signed Method) contra redes neuronales en algoritmos de Deep Learning

El área del Machine Learning aplicado a Ciberseguridad, y más concretamente el uso de algoritmos de Deep Learning, está cobrando cada vez más importancia. Esta afirmación es cuasi evidente, ya que nos permite resolver algunos problemas clásico en menor tiempo, así como conseguir mejores resultados o resolver casos que antes no se podían resolver de manera sencilla. Una prueba de hacia donde vamos son las aplicaciones del nuevo modelo GPT3 del que nos habló nuestro compañero Pablo Saucedo.

Figura 1: Machine Learning: Ataques FGSM (Fast Gradient Signed Method)
contra redes neuronales en algoritmos de Deep Learning

En este artículo de hoy os hablaré de un tema de actualidad en el mundo del Machine Learning y la Ciberseguridad. En concreto vamos a hablar de securizar modelos de Deep Learning, como las redes neuronales. A alguno le puede sorprender que haya que hacer esto, pero deberéis esperar al final para entender si se puede o no hackear una red neuronal.


Antes de comenzar repasaremos, a grandes rasgos, cómo funcionan las redes neuronales para que todos podamos entender la vulnerabilidad que afecta a algunos modelos de Deep Learning

Una red neuronal sencilla

Lo primero que tenemos que saber es que las redes neuronales aprenden funciones, es decir, son capaces de mapear una entrada X a una salida Y. Por tanto, estos modelos tienen una fase previa de aprendizaje u optimización. Por ejemplo, podemos enseñar a una red neuronal a distinguir números manuscritos. Estos modelos son capaces de aprender funciones gracias a sus parámetros, normalmente denominados pesos. 

Figura 3: Función simple de una red neuronal

Una red neuronal sencilla de una sola capa se rige por la ecuación de la Figura 3. Como veis una red sencilla no es más que una multiplicación de matrices. Cabe mencionar que muchas de las redes neuronales profundas que existen tienen millones de parámetros. Esto último es importante para entender los ataques que os vamos a explicar, ya que estos tienen éxito debido a la gran cantidad de parámetros que suelen tener este tipo de redes. ¡Vamos a ello!

Ataque FSGM (Fast Gradient Signed Method)

Este ataque consiste en generar ejemplos adversarios, casi indistinguibles por el ojo humano, que sean capaces de confundir o engañar a un modelo de Deep Learning. Es decir, entrenaremos una red neuronal para clasificar imágenes en diez posibles clases con una alta fiabilidad (cercana al 80%) y posteriormente, modificaremos estas imágenes de forma que la fiabilidad de la red baje y con ello provoquemos clasificaciones incorrectas. 

Figura 4: Imágenes modificadas en 0.01 y en 0.09

Existen varios métodos para llevar a cabo este ataque, algunos de ellos muy sofisticados. El que veremos se denomina FSGM o Fast Gradient Signed Method. Podéis ver un par de ejemplos de este ataque en la Figura 4. En el primero podéis ver que el cambio sobre la imagen es imperceptible y en el segundo hemos exagerado el efecto para que veáis la transformación que hemos realizado.

Cuando entrenamos un modelo tenemos que pasarle unas entradas, que normalmente se encuentran acotadas dentro de un dominio. Por ejemplo, los píxeles de las imágenes toman valores enteros entre 0 y 255. Por tanto, nuestra red se debería comportar de la misma forma si introducimos los píxeles con intensidades X = [21, 34, 128, 11] y Xs = [21.001, 34.001, 128.001, 11.001]. La realidad es que no es así. Como vimos antes en una red sencilla se realiza la operación de la Figura 3. Eliminaremos algunos términos para facilitar la explicación, dejando la expresión de la siguiente forma: 

Figura 5: Simplificación de la fórmula de la red neuronal

Como vemos nuestra entrada Xs es el resultado de sumar X + S, siendo S = [0.001, 0.001, 0.001, 0.001]. Por tanto, si introducimos como entrada Xs la salida vendrá determinada por la siguiente ecuación: 

Figura 6: Salida modificada

Con esta ecuación podemos ver que si W es positivo y su dimensión es muy grande (recordad que en casos reales estamos hablando de millones de parámetros) podríamos producir un cambio muy grande en la salida haciendo un cambio muy pequeño en la entrada. La amplificación de la salida viene dada por la fórmula E*N*M, siendo E = ||S||, N el número de dimensiones de W y M el valor medio de W. El ataque FSGM modifica la imagen de entrada siguiendo la fórmula siguiente:

Figura 7: Fórmula FSGM

Como podéis ver estamos calculando el signo de los gradientes de la función de coste con respecto a la imagen de entrada y después lo estamos multiplicando por un valor E. El signo de los gradientes nos proporciona la dirección aproximada de maximización de la función de coste y con E regulamos la cantidad de pérdida. Por tanto, estamos modificando la imagen de forma que maximicemos la probabilidad de que la red falle. Sé que puede sonar un poco complicado, por ello vamos a intentar verlo gráficamente. 

Representación gráfica del ataque FSGM y Demo

En la Figura 8 hemos dibujado la función de coste con respecto a la imagen de entrada. En esta gráfica hemos supuesto que la imagen solo se compone de dos píxeles para poder trabajar en tres dimensiones. El eje azul representa la función de coste J, el eje rojo representa el valor de intensidad del primer píxel de la imagen, el eje verde representa el valor de intensidad del segundo píxel y el punto amarillo indica la pérdida actual de la imagen (es decir, cuánto se confunde la red al clasificar la imagen de entrada). 

Figura 8: Gradiente de la función de pérdida con respecto a la imagen de entrada

La flecha negra con borde amarillo es el vector gradiente que hemos calculado. Si os fijáis, ésta apunta hacia la dirección de máximo crecimiento de la función de coste. Si aplicamos la función signo sobre este vector nos estamos quedando con la dirección aproximada a la que apunta. Con la variable E estamos indicando la longitud de este vector, es decir, la longitud de la flecha.  Hemos implementado este algoritmo en TensorFlow. A continuación os dejamos un vídeo explicativo.


Figura 9: Explicación y demo de los ataques FGSM a redes neuronales

Si os habéis fijado este ataque es un ataque de caja blanca, es decir, necesitamos tener acceso a la red para poder calcular los gradientes, aunque también existen ataques similares de caja negra. Si queréis seguir investigando os animo a leer el siguiente paper, donde encontraréis más detalles sobre el ataque y algunas contramedidas o defensas. De todas formas, en el siguiente artículo tenéis explicadas algunas de estas defensas.

¡Espero que os haya gustado! 

Autor: Marcos Rivera Martínez (@marcos_98_rm), Ingeniero Informático e investigador de Inteligencia Artificial y Ciberseguridad en el equipo de Ideas Locas de la unidad CDCO de Telefónica.

Entrada destacada

Hacking IA: Jailbreak, Prompt Injection, Hallucinations & Unalignment. Nuestro nuevo libro en 0xWord

Pocas veces me ha hecho tanta ilusión que saliera un nuevo libro en 0xWord como con este libro de " Hacking IA: Jailbreak, Prompt Inje...

Entradas populares