domingo, 30 de junio de 2019

Forense (VIII): Solución Reto picoCTF 2018 "Truly an Artist"

Continúo con la solución a otro de los retos de "forense" de la plataforma picoCTF 2018.

El octavo de ellos tiene el título "Truly an Artist" y, en mi opinión, presenta un nivel de dificultad muy fácil (☆☆).

Truly an Artist - Points: 200:


Su enunciado dice lo siguiente: '
Can you help us find the flag in this Meta-Material? You can also find the file in /problems/truly-an-artist_0_4f3e3848bbbfc5cfcfa404bd18b8ac96'.

Y en la pestaña 'Hints''Try looking beyond the image?' y 'Who created this?'.
Solución: se proporciona un archivo de imagen con el logotipo de picoCTF (2018.png). Por el enunciado me queda claro que la flag puede encontrarse en los metadatos de este archivo y, tanto por el título como por las pistas que se dan, que posiblemente esté en el metadato correspondiente a 'Artist'.

Abro el archivo con 'ExifToolGUI' y miro en el metadato 'Artist':
Con lo que la solución a este reto es: picoCTF{look_in_image_788a182e}.

Forense (VII): Solución Reto picoCTF 2018 "hex editor"

Solución a otro de los retos de "forense" de la plataforma picoCTF 2018.

El séptimo de ellos tiene el título "hex editor" y, en mi opinión, presenta un nivel de dificultad muy fácil (☆☆).

hex editor - Points: 150:

Su enunciado dice lo siguiente: '
This cat has a secret to teach you. You can also find the file in /problems/hex-editor_3_086632ac634f394afd301fb6a8dbadc6 on the shell server'.

Y en la pestaña 'Hints': 'What is a hex editor?', 'Maybe google knows', y se hace referencia a varios editores de texto.
Solución: se proporciona un archivo con la imagen de un gato (hex_editor.jpg). Lo abro con un editor hexadecimal y busco "pico":
Con lo que la solución a este reto es:

picoCTF{and_thats_how_u_edit_hex_kittos_8BcA67a2}.

Forense (VI): Solución Reto picoCTF 2018 "admin panel"

En este post la solución a otro de los retos de "forense" de la plataforma picoCTF 2018.

El sexto de ellos tiene el título "admin panel" y, en mi opinión, presenta un nivel de dificultad fácil (☆☆).

admin panel - Points: 150:

Su enunciado dice lo siguiente: '
We captured some traffic logging into the admin panel, can you find the password?'.

Y en la pestaña 'Hints' : 'Tools like wireshark are pretty good for analyzing pcap files'.
Solución: se proporciona un archivo de captura de paquetes de tráfico de red (data.pcap) y lo abro utilizando 'Wireshark'.

Establezco un filtro para el método "POST" de petición HTTP:
La segunda de las peticiones que se muestran contiene la bandera:
Con lo que la solución a este reto es: picoCTF{n0ts3cur3_b186631d}.

Forense (V): Solución Reto picoCTF 2018 "Recovering From the Snap"

Continúo con las soluciones a los retos de "forense" de la plataforma picoCTF 2018.

El quinto de ellos tiene el título "Recovering From the Snap" y, en mi opinión, presenta un nivel de dificultad fácil (☆☆).

Recovering From the Snap - Points: 150:

Su enunciado dice lo siguiente: '
There used to be a bunch of animals here, what did Dr. Xernon do to them?'.

Y en la pestaña 'Hints' : 'Some files have been deleted from the disk image, but are they really gone?'.
Solución: se proporciona un archivo de imagen de disco (animals.dd) y por la pista que se da está claro que se han borrado algunos ficheros.

Para resolver este reto utilizo el software 'Autopsy' y entre los ficheros borrados veo un archivo de imagen (theflag.jpg) que contiene la flag:
Con lo que la solución a este reto es: picoCTF{th3_5n4p_happ3n3d}.

viernes, 28 de junio de 2019

Criptografía (CL): Solución Reto picoCTF 2018 "eleCTRic"

Solución a otro reto de criptografía de la plataforma picoCTF 2018.

