Unboxing a #0day – Hack a biometric system

#DISCLAIMER

Antes de empezar quiero dejar claro que me intente poner en contacto en 3 ocasiones con la empresa afectada, en dos de ellas por email pregunte por su departamento de seguridad y solo me facilitaban información comercial, intenté contactar con ellos también por twitter, sin ningún resultado.

Ahora mi responsabilidad como researcher solo me deja dos posibles soluciones (if/else), publicarlo (mentalidad hacker) o dejarlo y que otro lo explote sin que se conozca (pensamiento de pirata informático). Como mi intención nunca será la de hacer daño a la empresa o su imagen por la «seguridad de su producto» intentaré pixelar todo lo que pueda para que solo reconozca el producto aquel que ya lo haya comprado o se disponga a ello.

Gran parte de esta investigación se ha realizado en el lugar donde trabajo, por lo que estoy agradecido de que se me haya dado esa oportunidad (developer).

No expondré código alguno del exploit, primero no me pertenece (al haberlo echo en horario laboral) y segundo, no creo que sea ético dar las llaves de las cerraduras a la gente, si lo que queremos es mejorar la seguridad de las personas.

Por último quiero dejar claro que tampoco pretende ser una guía de como entrar a robar a un sitio, ni mucho menos, la única intención de este artículo es precisamente lo contrario, demostrar que tenemos que buscar los consumidores a la hora de buscar un producto de estas características.

Dicho todo esto comenzamos con la entrada 🙂

 

#WELCOME

Buenos días amigos de los Oryctolagus, lo que os traigo hoy no es mas que el estudio de las vulnerabilidades encontradas en un producto comercial y que están aún vigentes debido a la dejadez o falta de interés del fabricante a contactar conmigo, a devolverme los correos y sobretodo a la falta de un BugBounty. Que queda entonces, pues hacer un disclosure y esperar que algún día el fabricante encuentre su producto entre las entrañas de Internet y se digne a arreglarlo, aunque a mi parecer, la seguridad no ha sido un de los pilares durante su desarrollo y puede ser mas complicado de lo que parece.

Recientemente adquirimos un control de personal (para ver horarios de entrada y salida) y control de accesos biométrico (poder abrir puertas con la huella del dedo). Como podéis ver no es precisamente barato. Y me dispuse a ver cuan seguro era dicho producto, a la vez de si podía o había algún tipo de librería para conectarlo con un programa (para el que trabajo). Mi sorpresa fue que no había SDK y que no parecía que tuvieran intención de hacerlo, por lo que para conectarlo, me dispuse a ver como se podría sacar la información de dicho aparato.

UPDATE: Pocos días antes de publicar esta entrada, encontré un SDK, por lo que el propio SDK puede valer de exploit.

 

#UNBOXING FÍSICO

Primero voy a enseñaros las especificaciones técnicas del producto, para ver cómo podría evadir el sistema un usuario malintencionado y abrir la puerta. Olvidaros de enchufar dos cables y ver un contador bajando «¡Quedan dos minutos jefe!», nada de eso … La realidad supera siempre a la ficción compañeros.

¿Como podría un ladrón abrir una puerta protegida por un sistema biométrico, de tarjetas o por pin? (pudiera ser solo contara con la opción de biometría)

El primer fallo notable se ve ya en sí en la propia instalación del producto, ya que al instalarlo toda la electrónica queda del lado expuesto de la puerta, del que se encuentra nuestro «ladrón» o persona non grata. Lo que podría permitir al «atacante» operar con el producto para ver sus entresijos. Al montar un sistema de este tipo, si tu intención es proteger lo que hay por detrás, no puedes dejar a la persona que tiene las llaves con el culo al aire y delante de la puerta …

Cabe decir que cuenta con un avisador, para que en caso de manipulación suene una alarma, aunque ya veremos como evadir esta parte.

El segundo fallo destacable del producto es que su carcasa es de plástico. Lo que nos vendrá muy bien para nuestro propósito. Abriéndole las tripas podemos distinguir a grandes rasgos 4 partes importantes del producto:

  • Una entrada USB (no jugaremos con ella)
  • Una entrada de ethernet ( welcome to the jungle )
  • El detector de manipulación ( controla un pitido molesto a la hora de abrirlo )
  • Los conectores a la puerta ( nuestro objetivo para ver el Area 51 ), justo debajo de él se encuentra el relé que abrirá y dará acceso a la puerta.

 

