Navaja Negra 7e – Wrong file transfer

Como seguramente sabréis estos días se ha celebrado la séptima edición de Navaja Negra (https://www.navajanegra.com/) y los cabr… buenos muchachos de Ka0Labs han organizado el CTF de este año y aquí os traigo un par de writeups de las que conseguí solucionar, y si, solo un par porque menudo nivelazo de CTF, desde aquí felicitarlos por montar un CTF que ha sido divertido y a la vez un gran reto para todos.

Comencemos con una prueba de misc (aunque casi podría ser forense) del cual nos dan el siguiente enunciado:

Wrong file tranfer

75

Size always matters, gimme the flagz!!

Y un archivo pcapng, lo abrimos con wireshark y nos encontramos lo siguiente:

De un vistazo se puede ver que es una captura de USB por el protocolo y si nos fijamos en el info vemos que hay operaciones de escritura y el tipo de dispositivo SCSI lo cual nos dice que probablemente sea un disco externo o un pendrive al que se transfieren archivos.

También podemos ver que las llamadas de URB_BULK out son las únicas que contienen información así que lo primero que hice fue generar un archivo con tshark con toda esa información solamente:

tshark -r asdf.pcapng -T fields -e usb.capdata > raw.data

Ahora utilizamos xxd para convertir la información hexádecimal a bytes:

xxd -r -p  raw.data  raw.bin

Y tiramos un binwalk a ver que nos encontramos:

Vemos muchísimos Unix Path pero ese BMP del principio tiene buena pinta, lo extraemos utilizando dd:

dd if=raw.bin of=raw.bmp skip=15890 count=760592 bs=1

Y obtenemos esta imagen:

Mmmh, es curioso como parece que es solo media imágen, ¿quizás el tamaño importa como nos dijeron en el enunciado? Vamos a modificar el bmp utilizando un editor hexadecimal para cambiar el tamaño del BMP a ver que pasa.

42 4D F6 64 35 00 00 00 00 00 36 00 00 00 28 00 00 00 30 02 00 00 38 04 00 00

Esta es la cabecera del BMP de la cual nos interesa los últimos bytes que son los que especifican el tamaño del mismo, decidí quedarme con la longitud mayor dejando los bytes correspondientes de la siguiente manera:

42 4D F6 64 35 00 00 00 00 00 36 00 00 00 28 00 00 00 38 04 00 00 38 04 00 00

Guardamos y obtenemos lo siguiente:

Parece que no vamos mal, curiosamente da la impresión de que tenemos bien la cabecera y la parte final pero nos falta lo de la mitad. Quizás hayamos cortado de más al utilizar dd, vamos a quedarnos con toda la información después de la cabecera:

dd if=raw.bin of=raw.bmp skip=15890 bs=1

Y obtenemos un archivo mucho más prometedor:

Vamos a cambiar nuevamente el tamaño en la cabecera y obtenemos esto:

Y ahí podemos ver la flag: nn7e{e4sy_t0_r3c0v3r}

Aunque aquí me he ido a los pasos directos la prueba me dio muchos dolores de cabeza sobre todo porque me costo ver por qué tenía la cabeza y los pies ¡Pero no el resto! jeje

Espero os haya gustado y en cuanto pueda subiré el siguiente writeup de navajas.

Un saludo y gracias por vuestra visita!

Publicado en ctf, forense, misc, navaja negra 7e, writeups | Deja un comentario

Monitor e injection en Raspberry pi 3/zero

Saludos gente, ya sé que os tengo abandonados pero es que últimamente estoy a mil cosas a la vez, pero eso no significa que saque un poco de tiempo para trastear jeje

Precisamente intentando hacer unas pruebas (nada malo señor agente) para probar la seguridad de mi wifi me encontré con la sorpresa de que mi Pi Zero no soportaba modo monitor… RTFM como suelo decir, a veces me tengo que aplicar el cuento.

Efectivamente el chipset wireless Broadcom bcm43430a1 que traen tanto la pi 3 como la zero no soporta modo monitor con el módulo nativo … pues genial … ¿y ahora que hacemos? Unas cuantas consultas a San Google después me encontré con nexmon que, según su descripción, viene a ser un framework hecho en C para parchear el firmware de chipsets broadcom y cypress para habilitar el modo monitor y la inyección.

Pues seguís los pasos y ya está, nos vemos otro día, como siempre grac…. ¿Como? ¿Que no compila? Pues claro, ya tardaba la ley de Murphy, o lo que hace realmente divertida la informática. Resulta que por alguna razón mi recién flasheado raspbian no quería que le metiera la mano debajo del capó y se negó en rotundo a que los pasos de la gente de nexusmon en github, para mi modelo, para Debian, para la versión stretch, pues que no debía funcionar y punto. Me jodió bastante porque ha sido de las pocas veces que me he encontrado una buena documentación paso a paso y por algún motivo que no llegué a comprender (vale si, no me maté demasiado en el troubleshooting) al final no nos sirven de nada.

Pero tras unas cuantas consultas más a San Google ¡incluso llegar a la página dos de resultados! me encontré con que le kernel Re4son ya traía dicho módulo de nexmon precompilado, ¡bien!

Aquí tengo que reconocer que me acojoné bastante porque no paraban de hablar de firmware, ese software, tan tocahuevos a veces, que hace que nuestros cacharretes funcionen y que toqueteando más de la cuenta a veces nos deja con un bonito pisapapeles, pero… ¿como que firmware? ¿si el problema es un módulo del kernel que pinta el firmware? Pues nada, me asusté por no darme cuenta de que hay gente que no diferencia un kernel de un firmware y simplemente utilizaban el termino inadecuado.

Aún así no las tenía todas conmigo, el kernel de Re4son está basado en la versión 4.9.41 y yo tenía la 4.9.50, no debería haber problema, pero ¿os acordais del tal Murphy? Por esta misma razón decidí hacer un backup de la tarjeta por si acaso se llevaba el sistema por delante y, que demonios, nunca está demás backear por si las moscas.

La verdad es que las instrucciones de la web están muy bien aunque algunos pasos parecen desactualizados, por si os interesa están en inglés aquí.

Después de tanto rollo e historieta vamos a ensuciarnos las manos, comentaros que todo esto lo he realizado en una instalación limpia de Debian Stretch para la Pi Zero, debería de funcionar para otros OS pero por si las moscas avisados quedáis.

Todo esto lo haremos como root y si no sabéis como usar sudo o su os recomiendo que paréis aquí y lo busquéis primero, os estaréis metiendo en camisas de once varas si los conocimientos necesarios.

Primero montamos la partición boot, cambiad el dispositivo dev por el correspondiente en caso de que no sea el mismo:

mount /dev/mmcblk0p1 /boot

Nos vamos al directorio /usr/local/src:

cd /usr/local/src

Y nos bajamos la última versión del instalador y la descomprimimos:

wget  -O re4son-kernel_current.tar.xz https://whitedome.com.au/re4son/downloads/11299/
tar -xJf re4son-kernel_current.tar.xz

O si queremos la antiguo estable basada en el kernel 4.4:

wget -O re4son-kernel_old.tar.xz https://whitedome.com.au/re4son/downloads/12009/
tar -xJf re4son-kernel_old.tar.xz

Entramos en la carpeta y ejecutamos el instalador:

cd re4son-kernel_4*
./install.sh

El instalador nos hará algunas preguntas sobre si queremos instalar los módulos tanto de bluetooth como de wireless, lógicamente le damos que sí ya que para eso estamos haciendo todo esto ¿no?

Al finalizar la instalación … ¿ya? Pues sí, la verdad es que no tuve ningún problema durante el proceso de instalación, un buen script de bash que se ocupó de instalar, desinstalar y actualizar todo lo necesario. Así que sí, al finalizar la instalación reiniciamos y ya tendremos nuestra pi con el nuevo kernel.

Ahora vienen unos cuantos detalles que en la documentación están explicados mal o desactualizados y que os conviene saber.

Primero algo que sí está explicado es el tema del bluetooth y los sources del kernel. Re4son instala una versión modificada de bluez lo cual puede hacer que aparezcan errores al intentar actualizar el sistema ya que habrá problemas de dependencias, para solucionar esto simplemente nos vamos al instalador otra vez y desinstalamos el bluetooth:

cd /usr/local/src/re4son-kernel_4*
./install.sh -r

Y después de actualizar lo instalamos de nuevo:

./install.sh -b

Fácil, sencillo y para toda la familia. Para instalar los sources del kernel proceso es similar, llamamos al instalador pero de la siguiente manera:

cd /usr/local/src/re4son-kernel_4*
./install.sh -e

Con esto ya tendríamos todo listo para poder seguir operando con nuestra pi, compilando módulos, usando bluetooth, etc, etc pero todo esto ha comenzado por la wifi, vamos a probar el modo monitor.

Al utilizar los drivers de nexmon ya no es necesario utilizar airmon-ng, simplemente ejecutamos el siguiente comando para cambiar la interfaz a modo monitor:

nexutil -m2

Y para devolverla a modo managed:

nexutil -m0

Ahora ya podremos esnifar paquetes y utilizar el modo monitor de forma pasiva, y si, he dicho pasiva, porque después de volverme loco intentado saber porque demonios la inyección no funcionaba cuando se suponía que el módulo nuevo lo soportaba es porque realmente no estamos utilizando el módulo que debemos, por defecto se carga un módulo el cual soporta modo monitor pero no inyección (modulo original no soporta nada, modulo de nexmon soporta ambos, y este solo soporta monitor, parece que se quedo entre medias) después de hacer un locate descubrí que el módulo que quería se encontraba en la carpeta de instalación de Re4son, así que vamos a hacer el cambio y ver que pasa.

Vamos a movernos a la carpeta donde esta el nuevo módulo, si utilizasteis la misma carpeta el comando sería:

cd /usr/local/src/re4son-kernel_4.9.41-20170829/nexmon/armel

Quitamos el módulo antiguo:

rmmod brcmfmac

He insertamos el nuevo:

insmod brcmfmac.ko

Realizamos una prueba simple con aireplay-ng (podéis instalarlo de los repos de Debian):

Como veis primero hemos cambiado la interfaz a modo monitor utilizando nexutil, ha continuación confirmo que efectivamente esta en dicho modo y finalmente aireplay nos da la buena noticia de que la inyección finalmente está funcionando.

Y eso es todo por hoy, quizás me haya explayado mucho o quizás os esperabais algo más relacionado con la seguridad, pero ¿que mejor para seguridad que un cacharrete que puedes llevar en la cartera (no lo recomiendo, muy frágil jeje) y que ya no solo puede hacer de rubber ducky, realizar ataques poison tap, etc sino que ahora también permite realizar todo tipo de ataques wireless? ¡Si es que el cacharro este lo tiene todo! jajajaja

Bromas aparte, muchas gracias por vuestra visita y espero os haya gustado, saludos!

Publicado en DIY, raspberry, tools, tutorial, wireless | Deja un comentario

HackIt 2017 – Crypto 100 – 4_messages

Y aquí esta el último writeup de las pruebas que conseguí realizar durante el HackIt2017, esta vez no será forense sino cryptografía, veamos el enunciado:

_messages
crypt100

Description: We’ve captured 4 enemies’ cryptograms. What we know: 1) Enemies used Lord Playfair cryptosystem. 2) All the messages that is hidden behind the cipher texts are similar. 3) Each message has got the similar beginning – it is ‘Good evening hackit two thousand seventeen’ 4) Enemies use pretty usual method of key generation. One of the samples you can find here – https://github.com/AsenOsen/playfair ; Help us to restore the original message.