En esta ocasión se trata de un reto en el que se ve involucrado otro modo de operación, CTR ('Counter'), de los algoritmos de cifrado por bloques, y que,  en mi opinión y al igual que el reto de criptografía anteriorpresenta un nivel de dificultad alto ().

- eleCTRic - Points: 400:

Su enunciado dice lo siguiente: '
You came across a custom server that Dr Xernon's company eleCTRic Ltd uses. It seems to be storing some encrypted files. Can you get us the flag? Connect with nc 2018shell.picoctf. com 61333Source'.
Solución: Aunque por el título se puede sospechar claramente que en este reto se ve involucrado el modo de operación CTR de los algoritmos de cifrado por bloques, ésto se confirma a la vista del archivo fuente que se proporciona, ya que puedo ver que en él se cifra utilizado el criptosistema AES en ese modo.

Tal y como nos cuenta wikipedia, en el tipo de cifradores indicado anteriormente los mensajes en claro se dividen en bloques, y en el modo CTR se convierte una unidad de cifrado por bloques en una unidad de flujo de cifrado, de la siguiente manera: 
Si no lo entiendo mal, lo que se conoce como flujo de claves ('keystream') se forma cifrando en modo ECB ('Electronic Code-Book'un número aleatorio ('Nonce') combinado con un contador ('Counter'), y para obtener el texto cifrado o criptograma correspondiente se realiza XOR entre el resultado del cifrado anterior y el texto plano.

En este modo, si el valor del contador permanece constante se revela el flujo de claves ('keystream'), lo que produce como resultado la vulnerabilidad del cifrado, y, a la vista de las pistas dadas en la pestaña 'Hints' ('I have repeated myself many many many times- do not repeat yourself' y 'Do I need to say it in different words? You mustn't repeat thyself'), sospecho que esto es lo que ocurre en este reto, lo que también  confirmo a la vista del archivo fuente que se proporciona.

Dicho todo lo anterior vuelvo al reto. Me conecto al servicio, utilizo la opción para listar ficheros ('L[i]st files') y veo que hay un archivo que supuestamente contiene la bandera:
Pero, ¿cómo veo su contenido?. Voy a ver si consigo descubrir alguna forma.

Utilizo la opción para cifrar y almacenar un fichero ('E[n]crypt and store file'); se me pide: el nombre del fichero (introduzco 32 caracteres "a") y los datos o contenido del fichero (incluyo “prueba reto criptografia eleCTRic picoCTF 2018”), y se me proporciona un código de compartir (‘Share code’) codificado en base 64:
Vuelvo a utilizar la opción para listar ficheros ('L[i]st files') y veo que el fichero que acabo de cifrar se ha almacenado:
y, finalmente, utilizo la opción para descifrar un fichero ('D[e]crypt file'); se me pide el código de compartir (incluyo el que se me ha proporcionado) y se muestra el contenido en texto plano del fichero que he cifrado y almacenado:
Por tanto, para ver el contenido del fichero que supuestamente contiene la flag debo conocer su código de compartir (‘Share code’), y aquí es donde comienza el ataque.

Antes que nada, a la vista del código fuente que se proporciona y de la prueba realizada, si no me equivoco, concluyo lo siguiente:

a) El algoritmo utilizado para cifrar, tanto el nombre del fichero como su contenido, es AES.

b) El código de compartir que se asigna a un fichero depende únicamente del nombre que se le da a éste y no de su contenido.

c) El que en la prueba haya incluido 32 caracteres "a" como nombre del fichero a cifrar no ha sido casualidad, sino que lo he hecho para estar seguro de que el valor del contador no cambia. El código de compartir que se ha proporcionado para el fichero que he cifrado y almacenado es (base 64):

"zOzXO3bVKI/L6SvwADhk0szs1zt21SiPy+kr8AA4ZNKD+c4u"

En hexadecimal obtengo:

ccecd73b76d5288fcbe92bf0003864d2 ccecd73b76d5288fcbe92bf0003864d2 83f9ce2e

Y veo que el código correspondiente a los 16 primeros caracteres "a" es igual que el código correspondiente a los 16 siguientes caracteres "a", con lo que confirmo que el contador ha permanecido constante. Los últimos 4 Bytes se corresponden con la extensión del archivo (.txt).