Aquí tenemos en mas detalle las especificaciones y los detalles de cada una de las entradas

Pues vamos a ver como se porta «el cacharrito en caso de manipulación no deseada», como se esperaba ¡se queja!

#Bypasseando la sirena de manipulación

Como nuestro objetivo de momento es entrar al otro lado, vamos a ver que podemos hacer para conseguir realizar un simple puente que accione el relé y con ello abrir la puerta de par en par.

Método 1 – Soldando

Con este método tan solo tendríamos que soldar un pequeño agujero en este punto que nos permitiera hacer el puente, no se accionaría la palanca y no saltaría ninguna alarma. Eso sí un poco hacia el lateral para salvar la electrónica de la pantalla y del teclado (que dudo mucho nos importará que quedara inutilizado)

Mediante esta técnica no necesitarías abrirlo, porque el hueco te permitiría manipular las conexiones para realizar el puente al relé.

Método 2 – A lo vasco ¡Arrancándolo de la pared!

Está claro que el que quiere entrar no va tener miramientos, por lo que como decía antes, que la electrónica esté por fuera es un grave problema. Si el atacante arrancara de cuajo de la pared el aparato, podría abrirlo sin activar la sirena, ¿cómo? pues como diría el famoso niño, con …

Os dejo un vídeo de la prueba de concepto, donde por medio del hueco del cableado, es completamente accesible el accionador y se puede bloquear durante la apertura del mismo.

¿Y para que queremos abrirlo? pues para realizar un simple puente que abra la puerta del Area51. Aquí tenéis un ejemplo (sin soldar obviamente), donde podéis escuchar el sonido del relé cuando se produciría la apertura de la puerta.

También pude comprobar que la sirena no sonaba cambiando el cable de red. Por lo que si rompieras el pladur, sacaras el macarrón y crimparas un extremo, podrías pasar a realizar la serie de ataques que veremos a continuación.

#UNBOXING DIGITAL

Ahora vamos a centrarnos mas en la parte de unos y ceros. La que realmente nos interesa, la que te convierte en un ladrón de guante blanco, y como no, hubo que empezar reverseando el software de la máquina.

Como su comunicación va por TCP/IP me dispuse a utilizar el famoso WireShark para ver que mandaba el programa (tiene un software que registra las entradas y salidas del personal). La verdad era una tarea un poco pesada, así que opté por examinar a fondo la carpeta de la instalación y cual fue mi sorpresa cuando en una carpeta log (sin haber activado yo ninguna opción de depuración) me encuentro todas las llamadas que hace la aplicación ¡y sus respuestas! (instalación por defecto).

 

Me acababa de ahorrar muchísimas horas de análisis de tráfico, por lo que no sabía si estar agradecido o flipando por semejante fuga de información. Ahora solo quedaba entender como funcionaba el protocolo y replicar el proceso, para ello, solo tenía que utilizar el programa como un usuario, borrando el log previamente para ver que le mandaba y que recibía la máquina cada vez que realizaba alguna acción. Y mi primera sorpresa fue, tras resetearla de fábrica, que todo lo que enviaba y recibía era lo mismo, carecía de encriptación y encima de autentificación, ninguna clave era enviada para decirle a la máquina, ¡oye que soy yo, no un cualquiera! …

Con ayuda de muchas horas de trabajo y sobretodo de la página https://hexed.it , pude entender poco a poco que era lo que enviaba y recibía (todo en Big-Endian)

Pronto tuve un código funcional (¿SDK?) de la propia máquina. Podía abrir puertas, dar de alta usuarios, ver los usuarios que existían con sus pines, modificar tarjetas, eliminar todos los registros del control de personal, etc, etc…

Como curiosidad, una de las partes que mas me costó fue dar con la función CRC que utilizaba para enviar los datos ya que por ejemplo una cadena de ejemplo que enviaba a modo de «Hola voy a empezar a decirte lo que tienes que hacer, pero sin decirte quien soy» era

 A5 00 00 00 01 48 00 00 F0 4A

