{"id":381,"date":"2017-09-25T00:17:38","date_gmt":"2017-09-24T23:17:38","guid":{"rendered":"http:\/\/klondike.es\/klog\/?p=381"},"modified":"2017-09-25T00:17:38","modified_gmt":"2017-09-24T23:17:38","slug":"descifrando-las-bases-de-datos-del-referendum-catalan","status":"publish","type":"post","link":"https:\/\/klondike.es\/klog\/2017\/09\/25\/descifrando-las-bases-de-datos-del-referendum-catalan\/","title":{"rendered":"Descifrando las bases de datos del refer\u00e9ndum catal\u00e1n"},"content":{"rendered":"<p>A trav\u00e9s del enlace de un amigo he acabado en una p\u00e1gina d\u00f3nde se muestra a los votantes del refer\u00e9ndum catal\u00e1n la ubicaci\u00f3n de la urna d\u00f3nde se debe votar. Como de costumbre, me ha podido la curiosidad y me he puesto a analizar como funcionaba el sistema. La verdad es que usan un sistema bastante interesante aunque el sistema criptogr\u00e1fico empleado presenta algunas vulnerabilidades. En este post os contar\u00e9 tanto el funcionamiento como las vulnerabilidades del sistema.<\/p>\n<p><!--more-->A alto nivel el funcionamiento del sistema es bastante sencillo, se le pide al votante su n\u00famero de DNI, su fecha de nacimiento y su c\u00f3digo postal y se usan estos datos para identificar y autenticar al mismo. Un sistema criptogr\u00e1fico procesa dichas entradas y devuelve un identificador que se usa para decidir que fichero de la base de datos descargar, dicho identificador tambi\u00e9n se usa para encontrar la entrada espec\u00edfica del votante y para descifrar los datos que le indican la mesa electoral en la que ha de votar. Finalmente se le muestran los datos descifrados al votante.<\/p>\n<p>En m\u00e1s detalle el funcionamiento tampoco es mucho m\u00e1s complicado. Se concatenan los \u00faltimos 5 d\u00edgitos del DNI, la letra, la fecha de nacimiento en formato AAAAMMDD y el c\u00f3digo postal (usando 5 d\u00edgitos). Luego se calcula el hash SHA-256 de estos datos 1715 veces con el detalle de que el resultado es convertido a hexadecimal antes de ser hasheado, esto se usa como semilla para la clave de descifrado, dicha semilla es convertida a hexadecimal y hasheada de nuevo para obtener el identificador en la base de datos. Respecto a la clave de descifrado que se obtiene de dicha semilla, tanto la clave AES256 como el IV se obtienen usando una funci\u00f3n equivalente a la funci\u00f3n <a href=\"https:\/\/wiki.openssl.org\/index.php\/Manual:EVP_BytesToKey%283%29\" target=\"_blank\">EVP_BytesToKey<\/a> de openssl. Una vez obtenido el identificador se usa el primer byte en hexadecimal del hash para elegir el directorio y el segundo para elegir el archivo dentro de dicho directorio, dicho archivo se baja del servidor y se procesa l\u00ednea a l\u00ednea hasta encontrar una cuyos primeros 60 bytes coincidan con el resto de bytes en hexadecimal del identificador. Finalmente la clave y el IV obtenidos con la funci\u00f3n equivalente a EVP_BytesToKey se usan para descifrar la informaci\u00f3n usando AES-256 en modo CBC el padding utilizado es PKCS#7. Los datos descifrados son luego procesados y mostrados al usuario. Si no aparece ninguna entrada para los datos introducidos, tambi\u00e9n se indica esto al usuario.<\/p>\n<p>Todo este c\u00f3digo est\u00e1 escrito en Javascript y est\u00e1 en la funci\u00f3n calcula de la propia p\u00e1gina web y en el m\u00f3dulo \/js\/bundleV8.js de dicha p\u00e1gina. No est\u00e1 ofuscado lo que ha simplificado el proceso.<\/p>\n<p>La verdad es que el sistema en si funciona de forma bastante rara, el cifrado de los datos de la mesa electoral no ofrece ninguna ventaja a la hora de proteger los datos del votante, ya que si un atacante obtiene el propio identificador de la entrada deber\u00eda haber obtenido primero la semilla usada para cifrar los datos. Desde este punto de vista ser\u00eda m\u00e1s eficiente, por ejemplo, asociar un identificador num\u00e9rico a cada mesa y usar este en su lugar. Uno podr\u00eda pensar que la idea es evitar que el atacante conozca todas las mesas, sin embargo se podr\u00eda haber obtenido un resultado similar cifrando todas las mesas (incluyendo algunas falsas) y cifrando \u00fanicamente el identificador de la misma (o la clave de descifrado con la que se podr\u00eda derivar el identificador). Adem\u00e1s, el sistema no evita completamente el ataque, dado que es posible utilizar fuerza bruta y esta es trivialmente paralelizable. De hecho, es razonable pensar que la informaci\u00f3n que utiliza la base de datos (el DNI, la fecha de nacimiento y el c\u00f3digo postal) ya la tenga el gobierno espa\u00f1ol y este pueda utilizarla para obtener la lista de mesas electorales.<\/p>\n<p>Pero nosotros no somos el Gobierno Espa\u00f1ol, as\u00ed que \u00bfcuales son nuestras posibilidades de obtener la informaci\u00f3n?. El DNI ofrece unos 21.13 bits de entrop\u00eda, la fecha de nacimiento unos 15.53 y el c\u00f3digo postal unos 15.80 para un total de unos 52.47 bits. Si elegimos \u00fanicamente los c\u00f3digos postales de las provincias de Catalu\u00f1a se nos quedan 11.55 bits para un total de 48.22. Es bastante obvio que es muy sencillo obtener un dato dados los otros dos (el peor caso ser\u00eda el DNI que no llevar\u00eda algo m\u00e1s de 2\u00b2\u2070 intentos), de forma semejante con s\u00f3lo uno de los datos es factible obtener los otros dos aunque el coste es mayor (2\u00b3\u2076 intentos en el peor caso) y obviamente el coste de atacar la base de datos completa por fuerza bruta es de algo menos de 2\u2075\u00b3.<\/p>\n<p>En aras de hacer pruebas he escrito <a href=\"http:\/\/klondike.es\/programas\/varios\/refcrack.tar.gz\" target=\"_blank\">una implementaci\u00f3n en python<\/a> (con una versi\u00f3n en C del algoritmo de hasheo) a modo de prueba de concepto. Con esta soy capaz de obtener unos 250 hashes por segundo con un Core 2 Duo y un s\u00f3lo hilo usando s\u00f3lo python y 500 usando el hasheo en C. Esta implementaci\u00f3n no hace uso de instrucciones SIMD para calcular varios hashes a la vez ni de m\u00faltiples hilos y usa la implementaci\u00f3n de SHA256 de openssl (o la de python si el m\u00f3dulo de C no est\u00e1 disponible), tampoco est\u00e1 muy optimizada. 500 hashes por segundo es muy poco, de hecho crackear la BBDD entera nos llevar\u00eda 395610 a\u00f1os. Sin embargo, una implementaci\u00f3n optimizada para GPU deber\u00eda poder llegar sin mucho problema a un mill\u00f3n de hashes por segundo (usando por ejemplo los kernels OpenCL de hashcat) esto reduce el tiempo de b\u00fasqueda a unos 198 a\u00f1os de GPU, o unos 86700$ si us\u00e1ramos instancias de GPU de Amazon, caro desde luego, pero dentro del \u00e1mbito de lo factible.<\/p>\n<p>Si quieres hacer pruebas, la base de datos completa pesa cerca de 2,3GB y puede bajarse con el siguiente comando:<br \/>\n<tt>curl --http2 --create-dirs -o '#1#2\/#3#4' 'https:\/\/&lt;p\u00e1gina web&gt;\/db\/{0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f}{0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f}\/{0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f}{0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f}.db'<\/tt><\/p>\n<p>Por \u00faltimo, a modo de demostraci\u00f3n, os dejo los datos de la mesa electoral de Roger Junqueras, el hermano de Oriol Junqueras. El DNI lo he obtenido utilizando Google y el c\u00f3digo postal a trav\u00e9s de las p\u00e1ginas blancas. Por cierto, su fecha de nacimiento es el 10 de Octubre de 1974 \ud83d\ude09<br \/>\n<tt>COL.LEGI PUBLIC REIXAC#Pa\\xc3\\xafsos Catalans, s\/n#MONTCADA I REIXAC#2#3#0A#e026f9484a40180141abc4f1793df6d8f3da736bf15224bcb3f74d41d3319074f20898f975211c6cca722708c313c14c41<\/tt><\/p>\n<p>De toda la informaci\u00f3n de la mesa, lo \u00fanico que no tengo claro es para que sirve el \u00faltimo identificador en hexadecimal. Sospecho que pueda ser una firma para verificar la integridad de la clave pero 768 bits son muy pocos para una clave RSA y demasiados para una curva el\u00edptica, as\u00ed que no os se decir para que sirven.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>A trav\u00e9s del enlace de un amigo he acabado en una p\u00e1gina d\u00f3nde se muestra a los votantes del refer\u00e9ndum catal\u00e1n la ubicaci\u00f3n de la urna d\u00f3nde se debe votar. Como de costumbre, me ha podido la curiosidad y me he puesto a analizar como funcionaba el sistema. La verdad es que usan un sistema [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3],"tags":[63,62,64],"class_list":["post-381","post","type-post","status-publish","format-standard","hentry","category-seguridad","tag-cracking","tag-criptografia","tag-datos-personales"],"_links":{"self":[{"href":"https:\/\/klondike.es\/klog\/wp-json\/wp\/v2\/posts\/381","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/klondike.es\/klog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/klondike.es\/klog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/klondike.es\/klog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/klondike.es\/klog\/wp-json\/wp\/v2\/comments?post=381"}],"version-history":[{"count":4,"href":"https:\/\/klondike.es\/klog\/wp-json\/wp\/v2\/posts\/381\/revisions"}],"predecessor-version":[{"id":385,"href":"https:\/\/klondike.es\/klog\/wp-json\/wp\/v2\/posts\/381\/revisions\/385"}],"wp:attachment":[{"href":"https:\/\/klondike.es\/klog\/wp-json\/wp\/v2\/media?parent=381"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/klondike.es\/klog\/wp-json\/wp\/v2\/categories?post=381"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/klondike.es\/klog\/wp-json\/wp\/v2\/tags?post=381"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}