d) Así que, básicamente, cada 16 Bytes se está haciendo XOR de los Bytes correspondientes del texto plano (nombre del archivo con la extensión) con el mismo valor.

Por tanto, para resolver este reto puedo hacer XOR del texto plano conocido (nombre del fichero con la extensión) con el texto cifrado conocido (código de compartir que se nos ha proporcionado) y obtener así el flujo de claves ('keystream').

Posteriormente sólo me queda hacer XOR del resultado obtenido en el paso anterior con el nombre de archivo que supuestamente contiene la bandera, para obtener su código de compartir, y, finamente, pedir al servicio que descifre el fichero con la flag introduciendo su código de compartir.

Para ello, creo un pequeño script en python:

import socket
from base64 import b64decode, b64encode

def seleccionar_opcion(opcion,nombre_fichero,contenido_fichero,keystream):
   while True:
      recibido=s.recv(1024).decode().strip()
      if 'Files:' in recibido:
         return recibido
      elif 'Name of file?' in recibido:
         s.send(nombre_fichero.encode())
         s.send(b'\n')
      elif 'Data?' in recibido:
         s.send(contenido_fichero.encode())
         s.send(b'\n')
      elif len(recibido)==141:
         return recibido
      elif 'Share code?' in recibido:
         s.send(keystream)
         s.send(b'\n')
      elif 'Please choose:' in recibido:
         return recibido

def cifrado(keystream, texto_plano):
    ret = bytearray()
    for i in range(0, len(texto_plano)):
        ret.append(keystream[i%len(keystream)] ^ ord(texto_plano[i]))
    return ret

s=socket.socket()
s.connect(('2018shell.picoctf.com',61333))

# Seleccionar la opcion de listar los ficheros y obtener fichero con la flag
opcion='i'
s.send(opcion.encode())
s.send(b'\n')
fichero_flag=seleccionar_opcion(opcion,'','','')[195:224]
print('[+] fichero con la flag:',fichero_flag)

# Seleccionar la opcion de cifrar fichero, incluir nombre del fichero y contenido, y obtener el codigo de compartir
opcion='n'
s.send(opcion.encode())
s.send(b'\n')
nombre_fichero='a'*32
print('[+] Fichero a cifrar (texto plano conocido):',nombre_fichero+'.txt')
contenido_fichero='prueba reto criptografia eleCTRic picoCTF 2018'
print('[+] Contenido de fihero a cifrar:',contenido_fichero)
codigo_compartir=seleccionar_opcion(opcion,nombre_fichero,contenido_fichero,'')[0:48]
print('[+] Codigo compartir fichero cifrado (texto cifrado conocido - b64):',codigo_compartir)

nombre_fichero+='.txt'
codigo_compartir=b64decode(codigo_compartir)

# Calcular keystream a partir del texto cifrado conocido y del texto plano conocido
keystream = bytearray()
for i in range(0,32):
    keystream.append(codigo_compartir[i]^ord(nombre_fichero[i]))

# Obtener el codigo compartir del fichero con la flag
codigo_compartir_flag=b64encode(cifrado(keystream,fichero_flag))
print('[+] Codigo compartir fichero con la flag - b64:',codigo_compartir_flag)

# Seleccionar la opcion de descifrar fichero, incluir codigo compartir del fichero con la flag, y obtener la solucion al reto
opcion='e'
s.send(opcion.encode())
s.send(b'\n')
flag=seleccionar_opcion(opcion,'','',codigo_compartir_flag)[0:54]
print('[+] Flag:',flag)

s.close

Lo ejecuto:
Y ya puedo ver la solución de este reto:


picoCTF{alw4ys_4lways_Always_check_int3grity_6c094576}

domingo, 23 de junio de 2019

Forense (IV): Solución Reto picoCTF 2018 "Reading Between the Eyes"

En este post continúo con las soluciones a los retos de "forense" de la plataforma picoCTF 2018.

El cuarto de ellos tiene el título "Reading Between the Eyes". En este caso, en mi opinión, se trata de un reto que presenta un nivel de dificultad fácil (☆☆), pero no entiendo muy bien porque se ha catalogado en la categoría "forense", ya que creo que encajaría mejor en el tipo de "esteganografía", aunque esta categoría no existe en esta plataforma :).