Donde  0xA5, 0x00, 0x00, 0x00, 0x01 era un prefijo que se utilizaba siempre (supongo que un tipo de versionado) 48 00 00 era el mensaje que se quería enviar (en este caso el Handshake) y F0 4A era un dichoso CRC, al menos estaba seguro de ello, no variaba a no ser que yo variara, por ejemplo, el nombre del usuario a crear, detalles así me hicieron pensar que era un CRC de 16 bits, pero hay tantas formas de calcular un CRC, ¿realmente lo necesitaba? la mayoría de mensajes eran fijos, ABRIR PUERTA, BORRAR USUARIOS, un simple ataque de replicación de tráfico los ejecutaba a la perfección. Pero yo quería poder crear mi usuario, no tener todo hardcodeado, llegar un poco mas allá, así que me dispuse a averiguar como calculaba el dichoso checksum.

Calculando el CRC

¿De que manera calcularía el CRC? si algo tenía claro es que era un CRC de 2 bytes, por lo que mi primera opción antes del reversing fue buscar CRC pre-calculados, y si coincidían, pues me ahorraría horas de reversing. Probé con esta web https://www.lammertbies.nl/comm/info/crc-calculation.html donde le ponías un dato y te generaba el CRC, con el fin de sacar la función que utilizaba para calcularlo.

También existe esta http://crccalc.com (que es mas completa) y que he descubierto haciendo esta entrada (siempre se aprende algo), la cual me habría dado un falso negativo a pesar de que el método si que está entre los listados, por lo que voy a pasar a explicar a continuación.

Tras mi primera frustración lo primero que hice fue ir al IDA y buscar donde guardaba el log, para ir de ahí para atrás y ver donde generaba el CRC en función del mensaje.

Buscando un poquito localice la función donde se escribían dichos archivos de log.

Rápidamente localice la función del cálculo donde establecía dichos valores al final del buffer (utilize x64dbg para este proceso)

 

Me fui a IDA dónde claramente distinguí que tiene un array (word_C3D324) del cual va sacando los valores sobre los que hará un XOR (a grandes rasgos)

Mi siguiente paso fue buscar dos o tres valores de los utilizados, como soy un poco vago por naturaleza (y mis conocimientos de reversing también son limitados) tiré de tito google y localicé un script en python (https://github.com/digidotcom/python-suitcase/blob/master/suitcase/crc.py) que utilizaba los mismos valores para calcular un CRC de 16 bits, ¿demasiada coincidencia? ¿cual era? el CRC-16/KERMIT. ¡Pero no me funcionaba! no me daba el mismo resultado, entonces volví al IDA y enseguida me di cuenta de que ellos inicializaban la función con 0xFFFF y tanto la web anteriormente mencionada como el script localizado lo hacía con 0x0000. Por lo que pude replicar ya con éxito el cálculo del checksum de cada uno de los mensajes a enviar.

 


Ya disponía de la capacidad de poder escribir los mensajes que quisiera sin tener que tener harcodeado el payload completo (que sería la opción mas simple ya que no varía con el tiempo). Aquí tenéis un ejemplo de como se da de alta una tarjeta como administrador, que previamente no estaba registrada en el aparato.

#CÁLCULO DEL PIN

También cabe mencionar que el CRC no fue de lo único que se resistió, el cálculo del pin parecía un CTF, guardaba el pin numérico en 3 bytes (BigEndian) pero al pasar de 65535, algo no cuadraba … Tras un tiempo analizando muestras de diferentes pines, se llegó a la conclusión de que para generarlo, utilizaba también la logitud del mismo en el primer digito hexadecimal del primer byte. Quedando la función en c# de la siguiente manera

static byte[] Pin2Buffer(int pin)
{
  // Cuando no se le pase un pin válido devolver 0xFFFFFF
  if (pin == int.MaxValue || pin == int.MinValue) return new byte[] { 0xFF, 0xFF, 0xFF };
  // Sacar longitud del pin en string
  int l = pin.ToString().Length;

  // Convertirlo a Int32 y quitarle un byte (Int24)
  byte[] bp = BitConverter.GetBytes(pin).Take(3).ToArray();
  // Invertirlo para el BigEndian
  Array.Reverse(bp);
  // Al primer byte sumarle el tamaño en Hexadecimal al valor actual
  bp[0] = (byte)(bp[0] + Convert.ToByte(l.ToString() + "0", 16));
  return bp;
}

#MORALEJA

  • Con un clip y un mechero puedes entrar al Area51
  • Cualquier empleado con acceso a la red, puede entrar al Area51
  • Este NO es un sistema seguro para proteger el Area51

Espero que os haya gustado, un saludo y ¡hasta la próxima!

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Los datos introducidos se guardarán en nuestra base de datos como parte del comentario publicado, como se indica en la política de privacidad.