Attachment: (none)

Webpage: https://mega.nz/#!8CoSVSJT!0gkKT_wmG_h1n_YgCtivJCfC2VHN8Y4TtyNsbOJuU8Y

Hint: Flag lower case (h4ck1t{flaginlowercaseformat}).

Nos descargamos el archivo y nos encontramos un txt con el siguiente contenido:

CAPTURED_CIPHER =  LGMFTYNSKOPTCKIHDVBVGFIGPUKLERTYNSBFNSKOGTKUFHSKDQMIPSBYBYUZMBOAENFGEFRKUCDFIGZAFHPELFBKQGKWBICUDXVSFGSMMFUZDBHFKUBKYKKQKTKIFQEVUZLGDVFGACYTHQKFKDUOQHSTQCMWGBKTFHNDYBDFDVGTDSFKYSMIGOZHOKNSKDOGAQFBRKPFGTNYAHDPNYFGSDGTDNHBUCYCNKUEMUBKKAKHVTDSBFVDGTNSBHENOFSUEPCZNBDVBFSUGTNSIMLDKOFBKTGDGLFBKTQCMEZNQZAOMLFBGTFTQBMV
CAPTURED_CIPHER =  HNQBRESPSMHKBDFEUZUXMWOWSAGUARRESPXISPSMWFSVIYMADVPBZSVXVXNWQLFRPCWMCREAISCVOWTVIYIUWHSCQKBAGYSIDECMWMSQQBNWYWYISVSCIAGAKVKPAWIFNWHNUZWMGBERCNSRKCMHNCXCSDKZFZKVIYPIXVCVUZWFRIRSAUPBPOESMSSPKCOPZHIXEAWUWFRVFVZIRVWMIRWFIPYUISEPICIGQVSCBKYEOKRIXIZUWFSPUYPCMYIVUIETKRUZXIIVWFSPBPOYSMIXKVTINHIXKVSDQABMWXRFFHIXWFIKGDKU
CAPTURED_CIPHER =  EMIEDZDGLDEFNBLKSYQYMUOUPTNGNPDZDGUGDGLDUFLPPMGXCBLHPHAZAZUZINMKOAUMADXLIPHAOUVKPMTUKHDNSIGWBGPIFBVTUMCDIEUZFQMPLPDNTXNQOHBLHQYGUZEMSYUMBEZDDQODHNMHQDUDBDSNMSOHPMOGZAHASYUFDHDOXCLHLEDPDLDGHNELXKGUXLPUUFNUROPFNUUMHDUFGOGQIPWLGZTCIHDNFRRLURDHUGYSUFDGQGOARMCPUTLVONSYUGCPUFDGHLKFLDGUOHTYMEGUOHBDGAZMQZKMMNGUUFGHKNNY
CAPTURED_CIPHER =  FAAEAZBSHQHIORFKPZYZECFBZLBMEQAZBSEKBSHQYKKQPKWBAYFOVCBZBZFCQOQFSKCEEOLTPGDOFBXHPKZEADOBCQBRGOGPRYPTCEYMAEFCEYKPKQOBNTEMKBTFOWCPFCFAPZCEGBZADRKDTOFLRDTDAGQUSCKBPKSAZBDOPZYKATDKLQFOBLXGQHBSTOLBUNKELTZCYKKZIKCYKZCETAYKASERPGZIBTLKACOBYFPFYIATEKZPYKBSRESKGKTMEZQPSOPZEKTMYKBSOFNAHQKEKBSRAFKEKBAGQBCBVXFQMFKEYKOKMOIV