Reading Between the Eyes - Points: 150:

Su enunciado dice lo siguiente: '
Stego-Saurus hid a message for you in this image, can you retreive it?'.
Solución: se proporciona un archivo de imagen (husky.png), de un bonito husky siberiano, en el que se ha ocultado un mensaje.

Además, en la pestaña 'Hints' se indica: 'Maybe you can find an online decoder?'; por lo que para resolver este reto utilizo una herramienta 'online' mediante la cual extraigo de cada fila de la imagen los bits menos significativos de los planos 'RGB':
Con lo que la solución a este reto es: picoCTF{r34d1ng_be7w33n_7h3_by73s}.

Una magnífica herramienta 'online' de esteganografía que he descubierto recientemente, pero también podríamos haber utilizado el software de escritorio que más me gusta para resolver este tipo de retos, 'Stegsolve':
Con lo que obtendríamos el mismo resultado.

Forense (III): Solución Reto picoCTF 2018 "Desrouleaux"

En este post continúo con las soluciones a los retos de "forense" de la plataforma picoCTF 2018.

El tercero de ellos, bajo el título "Desrouleaux", es casi tan fácil como los dos anteriores ya que, en mi opinión, presenta un nivel de dificultad muy fácil (☆☆).

Desrouleaux - Points: 150:

Su enunciado dice lo siguiente: '
Our network administrator is having some trouble handling the tickets for all of of our incidents. Can you help him out by answering all the questions? Connect with nc 2018shell.picoctf. com 10493incidents.json'.
Solución: se proporciona un archivo (incidents.json), con la siguiente información:
Me conecto:
- Primera pregunta:  ¿Cuál es la dirección IP de origen más común? Si hay más de una dirección IP que sea la más común, puede indicar cualquiera de las más comunes.
Respuesta: 251.71.156.29
- Segunda pregunta:  ¿Cuántas direcciones IP de destino únicas fueron seleccionadas por la dirección IP de origen 251.71.156.29?.
Respuesta: 4
- Tercera pregunta:  ¿Cuál es el número de ips de destino únicas a las que se envía un archivo, en promedio?.  Respuesta con 2 decimales correctos?.
Respuesta: 9/8 = 1.125 = 1.12
Y una vez contestadas las tres preguntas correctamente se muestra la flag:
Con lo que la solución a este reto es: picoCTF{J4y_s0n_d3rUUUULo_a062e5f8}.

Forense (II): Solución Reto picoCTF 2018 "Forensics Warmup 2"

En este post continúo con las soluciones a los retos de "forense" de la plataforma picoCTF 2018.

El segundo de ellos, bajo el título "Forensics Warmup 2", es casi tan fácil como el primero, y para lo único que vale es para "calentamiento", ya que, en mi opinión, presenta un nivel de dificultad muy fácil (☆☆).

Forensics Warmup 2 - Points: 50:

Su enunciado dice lo siguiente: '
Hmm for some reason I can't open this PNG? Any ideas?'.
Solución: se proporciona un archivo de imagen (flag.png), pero si lo abro con un editor hexadecimal veo que en realidad es un archivo jpeg, lo que, además, también puedo comprobar de muchas otras formas, por ejemplo con algún software para detectar tipos de ficheros:
Abro el archivo jpeg y puedo ver la flag:
Con lo que la solución a este reto es: picoCTF{extensions_are_a_lie}.

Forense (I): Solución Reto picoCTF 2018 "Forensics Warmup 1"

Mientras voy finalizando los retos de criptografía de picoCTF 2018 (ya me quedan pocos :)) comparto las soluciones de desafíos de esta plataforma correspondientes a otras categorías.

En este post comienzo con las soluciones a los retos de "forense". El primero de ellos bajo el título "Forensics Warmup 1", en mi opinión, ni siquiera puede considerarse como un reto, ya que presenta un nivel de dificultad más que muy fácil (☆☆).

- Forensics Warmup 1 - Points: 50:

Su enunciado dice lo siguiente: '
Can you unzip this file for me and retreive the flag?'.
Solución: se proporciona un archivo comprimido (flag.zip), y entiendo que los únicos objetivos de este reto consisten en regalar los primeros puntos a los participantes en esta competición y, tal y como se dice en la pestaña 'Hints':'Make sure to submit the flag as picoCTF{XXXXX}', en establecer el formato en el que hay que enviar las soluciones de los desafíos.

Extraigo el archivo de imagen (flag.jpg) del archivo comprimido, lo abro y puedo ver la flag:
Con lo que la solución a este reto es: picoCTF{welcome_to_forensics}.

sábado, 22 de junio de 2019

Criptografía (CXLIX): Solución Reto picoCTF 2018 "SpyFi"

Solución a otro reto de criptografía de la plataforma picoCTF 2018.

En esta ocasión se trata de un reto en el que se ve involucrado el método de operación más sencillo, ECB ('Electronic Code-Book'), de los algoritmos de cifrado por bloques, y que,  en mi opinión, presenta un nivel de dificultad alto ().

SpyFi - Points: 300:

Su enunciado dice lo siguiente: '
James Brahm, James Bond's less-franchised cousin, has left his secure communication with HQ running, but we couldn't find a way to steal his agent identification code. Can you? Conect with nc 2018shell.picoctf. com 33893Source'.
Solución: se proporciona un archivo fuente en el que puedo ver el cifrado de un mensaje utilizando el criptosistema AES en modo ECB. El tamaño del bloque es de 16 Bytes.

Tal y como nos cuenta wikipedia, en el tipo de cifradores indicado anteriormente los mensajes en claro se dividen en bloques (en el caso de nuestro reto de 16 Bytes), y en el modo ECB cada uno de ellos es cifrado por separado utilizando la misma clave.
La desventaja de este modo es que a bloques de texto plano o en claro idénticos les corresponden bloques idénticos de texto cifrado.

Dicho lo anterior vuelvo al reto. Me conecto al servidor: se me da la bienvenida y se me solicita que introduzca mi informe de situación, y después de introducir este último se muestra un texto cifrado o criptograma:
Analizo el archivo fuente que se nos proporciona con relación al criptograma obtenido y llego a la conclusión de que el cifrado del mensaje se ha realizado de la siguiente manera:

message = """Agent,
Greetings. My situation report is as follows:
{0}
My agent identifying code is: {1}.
Down with the Soviets,
006
"""

Utilizando “/” para indicar el salto de línea:

Agent,/Greetings
72f8928a2758a3379144f3c01fb298a4
. My situation r
1527c40d73f78fd78ba96d842e6d9587
eport is as foll
d2d89cbf39636928ba9b43db8bf5e348
ows:/aaaaaaaaaaa
29cca0a3f1dc5a9ffc881c3975e0b576
aaaaaaaaaaaaaaaa
99c96c6acd5a7be8bceefe7438374c89
aaaaaaaaaaaaaaaa
99c96c6acd5a7be8bceefe7438374c89
aaaaaaaaaaaaaaaa
99c96c6acd5a7be8bceefe7438374c89
/My agent identi
5c55697e5d18d2b94fffe188b4f3f279
fying code is: x
c551f6fbef081e96daec728c670444d3
...
Como informe de situación he introducido 59 caracteres "a" con lo que:

- Veo que, efectivamente, a idénticos bloques de texto plano o en claro les corresponden idénticos textos cifrados (líneas resaltadas en color verde).

- He obtenido un texto cifrado correspondiente a un bloque (línea resaltada en color azul) que me permitirá utilizarlo como valor de referencia para realizar un ataque de fuerza bruta con objeto de obtener el primer carácter de texto en claro (el carácter desconocido "x" que figura en el texto en claro de dicha línea) del código de identificación del agente 006, que es lo que pretendo robar y, por tanto, es la solución a este reto.

Es decir, si realizo fuerza bruta sobre el último carácter ("x") de la línea resaltada en azul (voy probando con todos los posibles caracteres: a, b, c,..., z, A, B, C,..., Z, 0, 1, 2,..., 9, !...) llegará un momento en que el criptograma que obtenga para ese bloque será igual a nuestro valor de referencia, ya que, tal y como he dicho, a bloques idénticos les corresponden textos cifrados iguales, y el carácter probado será precisamente el primero del código de identificación de agente que busco.

