Solución al challenge #1 (pre-quals): "7019 AES Bit-Flipping Attack" [Swiss Cyber Storm 3 CarGame Challenge].- ================================================================================ by RoMaNSoFt [8.Nov.2010] // Team "int3pids" // Nos dan este ticket: B60086CD1E68CEF25BC1BEC429D8F3C01D45F0196331DA5012B99067A25463A493CCBF690FD88F85 0BD5273C5A7D72B6 Y una web para validarlo (http://glocken.hacking-lab.com/login6). Probamos a ir modificando bytes del ticket. Si dividimos en "semibloques" de 8 bytes (16 digitos) esto es lo que obtengo al modificar un byte en cada uno: B60086CD1E68CEF2 -> Semibloque 1 -> Ticket invalid: format error 5BC1BEC429D8F3C0 -> Semibloque 2 -> Ticket invalid: format error 1D45F0196331DA50 -> Semibloque 3 -> Ticket invalid: expired on 20101011 12B99067A25463A4 -> Semibloque 4 -> ¡es posible modificar la fecha de expira- ción! 93CCBF690FD88F85 -> Semibloque 5 -> Ticket invalid 0BD5273C5A7D72B6 -> Semibloque 6 -> Ticket invalid Al decirnos que se trata de AES realmente los bloques son de 16 bytes (128 bits) por lo que realmente tenemos: - bloque 1 -> format err - bloque 2 -> se puede manipular sin que de error de formato (¡e incluso alterar la fecha de expiración!) - bloque 3 -> invalid Una posible solución se obtiene al modificar el semibloque 4 (bloque 2): *12*B99067A25463A4 -> *13*B99067A25463A4 Es decir, el ticket quedaría: B60086CD1E68CEF25BC1BEC429D8F3C01D45F0196331DA5013B99067A25463A493CCBF690FD88F85 0BD5273C5A7D72B6 Lo validamos: https://glocken.hacking-lab.com/12001/login_case6/login6/controller?action=ticke tlogin&ticket=B60086CD1E68CEF25BC1BEC429D8F3C01D45F0196331DA5013B99067A25463A493 CCBF690FD88F850BD5273C5A7D72B6&login=Login Y obtengo: "Hello hacker10 (email: ?R!????Sf??Z?). You've logged-in successfully Ticket valid until: 30101011 Solution code: X678RWER_HAXXOR" ¡Eureka! :) Si seguimos modificando bytes, vemos la correspondencia con la fecha de modifi- cación: 13B99067A25463A4 3 0 1 0 1 0 1 1 Luego podríamos haber alterado otros dígitos (en nuestro caso hemos modifido el primer dígito del año). Vale, ya está solucionado (y además nos hemos fijado que el email tiene una lon- gitud de 16 bytes, lo anotamos). Pero hay que ver qué modo es... Para ello hace- mos algunas pruebas más con lo que vemos: - al alterar la fecha de expiración, el email se corrompe: 00000320 3F 52 21 3F 3F 3F 3F 53 13 08 66 3F 3F 5A 10 3F ?R!????S..f??Z.? - si modificamos algun bit de semibloque 3 vemos que el email cambia también por completo: 00000320 7E 3F 5C 6F 3F 3F 3F 3F 7C 6A 3F 02 3F 3F 3F 3F ~?\o????|j?.???? 00000320 3F 3F 3F 3F 59 3F 08 15 3F 3F 3F 3F 0F 3F 3F 3F ????Y?..????.??? Nos dicen que tienen que existir los campos: - username - email - expiracion Si analizamos los modos posibles (http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation) y vemos cómo afecta la modificación de un bit: - ECB (Electronic codebook) Bit de bloque n -> Afecta a todo el bloque n No se está usando porque entonces se corromperia todo el campo de fecha, no se podria modificar bit a bit. - OFB (Output feedback) Bit de bloque n -> Afecta a bit bloque n No se está usando porque entonces no saldría el email corrupto, se modificaría solo la fecha limpiamente. - CBC (Cipher-block chaining) Bit de bloque n -> Afecta a todo el bloque n y al bit de bloque n+1 A priori podría ser y explicaría que el email salga corrupto (si el email está en bloque n y la fecha en n+1) - PCBC (Propagating cipher-block chaining) Bit de bloque n -> Afecta a todos los bloques n, n+1, etc No se está usando porque no puedo modificar un bit suelto. - CFB (Cipher feedback) -> Es el gráfico que se muestra en el enunciado (¿coin- cidencia?) Bit de bloque n -> Afecta a bit bloque n y a todo el bloque n+1 A priori podría ser y explicaría que el email salga corrupto (si el email está en el bloque n+1 y la fecha en el n) Entonces tenemos 2 posible soluciones: CBC y CFB. ¿Son ambas correctas? Formulemos una primera hipótesis: supongamos que es CFB (que además es lo que muestra el diagrama del enunciado). Entonces deberíamos tener: - bloque 2: "expiration date" (para poder modificarlo bit a bit, o en nuestro caso, byte a byte) - bloque 3: "email" (para que se corrompa al hacer la operación anterior) Además sabemos que el email son 16 bytes (justo todo el bloque) así que probamos a modificar un byte cualquiera del bloque 3. Si la hipótesis fuera correcta (CFB) deberíamos poder modificar el email. Sin embargo, al hacer la prueba obtenemos un: "Ticket invalid". Luego nuestra hipótesis NO era correcta. Supongamos entonces que se trata de CBC. Los bloques debería ser: - bloque 3: "expiration date" (al modificar un byte en el bloque 2 del ticket lo estamos cambiando en el bloque 3 del token sin cifrar) - bloque 2: "email" (se corrompe al realizar la operación anterior luego debe estar en el bloque siguiente) Al modificar un byte en el bloque 3 veíamos antes que obteníamos un "Ticket in- valid". Es coherente porque nos estamos cargando TODO el bloque 3, esto es, estamos corrompiendo la "expiration date". Además, podemos hacer una prueba más: modificar un dígito de la fecha intentando salirnos del rango numérico. Para ello, modificamos el mismo byte de la solución (semibloque 4, es decir, bloque 2): *12*B99067A25463A4 -> *52*B99067A25463A4 Si lo intentamos validar obtenemos: "Ticket invalid". Esto es coherente con la prueba de modificar un byte del bloque 3, que recordemos, corrompía la fecha obteniendo el mismo mensaje. Conclusión: se trata de CBC. Por último, trataremos de construir el layout del token sin cifrar, lo más exacto posible. Sabemos que probablemente el campo "username" tenga una longitud de 8 bytes (en la solución obtuvimos "hacker10") pero no sabemos ubicarlo. Para ello, modificaremos un byte del semibloque 3 (bloque 2). Vemos que se sigue mostrando el mismo username: "hacker10". Luego el "username" debe estar forzo- samente en el bloque 1. Pero ¿donde exactamente? ¿Semibloque 1 o 2? No lo pode- mos saber puesto que si modificamos un byte cualquiera del bloque 1 se corrompe este por completo. Luego el layout final que podemos deducir es: - bloque 1: "username" (8 bytes -probable- o más, no sabemos su situación exacta) - bloque 2: "email" (16 bytes, ocupa el bloque completo) - bloque 3: "expiration date" (8 bytes, exactamente al final del bloque) ===================================================================[ E O F ]===