Nos dan una pista sobre que puede ser playfair pero por no fiarme me fui aquí para verificarlo y copie el primer mensaje, este es el resultado:

Efectivamente parece ser playfair, como no es un cifrado al que este muy acostumbrado (suele aparecer vigenere con el que no me llevo muy bien) me toco hacer algo de investigación y me encontré con esta tool que realiza un análisis de frecuencia de las letras en utilizando un archivo distat.log que en este caso contiene información sobre el idioma inglés (tengo que mirar como generarlo para el español).

Compilamos la aplicación haciendo un simple make y ya la tenemos lista. Cree 4 archivos cada uno conteniendo solo la parte cifrada para poder pasarselos a la aplicación.

Después de ver el output de la aplicación hice el siguiente script para ir obteniendo las keys, el tiempo de ejecución es bastante largo a veces ya que no siempre realiza las mismas comprobaciones:

while true; do ./playn m1 | grep -i -A 11 "GO OD EV EN IN GH AC KI TX TW OT HO US AN DS EV"; if [[ $? == 0 ]]; then break; fi ; done

Como veréis el texto no es exactamente igual ya que después de lanzarlo varias veces a mano me fije en que se añadia una X de vez en cuando, este fue el resultado:

Como podemos ver tenemos un texto que se puede leer, pero parece que la clave no sigue el formato que nos han dado en el enunciado, este formato consiste en que la clave se genera en base a una palabra, por ejemplo “COSA”, y el resto del abecedario se incluye en orden así que tendriamos: “COSABDEFGHIJKLMNPQRTUVWXYZ”. Lo lanzamos un par de veces más a ver si conseguimos algo más concreto y parece que la primera clave palabra que debemos encontrar es HACKIT, modificamos el script para que busque tanto por el texto conocido como por esta palabra para ver si efectivamente hay resultados:

while true; do ./playn m1 | grep -i -A 11 "GO OD EV EN IN GH AC KI TX TW OT HO US AN DS EV" | grep -i hackit; if [[ $? == 0 ]]; then break; fi ; done

Y obtenemos los siguiente:

Esto ya sigue el formato que queremos, pero no exactamente así que lo reordenamos:

HACKITBDEFGLMNOPQRSUVWXYZ

El texto cifrado decía lo siguiente:

GOOD EVENING HACKIT TWO THOUSAND SEVENTEEN IN THIS TINY BROCURE WE WOULD LIKE
TO DESCRIBE HOW IT IS TO BE A PLAY FAIR
CRYPTOR NO DOUBT IT IS EASY AS HECK BUT YOU GOT TO HAVE A PIECE OF PAPER ALL THE
TIME WE BET THERE IS NO CONVINIENCE NOW LETS CUT THE SHIT RESTORE THE MATRIX KEYS
FOR EACH CIPHER TEXT THEN TAKE FIRSTS IX LETTERS THEN COMBINE THEM TOGETHER AND YOU WILL GET THE FLAG

Así que nos quedamos con la primera parte y obtenemos la primera palabra, HACKIT.

Ahora que ya sabemos como funciona el proceso editamos un poco el script para que solo nos devuelva la key en los mensajes que coincidan y ver si encontramos la siguiente palabra:

for i in {1..10}; do while true; do ./playn m2 | grep -i -A 11 "GO OD EV EN IN GH AC KI TX TW OT HO US AN DS EV" | grep keysquare; if [[ $? == 0 ]]; then break; fi ; done; done

Esto nos devuelve el siguiente resultado:

En este caso vemos que el segundo grupo parece que pone “VERYIS” y en el primero podemos ver también que termina en “ISVER” y comienza con “Y”,  como la forma correcta sería “ISVERY” vamos a comprobar si es una solución valida:

while true; do ./playn m2 | grep -i -A 11 "GO OD EV EN IN GH AC KI TX TW OT HO US AN DS EV" | grep keysquare | grep "ISVERY"; if [[ $? == 0 ]]; then break; fi ; done

Y efectivamente obtenemos:

Reordenamos nuevamente y obtenemos ISVERYABCDFGHKLMNOPQTUWXZ, así que nuestra segunda palabra es “ISVERY”.

Para las dos últimas palabras realizamos el mismo proceso que para la segunda (no quiero alargar esto demasiado) y obtenemos las palabras “DANGER” y “CRYPTO” con lo cual, y según el hint, la flag final es:

h4ck1t{isverydangercrypto}

Espero os haya gustado a pesar de no haber sido mucho más que bruteforcear las claves e ir descubriendo las distintas keys.

Como siempre, un saludo y gracias por vuestra visita!

Publicado en cripto, ctf, hackit, writeups | Deja un comentario

HackIt 2017 – Forensic 200 – Angry printer

Esta fue la última prueba de forense que se nos propuso durante el Hackit y que resolví junto a mi compañero de equipo @angu, las screenshoots finales son cortesía suya 🙂

Este era el enunciado:

Angry printer
foren200

Description: Our printer has just stopped working. Maybe there are some driver issues or so. Could you help us to fix them?

Attachment: (none)

Webpage: https://mega.nz/#!VUJBAKzI!ljRk-LOHM7W1JDPBlghOuKvAsCabgqeIJ0WMRaZaGLo

Hint: One of the drivers was replaced with a strange module, is it a keylogger? Hide

Nos descargamos el archivo initrd.img-4.9.1.0-1-amd64  y vemos que es un archivo comprimido, al descomprimir nos encontramos con un backup de un initrd, creamos una carpeta donde montarlo, entramos en ella y lo montamos con el siguiente comando:

cpio -id < ../initrd.img-4.9_1.0-1-amd64