Indico cómo funcionaría para el primer carácter del código de identificación de agente:

- Introduzco como informe de situación: aaaaaaaaaaafying code is: a

Agent,/Greetings
72f8928a2758a3379144f3c01fb298a4
. My situation r
1527c40d73f78fd78ba96d842e6d9587
eport is as foll
d2d89cbf39636928ba9b43db8bf5e348
ows:/aaaaaaaaaaa
29cca0a3f1dc5a9ffc881c3975e0b576
fying code is: a
c17da5606c552f2f750a47a9f342a75c
...
- El texto cifrado obtenido para el último bloque que se muestra no coincide con nuestro valor de referencia. Por tanto, "a" no es el primer carácter del texto en claro correspondiente al código de identificación de agente.

- Voy probando con los demás caracteres hasta que llego a "p", es decir, introduzco como informe de situación: aaaaaaaaaaafying code is: p

Agent,/Greetings
72f8928a2758a3379144f3c01fb298a4
. My situation r
1527c40d73f78fd78ba96d842e6d9587
eport is as foll
d2d89cbf39636928ba9b43db8bf5e348
ows:/aaaaaaaaaaa
29cca0a3f1dc5a9ffc881c3975e0b576
fying code is: p
c551f6fbef081e96daec728c670444d3
...
- El texto cifrado obtenido para el último bloque que se muestra coincide con nuestro valor de referencia. Por tanto, "p" es el primer carácter del texto en claro correspondiente al código de identificación de agente.

Creo un pequeño script en python para obtener este primer carácter (al final de este post pongo el script para 'crackear' completamente el código de identificación de agente). Lo ejecuto y obtengo:
Una vez obtenido el primer carácter del texto en claro, para obtener el segundo sólo tengo que introducir como informe de situación 58 caracteres "a", con objeto de calcular el nuevo valor de referencia incorporando el carácter del texto en claro hallado (primer carácter del código de identificación de agente), y continuar con el mismo procedimiento de fuerza bruta.

Explicado lo anterior, para conseguir la solución de este reto generalizo el script empleado para obtener el primer carácter, de la siguiente manera:

#!/usr/bin/env python3
import socket

charset='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~ '

encontrado=' '
flag=''
situation_report_ref='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
situation_report_car=' aaaaaaaaaaafying code is: '
n=1

while encontrado!='' and encontrado!='}':
   print('[+] Informe de situacion ...', situation_report_ref)

   s = socket.socket()
   s.connect(('2018shell.picoctf.com', 33893))

   while True:
      recibido=s.recv(448).decode().strip()
      if 'Welcome, Agent 006!' in recibido:
         print(recibido)
      elif 'Please enter your situation report:' in recibido:
         print(recibido)
         s.send((situation_report_ref).encode())
         s.send(b'\n')
      else:
         str_brute_force=recibido[256:288]
         break

   s.close

   if n>11:
      situation_report_car=' aaaaaaaaaaa'+situation_report_car[12:27]
      n=0
   else:
      n+=1

   situation_report=situation_report_car[1:27]

   for i in charset:
      s = socket.socket()
      s.connect(('2018shell.picoctf.com', 33893))

      situation_report_car=situation_report+i
      print(situation_report_car)

      encontrado=''

      while True:
          recibido=s.recv(384).decode().strip()
          if 'Welcome, Agent 006!' in recibido:
             pass
          elif 'Please enter your situation report:' in recibido:
             s.send((situation_report_car).encode())
             s.send(b'\n')
          else:
             if recibido[128:160]==str_brute_force:
                encontrado=i
                print('[+] Encontrado un caracter del codigo de identificacion de agente:', i)
                flag=flag+i
                print('[+] Flag =', flag)
             break

      if encontrado!='':
        situation_report_ref=situation_report_ref[0:59-len(flag)]
        break
      elif i==' ' and encontrado=='':
         print('[-] No se ha encontrado un caracter del codigo de identificacion de agente.')
         break

   s.close()

Lo ejecuto:
Y cuando finaliza obtengo la flag completa:

picoCTF{@g3nt6_1$_th3_c00l3$t_6081670}.