Esto nos montara el filesystem en la carpeta en la que nos encontramos, como hay bastante archivos decidí probar suerte con un grep y buscar por hackit a ver si había suerte y efectivamente:

Solamente hay un resultado en uno de los módulos del kernel, la pista no hace sino darle más peso a este hallazgo. Como en esos momentos no tenía manera de hacerle el reversing al módulo se lo pase a mi compañero @angu y este lo cargo en IDA, luego de buscar encontró lo siguiente:

Esta función parece realizar un XOR sobre la variable PATTERN utilizando como key 0x41, este es el contenido de la variable PATTERN:

Con este sencillo script de python, también cortesía de @angu, hacemos el XOR (ya que XOR de un XOR con la misma clave nos devuelve la cadena original) a la vez que convertimos los valores hexadecimales:

import binascii
pattern = binascii.unhexlify("2975222A70353A281E202C1E2E2F1E272833243C")
print ''.join(chr(ord(i)^0x41) for i in pattern)

Lo ejecutamos y obtenemos la flag: h4ck1t{i_am_on_fire}

Espero os haya gustado, como siempre, un saludo y gracias por vuestra visita!

Publicado en ctf, forense, hackit, writeups | Deja un comentario

HackIt 2017 – Forensic 100 – USB ducker

Ya sé que voy con algo de retraso en los writeups con respecto a lo que os tengo acostumbrados pero más vale tarde que nunca ¿no? Hoy os traigo un reto que ya había visto en otros CTF’s pero en este fue la primera vez que realmente me paré a hacerlo como dios manda y a lo largo de la semana he mejorado el script que use y que luego os compartiré. Comencemos con el enunciado:

USB ducker
foren100

Description: This file was captured from one of the computers at the Internet cafe. We think that the hacker was using this computer at that time. Try to get his secret documents. ( flag format is flag{…} )

Attachment: (none)

Webpage: https://mega.nz/#!NVJ1kZCR!mDxd7V0rHtMStePa-tUEHPW-SyAxQ6f1zRDCTxX8y3M

Hint: (none)

Nos bajamos el task.pcap y lo abrimos con Wireshark:

Aunque el título ya nos daba una pista está claro que estamos ante una captura de tráfico USB y no la típica de red que nos esperaríamos de un pcap. Utilizamos el filtro “usb.bDescriptorType” para quedarnos con los paquetes que nos darán información sobre los dispositivos USB:

Vemos que hay al menos dos dispositivos con el id 1.2.0 y 1.3.0. Comprobando el contenido de estos paquetes nos encontramos con una información muy valiosa:

Como veis el dispositivo 1.3.0 parece ser un teclado de apple, si buscáis por el id del vendor (1452 o 05ac)  y del producto (0221) veréis que concretamente se trata de un teclado Alumminium en su versión ISO.

Vamos a filtrar los paquetes de ese teclado en concreto:

Como podemos ver a continuación de los paquetes de información del dispositivo nos encontramos con una gran cantidad de interrupts que se corresponden con pulsaciones de teclas y todas tienen una longitud de 35 bytes. Si miramos más a fondo veremos que existe un campo llamado “Leftover Capture Data” que Wireshark no es capaz de interpretar, esta es la información que contiene las teclas pulsadas y que vamos a extraer para poder trabajar con ellas. Para hacerlo más fácil utilice tshark en lugar de Wireshark para generar un archivo con esta información en plano utilizando el siguiente comando:

tshark -r task.pcap -Y "usb.bus_id == 1 && usb.device_address == 3 && usb.transfer_type == 0x01" -T fields -e usb.capdata > captured.txt

Como veis hemos utilizado la dirección del teclado y especificado que solo nos devuelva los interrupts. Obtenemos el siguiente archivo:

00:00:1a:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:28:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:0e:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:28:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:09:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:28:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:05:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:28:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:20:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:34:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:52:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:2f:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:52:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:0f:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:52:00:00:00:00:00
00:00:00:00:00:00:00:00
02:00:00:00:00:00:00:00
02:00:20:00:00:00:00:00
02:00:00:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:52:00:00:00:00:00
00:00:00:00:00:00:00:00
02:00:00:00:00:00:00:00
02:00:2f:00:00:00:00:00
02:00:00:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:1a:00:00:00:00:00
00:00:00:00:00:00:00:00
02:00:00:00:00:00:00:00
02:00:21:00:00:00:00:00
02:00:00:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:51:00:00:00:00:00
00:00:00:00:00:00:00:00
02:00:00:00:00:00:00:00
02:00:37:00:00:00:00:00
02:00:00:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:05:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:51:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:04:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:0a:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:51:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:2f:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:08:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:51:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:06:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:0c:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:37:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:2f:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:52:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:2f:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:09:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:52:00:00:00:00:00
00:00:00:00:00:00:00:00
02:00:00:00:00:00:00:00
02:00:2f:00:00:00:00:00
02:00:00:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:0e:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:52:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:11:00:00:00:00:00
00:00:00:00:00:00:00:00
02:00:00:00:00:00:00:00
02:00:21:00:00:00:00:00
02:00:00:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:52:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:0d:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:18:00:00:00:00:00
00:00:00:00:00:00:00:00
02:00:00:00:00:00:00:00
02:00:30:00:00:00:00:00
02:00:00:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:51:00:00:00:00:00
00:00:00:00:00:00:00:00
02:00:00:00:00:00:00:00
02:00:33:00:00:00:00:00
02:00:00:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:51:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:20:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:51:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:18:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:51:00:00:00:00:00
00:00:00:00:00:00:00:00
02:00:00:00:00:00:00:00
02:00:22:00:00:00:00:00
02:00:00:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:2e:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:52:00:00:00:00:00
00:00:00:00:00:00:00:00
02:00:00:00:00:00:00:00
02:00:32:00:00:00:00:00
02:00:00:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:52:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:1c:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:52:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:23:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:52:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:36:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:34:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:51:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:13:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:51:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:05:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:51:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:24:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:51:00:00:00:00:00
00:00:00:00:00:00:00:00
02:00:00:00:00:00:00:00
02:00:22:00:00:00:00:00
02:00:00:00:00:00:00:00
00:00:00:00:00:00:00:00
02:00:00:00:00:00:00:00
02:00:24:00:00:00:00:00
02:00:00:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:52:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:07:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:52:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:27:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:52:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:0d:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:52:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:13:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:17:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:51:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:0c:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:51:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:04:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:51:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:2f:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:51:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:0e:00:00:00:00:00
00:00:00:00:00:00:00:00
02:00:00:00:00:00:00:00
02:00:26:00:00:00:00:00
02:00:00:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:52:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:2e:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:52:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:15:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:52:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:10:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:52:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:30:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:2e:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:51:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:27:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:51:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:07:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:51:00:00:00:00:00
00:00:00:00:00:00:00:00
02:00:00:00:00:00:00:00
02:00:37:00:00:00:00:00
02:00:00:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:51:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:0f:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:06:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:52:00:00:00:00:00
00:00:00:00:00:00:00:00
02:00:00:00:00:00:00:00
02:00:25:00:00:00:00:00
02:00:00:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:52:00:00:00:00:00
00:00:00:00:00:00:00:00
02:00:00:00:00:00:00:00
02:00:2d:00:00:00:00:00
02:00:00:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:52:00:00:00:00:00
00:00:00:00:00:00:00:00
02:00:00:00:00:00:00:00
02:00:2f:00:00:00:00:00
02:00:00:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:52:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:0d:00:00:00:00:00
00:00:00:00:00:00:00:00
02:00:00:00:00:00:00:00
02:00:22:00:00:00:00:00
02:00:00:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:51:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:18:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:51:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:16:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:51:00:00:00:00:00
00:00:00:00:00:00:00:00
02:00:00:00:00:00:00:00
02:00:26:00:00:00:00:00
02:00:00:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:51:00:00:00:00:00
00:00:00:00:00:00:00:00
02:00:00:00:00:00:00:00
02:00:25:00:00:00:00:00
02:00:00:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:1f:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:52:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:27:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:52:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:11:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:52:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:34:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:52:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:33:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:26:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:51:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:0b:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:51:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:21:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:51:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:30:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:51:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:1c:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:21:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:52:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:34:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:52:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:0e:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:52:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:33:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:52:00:00:00:00:00
00:00:00:00:00:00:00:00
02:00:00:00:00:00:00:00
02:00:2e:00:00:00:00:00
02:00:00:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:13:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:51:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:09:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:51:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:08:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:51:00:00:00:00:00
00:00:00:00:00:00:00:00
02:00:00:00:00:00:00:00
02:00:21:00:00:00:00:00
02:00:00:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:51:00:00:00:00:00
00:00:00:00:00:00:00:00
02:00:00:00:00:00:00:00
02:00:1e:00:00:00:00:00
02:00:00:00:00:00:00:00
00:00:00:00:00:00:00:00
02:00:00:00:00:00:00:00
02:00:30:00:00:00:00:00
02:00:00:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:52:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:1e:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:52:00:00:00:00:00
00:00:00:00:00:00:00:00
02:00:00:00:00:00:00:00
02:00:2d:00:00:00:00:00
02:00:00:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:52:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:0e:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:52:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:16:00:00:00:00:00
00:00:00:00:00:00:00:00
02:00:00:00:00:00:00:00
02:00:24:00:00:00:00:00
02:00:00:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:51:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:16:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:51:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:1f:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:51:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:06:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:51:00:00:00:00:00
00:00:00:00:00:00:00:00
02:00:00:00:00:00:00:00
02:00:22:00:00:00:00:00
02:00:00:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:14:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:52:00:00:00:00:00
00:00:00:00:00:00:00:00
02:00:00:00:00:00:00:00
02:00:21:00:00:00:00:00
02:00:00:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:52:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:37:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:52:00:00:00:00:00
00:00:00:00:00:00:00:00
02:00:00:00:00:00:00:00
02:00:1e:00:00:00:00:00
02:00:00:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:52:00:00:00:00:00
00:00:00:00:00:00:00:00
02:00:00:00:00:00:00:00
02:00:20:00:00:00:00:00
02:00:00:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:36:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:51:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:16:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:51:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:27:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:51:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:06:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:51:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:1d:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:20:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:52:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:08:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:52:00:00:00:00:00
00:00:00:00:00:00:00:00
02:00:00:00:00:00:00:00
02:00:30:00:00:00:00:00
02:00:00:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:52:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:2d:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:52:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:0c:00:00:00:00:00
00:00:00:00:00:00:00:00

Analizando un poco más esta captura podemos ver que la tecla pulsada esta situada en el tercer valor hexadecimal pero que también existe el valor 02 en algunas lineas, esto parece corresponderse con la tecla shift/mayúsculas, basándonos en esto generamos el siguiente script (después de muchas pruebas y errores):

mappings = {
        "04":["a","A"],
        "05":["b","B"],
        "06":["c","C"],
        "07":["d","D"],
        "08":["e","E"],
        "09":["f","F"],
        "0A":["g","G"],
        "0B":["h","H"],
        "0C":["i","I"],
        "0D":["j","J"],
        "0E":["k","K"],
        "0F":["l","L"],
        "10":["m","M"],
        "11":["n","N"],
        "12":["o","O"],
        "13":["p","P"],
        "14":["q","Q"],
        "15":["r","R"],
        "16":["s","S"],
        "17":["t","T"],
        "18":["u","U"],
        "19":["v","V"],
        "1A":["w","W"],
        "1B":["x","X"],
        "1C":["y","Y"],
        "1D":["z","Z"],
        "1E":["1","!"],
        "1F":["2","@"],
        "20":["3","#"],
        "21":["4","$"],
        "22":["5","%"],
        "23":["6","^"],
        "24":["7","&"],
        "25":["8","*"],
        "26":["9","("],
        "27":["0",")"],
        "28":"\n",
        "29":"ESC",
        "2A":"BKSPC",
        "2B":"  ",
        "2C":" ",
        "2D":["-","_"],
        "2E":["=","+"],
        "2F":["[","{"],
        "30":["]","}"],
        "31":["\\","|"],
        "32":"(INT 2)",
        "33":[";",":"],
        "34":[",",'"'],
        "35":["`","~"],
        "36":[",","<"],
        "37":[".",">"],
        "38":["/","?"],
        "39":"CAPSLOCK",
        "3A":"F1",
        "3B":"F2",
        "3C":"F3",
        "3D":"F4",
        "3E":"F5",
        "3F":"F6",
        "40":"F7",
        "41":"F8",
        "42":"F9",
        "43":"F10",
        "44":"F11",
        "45":"F12",
        "46":"PRTSCR",
        "47":"SCRLOCK",
        "48":"PAUSE",
        "49":"INS",
        "4A":"HOME",
        "4B":"PGUP",
        "4C":"DEL",
        "4D":"END",
        "4E":"PGDOWN",
        "4F":"RIGHT",
        "50":"LEFT",
        "51":"DOWN",
        "52":"UP",
        "53":"NUMLOCK"
        }

nums = []
keys = open('captured.txt')
for line in keys:
        nums.append(line.strip().upper())
keys.close()
output = list()
for n in nums:
    push=n.split(":")
    if push[2] == "00":
        continue
    else:
        key=push[2]
    if push[0] != "02":
        islist=mappings[key]
        if type(islist) is list:
            output.append(mappings[key][0])
        else:
            output.append(mappings[key])
    else:
        output.append(mappings[key][1])
final=dict()
empty_line=list()
final[0]=[]
counter=0
for i in output:
    if i == "\n":
        counter += 1
        final[counter]=["\n"]
    elif i == "DOWN":
        if counter < len(final):
            counter += 1
    elif i== "UP":
        if counter != 0:
            counter -= 1
    else:
        final[counter].append(i)

output=""
for x in final.keys():
    for y in final[x]:
        output+=y
print output

Y digo después de muchas pruebas y errores porque habitualmente cuando tengo visto este tipo de pruebas se limitan como mucho a meter letras, números y símbolos pero en este caso nos hemos encontrado con que también se utilizaban las flechas …. En este script no se plantean las flechas de derecha e izquierda pero por el resto debería de reconocer prácticamente todo el teclado con un layout USA.

Ejecutamos el script y obtenemos el siguiente resultado donde se puede ver la flag:

w{w$ju},,pt]=j%;9+ps&#,i
k#>bn$:6pjim0{u,h;fks!s-
flag{k3yb0ard_sn4ke_2.0}
b[[e[fuI7d[=>*(0],$1c$ce
3,ci.[%=%&k(lc*2y4!}%qz3

Espero os haya gustado este nuevo writeup, aun tengo un par más de ellos pendientes y los iré publicando poco a poco ya que estoy trabajando en algunas otras cosas que creo que os parecerán interesantes. ¡Estaros atentos!

Como siempre, gracias por vuestra visita, saludos!

Publicado en ctf, forense, hackit, writeups | Deja un comentario

HackIt 2017 – Forensic 150 – Cypherpunk’s nightmare

Este fin de semana ha sido el CTF organizado por la gente de HackIt Ucrania y os traigo unos pocos writeups de algunas pruebas que conseguí resolver. No empiezo por orden ya que esta prueba me la ha pedido bastante gente así que vamos allá, nos dan el siguiente enunciado:

Cypherpunk’s nightmare
foren150

Description: Our officers just have made cold boot attack on the suspect’s computer. Your role is to recover the content of this encrypted hard drive.

Attachment: (none)

Webpage: https://mega.nz/#!VdRAkaKT!xP7s74jwnlGmR2spg9RNaKFf5GmCGAv-pxW8aPZNkOw

Hint: (none)

Nos descargamos el archivo nightmare.zip de mega y al descomprimir nos encontramos con dos archivos:

El enunciado ya nos los decía así que no es ninguna sorpresa, tenemos una imagen de un disco cifrada en luks y un dump de la memoria del equipo del cual podremos extraer las claves de luks. Para ello vamos a probar la herramienta aeskeyfind (la web original no funciona el link así que toca utilizar un poco de google hasta conseguir los sources y compilarlo.

Le pasamos nuestro memdump y esperamos a ver que nos dice:

Como veis nos ha sacado dos posibles claves, espera … ¿dos? Aquí vino el mayor quebradero de cabeza ya que al intentar montar la imagen nos daba el siguiente error:

Y es que si os fijáis las claves que nos ha extraído aeskeyfind solamente tienen una longitud de 16, vamos a echarle un vistazo al dump con un lector hexadecimal y busquemos la primera key, al principio no vemos nada raro pero al llegar al último vemos lo siguiente:

Vemos que justo antes de la key que estábamos buscando aparece la segunda (la que he marcado en claro) y que el total de bytes esta delimitado de bytes a 0,  y que el total suman 32 bytes que era lo que buscábamos, ¿será está la key real? La metemos en un archivo con el siguiente comando:

echo "68 3C 5A 4B F8 F1 CE DF 5B 64 9C 48 2E 48 E6 39 9E 90 12 6C 33 C8 5D 9A 69 13 E6 49 30 1B 5D CF" | tr -d " " | xxd -r -p > Safe.key

Y ahora montamos utilizando el nuevo archivo de key:

sudo cryptsetup luksOpen --master-key-file Safe.key encrypted.dd safe-home

Ya sin errores, montamos la partición luks en una carpeta y vemos que hay dentro:

Y ahí tenemos nuestro archivo con la flag, lo abrimos y obtenemos la flag:

h4ck1t{Not_paranoid_enough}

En los próximos días según vaya teniendo tiempo os subiré le resto de writeups de las pruebas que conseguí.

Espero os haya gustado, saludos!

Publicado en forense, hackit, writeups | Deja un comentario

Hardening Apache

Casi dos meses sin publicar nada pero fijo que de menos no me echabais jeje y es que han sido unos tiempos muy ocupados y apenas he tenido tiempo que dedicarle al blog.

Antes de seguir dando el coñazo con la serie de Bash hoy os traigo un artículo que ha surgido a raíz de algo que me ha pasado en el trabajo y es el tema del hardening de Apache.

Hay muchos posts donde se habla de como habilitar mod_security, instalar fail2ban, etc, etc para proteger nuestro servidor pero en muchos casos se obvian ciertas configuraciones sencillas pero que aportan un gran valor a nivel de seguridad.

No he utilizado demasiado nginx pero por lo que he visto estas configuraciones deberían ser prácticamente idénticas pero, antes de tocar nada, os recomiendo que lo comprobéis en la correspondiente documentación.

Como supongo que todos utilizaréis https y redireccionaréis a todo el mundo que intente entrar por http (a fin de cuentas no queremos que a la gente que usa nuestro servidor puedan espiarlos) me voy a saltar esa parte e ir directamente al grano, como son varias opciones iré una a una explicando un poco lo que hacen, y como ya sabéis como soy no me voy a detener a explicar, por ejemplo, que es HSTS ya que está más que documentado.

Todas estas lineas de configuración debemos añadirlas al final de nuestro apache.conf al menos para aquellos que como yo utilicen la versión de Debian. Algunas opciones ya vienen así marcadas por defectos pero vamos a ponerlas de todas maneras para asegurarnos que si deciden cambiarlas no nos afecte.

Comencemos con algo tan básico como el fingerprinting del servidor web, por defecto Apache nos devolverá su nombre, versión y probablemente mucha más información que no le interesa a nadie, cambiemos este comportamiento:

ServerTokens Prod
ServerSignature Off

De esta manera en las cabeceras Apache simplemente dirá que es eso, Apache, sin dar ningún dato más.

Otra cosa que da demasiada información son los ETags, digamosle a Apache que si el documento proviene de un archivo no genere este campo:

FileETag None

Bien, con esto ya nos hemos asegurado de que nuestro servidor de cuanta menos información posible o al menos la hemos reducido considerablemente.

Otra cosa que no se suele hacer es deshabilitar el método TRACE, este método se puede utilizar en distintos vectores de ataque (si, otra vez google jeje) así que lo vamos a deshabilitar:

TraceEnable off

Otra cosa con la que tenemos que tener cuidado son los cifrados y protocolos de cifrado que nuestro servidor soporta, no todos son seguros ni mucho menos, así que vamos a decirle a nuestro servidor que solo acepte aquellos en los que confiamos:

SSLCipherSuite HIGH:!MEDIUM:!aNULL:!MD5:!RC4
SSLProtocol -ALL +TLSv1 +TLSv1.1 +TLSv1.2

Si os fijáis en la segunda linea lo que hace es rechazar todos los protocolos y luego solamente habilitar TLS y en la primera limitamos que cifrados puede utilizar el cliente para negociar la conexión.

Ahora vamos a añadir unos cuantos headers para eliminar una cantidad considerable de vectores de ataque que, aunque no os lo creáis, son tan sencillos de realizar pero que por defecto no son mitigados:

Header always append X-Frame-Options SAMEORIGIN
Header edit Set-Cookie ^(.*)$ $1;HttpOnly;Secure
Header always append X-XSS-Protection "1; mode=block"
Header always append X-Content-Type-Options nosniff
Header always set Strict-Transport-Security "max-age=63072000; includeSubdomains;"

Creo que estos headers son bastante auto explicativos así que no me detendré en ellos pero a grandes rasgos: evitamos que nuestra web pueda ser insertada en un iframe en otro servidor, ponemos todas las cookies como seguras y httponly; evitamos la ejecución de XSS si el navegador lo detecta (no todos lo soportan), evitamos que el navegador haga MIME-sniffing y, por último pero no menos importante, habilitamos HSTS.

Ahora guardamos y reiniciamos nuestro Apache para aplicar los cambios et voila, ya tenemos un servidor que da el mínimo de información a un atacante y a la vez protege el tráfico de los clientes.

Recordad que esto no es la panacea ni mucho menos, deberéis habilitar otros modulos como mod_security, configurar fail2ban, etc, etc Este artículo no pretende sustituir a los cientos de tutoriales que ya existen en internet sino servir como complemento a los mismos.

Espero os haya gustado esta breve entrada y a ver si consigo sacar más tiempo para seguir cacharreando y compartiendo más cosas divertidas, pero recordad, no todo es atacar ¡También hay que saber defenderse!

Como siempre, muchas gracias por vuestra visita, y cualquier duda o comentario, dejarmelo por aquí y os responderé en cuanto pueda.

Saludos!

Publicado en hardening, tutorial, web | 2 comentarios

Tutoriales sobre Bash Scripting III : Condicionales: if, elif, else, && y ||

En este capítulo hablaremos sobre los condicionales que tan importantes son a la hora de controlar el flujo de trabajo de nuestros scripts.

La sintaxis utilizando algo de pseudocódigo sería:

if condición
then
        echo "Me muestro si la condición es verdadera"
elif condición
then
        echo "Me muestro si la condición del primer if es falsa y la del elif es verdadera"
else
        echo "Me muestro si todas las condiciones anteriores son falsas"
fi

if condición; then echo "Me muestro si la condición es verdadera"; elif condición; then echo "Me muestro si la condición del primer if es falsa y la del elif es verdadera"; else; echo "Me muestro si todas las condiciones anteriores son falsas"; fi
condición && echo "Me muestro si la condición es verdadera"
condición || echo "Me muestro si la condición es falsa"
condición && echo "Me muestro si la condición es verdadera" || echo "Me muestro si la condición es falsa"

Como vemos la sintaxis es bastante sencilla y no muy distinta de la de otros lenguajes de programación o escripting.

Un detalle a tener en cuenta es que al then le ocurre lo mismo que al do de los loops, debe ir en la linea a continuación del if.

También se puede apreciar que el if se cierra con un fi al final de toda las instrucciones, no es necesario ponerlo antes de un else o un elif.

Veamos que es lo que substituiría a condición en el pseudocódigo anterior:

  • [ condición ]  : Este es el comando test tradicional de shell disponible en todas las shells POSIX. El comando test devuelve un exit code e if actúa en concordancia. Suele usarse para ver si un archivo/directorio existe o un número es igual a otro.
  • [[ condición ]] :Esta es una nueva variante soportada por bash, de nuevo el comando test devuelve un exit code con el cual if actúa. Entre sus opciones extendidas puede comparar si un string equivale a un expresión regular.
  • comando :Se ejecuta el comando e if actúa en función de su exit code.
  • ( comando ) :Este se ejecuta en una subshell. El comando devuelve un exit code e if actúa en base a él.  Usualmente se utiliza para limitar los efectos secundarios del comando en caso de que requiera asignación de variable u otros cambios en el entorno de la shell.
  • (( comando )) :Otra nueva variante soportada por bash utilizada para realizar operaciones ariméticas. Como resultado de la operación se genera un exit code e if actúa en consecuencia. Devuelve un exit code de 0 (True) en caso de que el resultado de la operación no sea cero.

La principal cosa que podemos ver con respecto a otras shell como sh son los modos [[ ]] y (( )), estos métodos no pertenecen a POSIX y pueden no funcionar en otras shells.

Otra diferencia con respecto a otros lenguajes de programación o escripting es la posibilidad de utilizar los exit codes de comandos para nuestras condiciones sin utilizar un if tal cual, seguramente habréis visto esto varias veces:

apt-get update && apt-get upgrade

Ahí donde lo veis eso es otro condicional:

  • && : Comprueba que el exit code sea cero.
  • || :Comprueba que el exit code sea distinto de cero.

Esto se utiliza sobre todo para encandenar comando donde queremos asegurarnos que el siguiente se ejecuta solo si el anterior fue exitoso (exit code 0). En el ejemplo anterior esto significa que si apt-get update se ejecuta correctamente entonces ejecutaremos apt-get upgrade.

Esto lo podemos combinar con la lista anterior para conseguir resultados como estos:

[ -f file.txt ] && echo "El archivo existe" || echo "El archivo no existe"

En este caso utilizaremos un condicional para comprobar si el archivo file.txt existe y en cada caso se mostrará el mensaje correspondiente.

Existen gran número de expresiones condicionales en bash, a continuación os dejo un listado:

  • -a archivo : True si el archivo existe.
  • -b archivo : True si el archivo existe y es un archivo de bloques.
  • -c archivo : True si el archivo existe y es un archivo de caracteres especiales.
  • -d archivo : True si el archivo existe y es un directorio.
  • -f archivo : True si el archivo existe y es un archivo regular.
  • -e archivo : True si el archivo existe.
  • -g archivo : True si el archivo existe y el bit set-group-id está marcado.
  • -h archivo : True si el archivo existe y es un enlace simbólico.
  • -k archivo : True si el archivo existe y el bit “sticky” esta marcado.
  • -p archivo : True si es un pipe tipo FIFO.
  • -r archivo: True si el archivo existe y se puede leer.
  • -s archivo : True si el archivo existe y su tamaño es mayor de cero.
  • -t fd : True si el file descriptor fd esta abierto y referencia a una terminal.
  • -u archivo : True si el archivo existe y el bit set-user-id esta marcado.
  • -w archivo : True si el archivo existe y se puede escribir.
  • -x archivo : True si el archivo existe y es ejecutable.
  • -G archivo : True si el archivo existe y pertenece al id de grupo en uso.
  • -L archivo : True si el archivo existe y es un enlace simbólico.
  • -N archivo : True si el archivo existe y fue modificado desde la última vez que fue leído.
  • -O archivo : True si el archivo existe y pertenece al usuario en uso.
  • -S archivo : True si el archivo existe y es un socket.
  • archivo1 -ef archivo2 : True si archivo1 y archivo2 hacen referencia al mismo dispositivo e inode.
  • archivo1 -nt archivo2 : True si archivo1 es más nuevo que archivo2 o si archivo1 existe pero archivo2 no.
  • archivo1 -ot archivo2 : True si archivo1 es mas viejo que archivo2 o si archivo2 existe pero archivo1 no.
  • -o nombreopt : True si la opción de shell nombreopt esta activada.
  • -v variable : True si la variable de shell  existe.
  • -R variable : True si la variable existe y es una referencia por nombre.
  • -z string : True si la longitud de string es cero.
  • -n string: True si la longitud de string es distinta de cero.

Cortita ¿verdad? ¡Pero si aun nos faltan las opciones para los strings y aritmética!

Comencemos con los strings:

  • string1 == string2  y string1 = string2 : True si los strings son iguales. El = se debe usar con el comando test conforme a POSIX.
  • string1 != string2 : True si los strings no son iguales.
  • string1 < string2 : True si la longitud de string1 es menor a string2.
  • string1 > string2 : True si la longitud de string1 es mayor a string2.

Y por último los operadores aritméticos binarios, que siguen la sintaxis arg1 OP arg2, donde los args pueden ser enteros positivos o negativos y OP es uno de los siguientes:

  • -eq : Igual.
  • -ne : No igual.
  • -lt : Menor que.
  • -le : Menor o igual que.
  • -gt : Mayor que.
  • -ge : Mayor o igual que.

Puede parecer que son muchísimas opciones para acordarse de todas pero como con todo o acostumbraréis a utilizar las más comunes muy rápidamente.

Espero os haya gustado este nuevo post de la serie sobre bash scripting y cualquier duda o comentario no dudéis en dejar un comentario.

Como siempre, gracias por vuestra visita, saludos!

Publicado en bash, tutorial | 2 comentarios

Google CTF 2017 – Mindreader

Este fin de semana fue el Google CTF 2017 donde Shellwarp nos clasificamos en un modesto 296º puesto jajaja Y es que el CTF de google no es ninguna broma, al menos puedo decir que este año hemos resuelto una de las pruebas cuyo writeup os traigo hoy.

Este era el enunciado:

Can you read my mind?

Challenge running at https://mindreader.web.ctfcompetition.com/

Pues vaya, no nos dice mucho. Veamos la web:

Mmm, pues no ha mejorado mucho la cosa, veamos el source:

Pues vaya por dios, muchas pistas no nos han dado. Veamos, tenemos un form que nos pregunta que queremos leer, probemos a meter algo aleatorio:

Archivo no encontrado, ¿sera un LFI? Probamos el típico /etc/passwd:

¡Bien! ¿Pero donde demonios estará la flag? Después de probar todos los archivos que se nos ocurren vemos que es un Debian 8 pero no podemos ver ni los logs ni los archivos de configuración, el .bashrc de root no nos dice nada …. Probamos a abrir /proc/version para ver que nos dice y:

Por fin algo distinto, parece que proc no nos permite leerlo ¿nos hará falta para encontrar la flag?

Entonces un compañero me comenta que las pruebas de web que ha mirado estaban hechas en python, así que empezamos a probar y nos encontramos con el archivo main.py:

Aquí había cambiado a curl para poder ver los archivos bien ya que en chrome los saltos de linea no aparecían.

El código nos dice que la flag está oculta en una variable de entorno llamada FLAG y que hay un filtro para que no podamos acceder a determinados sitios, entre ellos proc, el cual nos ayudaría a leer las variables de entorno.

Pero ¿hay otra manera de llegar a proc? En /dev existe un symlink a /proc/self/fd vamos a probar bajando un nivel y pidiendo environ que nos daría las variables de entorno:

¡Et voila! Ahí vemos las variables de entorno y con ella la flag:

CTF{ee02d9243ed6dfcf83b8d520af8502e1}

Decir que aquí pueda parecer que lo sacamos super fácil pero fueron horas de prueba y error, intentar otras pruebas, etc.

Espero os haya gustado y como siempre, gracias por vuestra visita.

Saludos!

Publicado en google ctf 2017, python, web, writeups | Deja un comentario

Follow the white rabbit CTF – Elliot “knows” everything

Nuevamente os traigo un writeup de una prueba que han hecho los conejos, en este caso viene de la mano de @belane.

Nos vamos a http://challenge.followthewhiterabbit.es:2345/ y nos encontramos con esto:

 Vale, tenemos 6 imagenes, ¿estego quizás? Veamos el source:

Vale, parece que hay otra imagen comentada. Vamos a descargarlas todas a ver si hay algo interesante:

for i in $(curl -s http://challenge.followthewhiterabbit.es:2345/ | egrep -o "<img src=[^>]*>" | sed 's/<img src=\"\([^"]*\).*/\1/g'); do wget http://challenge.followthewhiterabbit.es:2345/$i; done

Como todas están en png vamos a ver primero si hay algo raro en alguna de ellas, para ello utilizaremos pngcheck, una utilidad que comprueba que los png no tengan errores:

pngcheck *.png

Nos encontramos con esto:

Parece que solo una ha fallado, veamos que nos dice binwalk:

binwalk mr_2617.png

Interesante, tenemos un archivo zip, vamos a extraerlo utilizando dd (podríamos sacarlo con binwalk pasándole -e pero vamos a aprender un poco):

dd if=mr_2617.png of=output.zip bs=1 skip=1818192

Le decimos a dd que utilice como medida un byte y que se salte los 1818192 primeros bytes para que empiece a leer desde donde binwalk nos dice que empieza el zip. En caso de que hubiera mas información después del zip podríamos utilizar la opción count para extraer un número de bytes determinado (la diferencia entre el byte donde termina el zip y el byte donde comienza).

Intentamos descomprimir el archivo:

unzip output.zip

o 

7z x output.zip

Yo suelo preferir la opción de 7z ya que reconoce el tipo de compresión y te sirve para descomprimir diversos tipos de fichero con una sola herramienta.

El archivo tiene contraseña, mmm, ¿donde estará?. Vamos a empezar con exiftool y la imagen que contenía el zip a ver que nos dice:

Espera, ¿es eso binario? Vamos a probar a decodificarlo en http://www.asciitohex.com/:

Pues tiene toda la pinta, utilizamos “P4ssw0Rd_F1le.HL” como password y obtenemos el archivo que antes estaba comprimido, lo leemos y obtenemos la flag:

fwhibbit{rabbit-flag-1201dc1f15046f6e62f3eb338c92a}

Como nota final decir que esta solución no era la esperada y fue debido a un pequeño olvido ya que la password no debería de aparecer en plano sino que tendríamos que leerla de la imágen directamente.

Aquí podéis leer el writeup de David donde la resuelve de la forma en que la prueba estaba realmente diseñada.

Espero os haya gustado, como siempre, gracias por vuestra visita, saludos!

Publicado en ctf, estego, fwhibbit-ctf, web, writeups | Deja un comentario